diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java index 84e3bfa..2fad899c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentApp.java
@@ -6,6 +6,7 @@ import android.os.Handler; +import org.chromium.content_public.browser.WebContents; import org.chromium.payments.mojom.PaymentMethodData; import java.util.ArrayList; @@ -24,6 +25,7 @@ * @see https://w3c.github.io/webpayments-payment-apps-api/ */ public class ServiceWorkerPaymentApp implements PaymentApp { + private final WebContents mWebContents; private final ServiceWorkerPaymentAppBridge.Manifest mManifest; private final Set<String> mMethodNames; @@ -32,9 +34,12 @@ * * @see https://w3c.github.io/webpayments-payment-apps-api/#payment-app-manifest * + * @param webContents The web contents where PaymentRequest was invoked. * @param manifest A manifest that describes this payment app. */ - public ServiceWorkerPaymentApp(ServiceWorkerPaymentAppBridge.Manifest manifest) { + public ServiceWorkerPaymentApp( + WebContents webContents, ServiceWorkerPaymentAppBridge.Manifest manifest) { + mWebContents = webContents; mManifest = manifest; mMethodNames = new HashSet<>(); @@ -51,7 +56,8 @@ new ArrayList<PaymentInstrument>(); for (ServiceWorkerPaymentAppBridge.Option option : mManifest.options) { - instruments.add(new ServiceWorkerPaymentInstrument(mManifest.scopeUrl, option)); + instruments.add(new ServiceWorkerPaymentInstrument( + mWebContents, mManifest.registrationId, option)); } new Handler().post(new Runnable() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java index 46cf672f..a67cd751 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java
@@ -7,7 +7,6 @@ import android.content.Context; import android.graphics.drawable.Drawable; -import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.content_public.browser.WebContents; @@ -15,7 +14,7 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map; +import java.util.Set; /** * Native bridge for interacting with service worker based payment apps. @@ -33,11 +32,11 @@ */ public static class Manifest { /** - * The scope url of the service worker. + * The registration ID of the service worker. * * This can be used to identify a service worker based payment app. */ - public String scopeUrl; + public long registrationId; public String label; public Drawable icon; public List<Option> options = new ArrayList<>(); @@ -56,50 +55,33 @@ public List<String> enabledMethods = new ArrayList<>(); } - /** - * Fetch all the installed service worker app manifests. - * - * This method is protected so that it can be overridden by tests. - * - * @return The installed service worker app manifests. - */ - @VisibleForTesting - protected List<Manifest> getAllAppManifests() { - return nativeGetAllAppManifests(); - } - @Override public void create(Context context, WebContents webContents, PaymentAppFactory.PaymentAppCreatedCallback callback) { - List<Manifest> manifests = getAllAppManifests(); - for (int i = 0; i < manifests.size(); i++) { - callback.onPaymentAppCreated(new ServiceWorkerPaymentApp(manifests.get(i))); - } - callback.onAllPaymentAppsCreated(); + nativeGetAllAppManifests(webContents, callback); } /** * Invoke a payment app with a given option and matching method data. + * + * @param webContents The web contents that invoked PaymentRequest. + * @param registrationId The service worker registration ID of the Payment App. + * @param optionId The ID of the PaymentOption that was selected by the user. + * @param methodData The PaymentMethodData objects that are relevant for this payment app. */ - public void invokePaymentapp( - String scopeUrl, String optionId, Map<String, PaymentMethodData> methodData) { - nativeInvokePaymentApp(scopeUrl, optionId, methodData); + public static void invokePaymentApp(WebContents webContents, long registrationId, + String optionId, Set<PaymentMethodData> methodData) { + nativeInvokePaymentApp(webContents, registrationId, optionId, + methodData.toArray(new PaymentMethodData[0])); } @CalledByNative - private static List<Manifest> createManifestList() { - return new ArrayList<Manifest>(); - } - - @CalledByNative - private static Manifest createAndAddManifest( - List<Manifest> manifestList, String scopeUrl, String label, String icon) { + private static Manifest createManifest(long registrationId, String label, String icon) { Manifest manifest = new Manifest(); - manifest.scopeUrl = scopeUrl; + manifest.registrationId = registrationId; manifest.label = label; // TODO(tommyt): crbug.com/669876. Handle icons. manifest.icon = null; - manifestList.add(manifest); return manifest; } @@ -120,7 +102,26 @@ option.enabledMethods.add(enabledMethod); } - private static native List<Manifest> nativeGetAllAppManifests(); - private static native void nativeInvokePaymentApp( - String scopeUrl, String optionId, Object methodDataMap); + @CalledByNative + private static void onGotManifest(Manifest manifest, WebContents webContents, Object callback) { + assert callback instanceof PaymentAppFactory.PaymentAppCreatedCallback; + ((PaymentAppFactory.PaymentAppCreatedCallback) callback) + .onPaymentAppCreated(new ServiceWorkerPaymentApp(webContents, manifest)); + } + + @CalledByNative + private static void onGotAllManifests(Object callback) { + assert callback instanceof PaymentAppFactory.PaymentAppCreatedCallback; + ((PaymentAppFactory.PaymentAppCreatedCallback) callback).onAllPaymentAppsCreated(); + } + + /* + * TODO(tommyt): crbug.com/505554. Change the |callback| parameter below to + * be of type PaymentAppFactory.PaymentAppCreatedCallback, once this JNI bug + * has been resolved. + */ + private static native void nativeGetAllAppManifests(WebContents webContents, Object callback); + + private static native void nativeInvokePaymentApp(WebContents webContents, long registrationId, + String optionId, PaymentMethodData[] methodData); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java index 5dd4af9d..f0f9761 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentInstrument.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.payments; +import org.chromium.content_public.browser.WebContents; import org.chromium.payments.mojom.PaymentItem; import org.chromium.payments.mojom.PaymentMethodData; @@ -22,6 +23,8 @@ * @see https://w3c.github.io/webpayments-payment-apps-api/ */ public class ServiceWorkerPaymentInstrument extends PaymentInstrument { + private final WebContents mWebContents; + private final long mAppRegistrationId; private final ServiceWorkerPaymentAppBridge.Option mOption; private final Set<String> mMethodNames; @@ -31,12 +34,16 @@ * * @see https://w3c.github.io/webpayments-payment-apps-api/#payment-app-options * - * @param scopeUrl The scope url of the corresponding service worker payment app. - * @param option A payment app option from the payment app. + * @param webContents The web contents where PaymentRequest was invoked. + * @param appRegistrationId The registration id of the corresponding service worker payment app. + * @param option A payment app option from the payment app. */ - public ServiceWorkerPaymentInstrument(String scopeUrl, + public ServiceWorkerPaymentInstrument(WebContents webContents, long appRegistrationId, ServiceWorkerPaymentAppBridge.Option option) { - super(scopeUrl + "#" + option.id, option.label, null /* icon */, option.icon); + super(Long.toString(appRegistrationId) + "#" + option.id, option.label, null /* icon */, + option.icon); + mWebContents = webContents; + mAppRegistrationId = appRegistrationId; mOption = option; mMethodNames = new HashSet<String>(option.enabledMethods); @@ -51,8 +58,8 @@ public void invokePaymentApp(String merchantName, String origin, PaymentItem total, List<PaymentItem> cart, Map<String, PaymentMethodData> methodData, InstrumentDetailsCallback callback) { - // TODO(tommyt): crbug.com/669876. Implement this for use with Service Worker Payment Apps. - callback.onInstrumentDetailsError(); + ServiceWorkerPaymentAppBridge.invokePaymentApp( + mWebContents, mAppRegistrationId, mOption.id, new HashSet<>(methodData.values())); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java index c1657df3..e2efac1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java
@@ -4,12 +4,13 @@ package org.chromium.chrome.browser.payments; +import android.content.Context; import android.support.test.filters.MediumTest; import org.chromium.base.test.util.Feature; +import org.chromium.content_public.browser.WebContents; import java.util.Arrays; -import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -31,19 +32,20 @@ } /** - * Installs a service worker based payment app for testing. + * Installs a mock service worker based payment app for testing. * * @param optionPresence Whether the manifest has any payment options. Either NO_OPTIONS * ONE_OPTION or TWO_OPTIONS */ - private void installServiceWorkerPaymentApp(final int instrumentPresence) { + private void installMockServiceWorkerPaymentApp(final int instrumentPresence) { PaymentAppFactory.getInstance().addAdditionalFactory( - new ServiceWorkerPaymentAppBridge() { + new PaymentAppFactory.PaymentAppFactoryAddition() { @Override - public List<Manifest> getAllAppManifests() { + public void create(Context context, WebContents webContents, + PaymentAppFactory.PaymentAppCreatedCallback callback) { ServiceWorkerPaymentAppBridge.Manifest testManifest = new ServiceWorkerPaymentAppBridge.Manifest(); - testManifest.scopeUrl = "https://bobpay.com/app"; + testManifest.registrationId = 0; testManifest.label = "BobPay"; if (instrumentPresence != NO_OPTIONS) { @@ -66,7 +68,9 @@ testManifest.options.add(testOption); } - return Arrays.asList(testManifest); + callback.onPaymentAppCreated( + new ServiceWorkerPaymentApp(webContents, testManifest)); + callback.onAllPaymentAppsCreated(); } }); } @@ -79,7 +83,7 @@ @Feature({"Payments"}) public void testNoOptions() throws InterruptedException, ExecutionException, TimeoutException { - installServiceWorkerPaymentApp(NO_OPTIONS); + installMockServiceWorkerPaymentApp(NO_OPTIONS); openPageAndClickBuyAndWait(mShowFailed); expectResultContains( new String[]{"show() rejected", "The payment method is not supported"}); @@ -89,7 +93,7 @@ @Feature({"Payments"}) public void testOneOption() throws InterruptedException, ExecutionException, TimeoutException { - installServiceWorkerPaymentApp(ONE_OPTION); + installMockServiceWorkerPaymentApp(ONE_OPTION); triggerUIAndWait(mReadyForInput); // TODO(tommyt): crbug.com/669876. Expand this test as we implement more // service worker based payment app functionality. @@ -99,7 +103,7 @@ @Feature({"Payments"}) public void testTwoOptions() throws InterruptedException, ExecutionException, TimeoutException { - installServiceWorkerPaymentApp(TWO_OPTIONS); + installMockServiceWorkerPaymentApp(TWO_OPTIONS); triggerUIAndWait(mReadyForInput); // TODO(tommyt): crbug.com/669876. Expand this test as we implement more // service worker based payment app functionality.
diff --git a/chrome/browser/android/payments/service_worker_payment_app_bridge.cc b/chrome/browser/android/payments/service_worker_payment_app_bridge.cc index 3421925..9ab20a3 100644 --- a/chrome/browser/android/payments/service_worker_payment_app_bridge.cc +++ b/chrome/browser/android/payments/service_worker_payment_app_bridge.cc
@@ -8,34 +8,35 @@ #include "base/android/scoped_java_ref.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/payments/payment_app.mojom.h" -#include "content/public/browser/service_worker_context.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/payment_app_context.h" #include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" #include "jni/ServiceWorkerPaymentAppBridge_jni.h" +using base::android::AttachCurrentThread; using base::android::ConvertUTF8ToJavaString; using base::android::JavaParamRef; +using base::android::JavaRef; +using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; -static ScopedJavaLocalRef<jobject> GetAllAppManifests( - JNIEnv* env, - const JavaParamRef<jclass>& jcaller) { - // TODO(tommyt): crbug.com/669876. Initialise the following two variables. - // At the moment, they are empty, so this function will return an empty - // list of manifests. We need to hook this function up to the service worker - // payment apps. - std::string scope_url; - std::vector<payments::mojom::PaymentAppManifestPtr> manifests; +namespace { - ScopedJavaLocalRef<jobject> java_manifests = - Java_ServiceWorkerPaymentAppBridge_createManifestList(env); - for (const auto& manifest : manifests) { +void OnGotAllManifests(const JavaRef<jobject>& jweb_contents, + const JavaRef<jobject>& jcallback, + content::PaymentAppContext::Manifests manifests) { + JNIEnv* env = AttachCurrentThread(); + + for (const auto& entry : manifests) { ScopedJavaLocalRef<jobject> java_manifest = - Java_ServiceWorkerPaymentAppBridge_createAndAddManifest( - env, java_manifests, ConvertUTF8ToJavaString(env, scope_url), - ConvertUTF8ToJavaString(env, manifest->name), - manifest->icon ? ConvertUTF8ToJavaString(env, *manifest->icon) - : nullptr); - for (const auto& option : manifest->options) { + Java_ServiceWorkerPaymentAppBridge_createManifest( + env, entry.first, ConvertUTF8ToJavaString(env, entry.second->name), + entry.second->icon + ? ConvertUTF8ToJavaString(env, *entry.second->icon) + : nullptr); + for (const auto& option : entry.second->options) { ScopedJavaLocalRef<jobject> java_option = Java_ServiceWorkerPaymentAppBridge_createAndAddOption( env, java_manifest, ConvertUTF8ToJavaString(env, option->id), @@ -47,16 +48,45 @@ env, java_option, ConvertUTF8ToJavaString(env, enabled_method)); } } + + Java_ServiceWorkerPaymentAppBridge_onGotManifest(env, java_manifest, + jweb_contents, jcallback); } - return java_manifests; + Java_ServiceWorkerPaymentAppBridge_onGotAllManifests(env, jcallback); +} + +} // namespace + +static void GetAllAppManifests(JNIEnv* env, + const JavaParamRef<jclass>& jcaller, + const JavaParamRef<jobject>& jweb_contents, + const JavaParamRef<jobject>& jcallback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + + content::BrowserContext* browser_context = web_contents->GetBrowserContext(); + + content::StoragePartition* storage_partition = + content::BrowserContext::GetDefaultStoragePartition(browser_context); + + content::PaymentAppContext* payment_app_context = + storage_partition->GetPaymentAppContext(); + + payment_app_context->GetAllManifests(base::Bind( + &OnGotAllManifests, ScopedJavaGlobalRef<jobject>(env, jweb_contents), + ScopedJavaGlobalRef<jobject>(env, jcallback))); } static void InvokePaymentApp(JNIEnv* env, const JavaParamRef<jclass>& jcaller, - const JavaParamRef<jstring>& scopeUrl, - const JavaParamRef<jstring>& optionId, - const JavaParamRef<jobject>& methodDataMap) { + const JavaParamRef<jobject>& jweb_contents, + jlong registration_id, + const JavaParamRef<jstring>& joption_id, + const JavaParamRef<jobjectArray>& jmethod_data) { + // TODO(tommyt): crbug.com/669876. Implement this NOTIMPLEMENTED(); }
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc index fdd1961..b2820437 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -240,6 +240,9 @@ override { return nullptr; } + content::PaymentAppContext* GetPaymentAppContext() override { + return nullptr; + } content::HostZoomMap* GetHostZoomMap() override { return nullptr; } content::HostZoomLevelContext* GetHostZoomLevelContext() override { return nullptr;
diff --git a/chrome/browser/chromeos/arc/arc_service_launcher.cc b/chrome/browser/chromeos/arc/arc_service_launcher.cc index 758e6d5..ef22e198 100644 --- a/chrome/browser/chromeos/arc/arc_service_launcher.cc +++ b/chrome/browser/chromeos/arc/arc_service_launcher.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/bind.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_service.h" @@ -25,6 +26,8 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "components/arc/arc_service_manager.h" +#include "components/arc/arc_session.h" +#include "components/arc/arc_session_runner.h" #include "components/arc/audio/arc_audio_bridge.h" #include "components/arc/bluetooth/arc_bluetooth_bridge.h" #include "components/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h" @@ -78,7 +81,9 @@ // Creates ArcSessionManager at first. arc_session_manager_ = - base::MakeUnique<ArcSessionManager>(arc_bridge_service); + base::MakeUnique<ArcSessionManager>(base::MakeUnique<ArcSessionRunner>( + base::Bind(ArcSession::Create, arc_bridge_service, + arc_service_manager_->blocking_task_runner()))); // List in lexicographical order. arc_service_manager_->AddService(
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.cc b/chrome/browser/chromeos/arc/arc_session_manager.cc index 0a6204c..3544f00 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager.cc
@@ -42,6 +42,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" #include "components/arc/arc_bridge_service.h" +#include "components/arc/arc_session_runner.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "components/sync_preferences/pref_service_syncable.h" @@ -83,22 +84,22 @@ } // namespace -ArcSessionManager::ArcSessionManager(ArcBridgeService* bridge_service) - : ArcService(bridge_service), +ArcSessionManager::ArcSessionManager( + std::unique_ptr<ArcSessionRunner> arc_session_runner) + : arc_session_runner_(std::move(arc_session_runner)), attempt_user_exit_callback_(base::Bind(chrome::AttemptUserExit)), weak_ptr_factory_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!g_arc_session_manager); g_arc_session_manager = this; - - arc_bridge_service()->AddObserver(this); + arc_session_runner_->AddObserver(this); } ArcSessionManager::~ArcSessionManager() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); Shutdown(); - arc_bridge_service()->RemoveObserver(this); + arc_session_runner_->RemoveObserver(this); DCHECK_EQ(this, g_arc_session_manager); g_arc_session_manager = nullptr; @@ -195,6 +196,11 @@ return user_manager::UserManager::Get()->IsLoggedInAsArcKioskApp(); } +void ArcSessionManager::OnSessionReady() { + for (auto& observer : arc_session_observer_list_) + observer.OnSessionReady(); +} + void ArcSessionManager::OnSessionStopped(StopReason reason) { // TODO(crbug.com/625923): Use |reason| to report more detailed errors. if (arc_sign_in_timer_.IsRunning()) @@ -203,7 +209,7 @@ if (profile_->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)) { // This should be always true, but just in case as this is looked at // inside RemoveArcData() at first. - DCHECK(arc_bridge_service()->stopped()); + DCHECK(arc_session_runner_->IsStopped()); RemoveArcData(); } else { // To support special "Stop and enable ARC" procedure for enterprise, @@ -213,6 +219,9 @@ FROM_HERE, base::Bind(&ArcSessionManager::MaybeReenableArc, weak_ptr_factory_.GetWeakPtr())); } + + for (auto& observer : arc_session_observer_list_) + observer.OnSessionStopped(reason); } void ArcSessionManager::RemoveArcData() { @@ -223,8 +232,8 @@ // OnArcDataRemoved resets this flag. profile_->GetPrefs()->SetBoolean(prefs::kArcDataRemoveRequested, true); - if (!arc_bridge_service()->stopped()) { - // Just set a flag. On bridge stopped, this will be re-called, + if (!arc_session_runner_->IsStopped()) { + // Just set a flag. On session stopped, this will be re-called, // then session manager should remove the data. return; } @@ -258,7 +267,7 @@ void ArcSessionManager::MaybeReenableArc() { // Here check if |reenable_arc_| is marked or not. // The only case this happens should be in the special case for enterprise - // "on managed lost" case. In that case, OnBridgeStopped() should trigger + // "on managed lost" case. In that case, OnSessionStopped() should trigger // the RemoveArcData(), then this. if (!reenable_arc_ || !IsArcEnabled()) return; @@ -273,10 +282,10 @@ void ArcSessionManager::OnProvisioningFinished(ProvisioningResult result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - // Due asynchronous nature of stopping Arc bridge, OnProvisioningFinished may - // arrive after setting the |State::STOPPED| state and |State::Active| is not - // guaranty set here. prefs::kArcDataRemoveRequested is also can be active - // for now. + // Due asynchronous nature of stopping the ARC instance, + // OnProvisioningFinished may arrive after setting the |State::STOPPED| state + // and |State::Active| is not guaranteed to be set here. + // prefs::kArcDataRemoveRequested also can be active for now. if (provisioning_reported_) { // We don't expect ProvisioningResult::SUCCESS is reported twice or reported @@ -370,7 +379,7 @@ result == ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR) { if (profile_->GetPrefs()->HasPrefPath(prefs::kArcSignedIn)) profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false); - ShutdownBridge(); + ShutdownSession(); if (support_host_) support_host_->ShowError(error, false); return; @@ -387,8 +396,8 @@ RemoveArcData(); } - // We'll delay shutting down the bridge in this case to allow people to send - // feedback. + // We'll delay shutting down the ARC instance in this case to allow people + // to send feedback. if (support_host_) support_host_->ShowError(error, true /* = show send feedback button */); } @@ -493,7 +502,7 @@ if (!g_disable_ui_for_testing) ArcAuthNotification::Hide(); - ShutdownBridge(); + ShutdownSession(); if (support_host_) { support_host_->Close(); support_host_->RemoveObserver(this); @@ -535,7 +544,7 @@ profile_->GetPrefs()->SetBoolean(prefs::kArcSignedIn, false); profile_->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, false); } - ShutdownBridge(); + ShutdownSession(); if (support_host_) support_host_->Close(); } @@ -634,12 +643,15 @@ StartTermsOfServiceNegotiation(); } -void ArcSessionManager::ShutdownBridge() { +void ArcSessionManager::ShutdownSession() { arc_sign_in_timer_.Stop(); playstore_launcher_.reset(); terms_of_service_negotiator_.reset(); android_management_checker_.reset(); - arc_bridge_service()->RequestStop(); + arc_session_runner_->RequestStop(); + // TODO(hidehiko): The ARC instance's stopping is asynchronous, so it might + // still be running when we return from this function. Do not set the + // STOPPED state immediately here. if (state_ != State::NOT_INITIALIZED && state_ != State::REMOVING_DATA_DIR) SetState(State::STOPPED); for (auto& observer : observer_list_) @@ -656,11 +668,31 @@ observer_list_.RemoveObserver(observer); } +void ArcSessionManager::AddSessionObserver(ArcSessionObserver* observer) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + arc_session_observer_list_.AddObserver(observer); +} + +void ArcSessionManager::RemoveSessionObserver(ArcSessionObserver* observer) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + arc_session_observer_list_.RemoveObserver(observer); +} + +bool ArcSessionManager::IsSessionRunning() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return arc_session_runner_->IsRunning(); +} + +bool ArcSessionManager::IsSessionStopped() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return arc_session_runner_->IsStopped(); +} + // This is the special method to support enterprise mojo API. // TODO(hidehiko): Remove this. void ArcSessionManager::StopAndEnableArc() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(!arc_bridge_service()->stopped()); + DCHECK(!arc_session_runner_->IsStopped()); reenable_arc_ = true; StopArc(); } @@ -673,7 +705,7 @@ provisioning_reported_ = false; - arc_bridge_service()->RequestStart(); + arc_session_runner_->RequestStart(); SetState(State::ACTIVE); } @@ -760,9 +792,10 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!terms_of_service_negotiator_); - if (!arc_bridge_service()->stopped()) { - // If the user attempts to re-enable ARC while the bridge is still running - // the user should not be able to continue until the bridge has stopped. + if (!arc_session_runner_->IsStopped()) { + // If the user attempts to re-enable ARC while the ARC instance is still + // running the user should not be able to continue until the ARC instance + // has stopped. if (support_host_) { support_host_->ShowError( ArcSupportHost::Error::SIGN_IN_SERVICE_UNAVAILABLE_ERROR, false); @@ -801,7 +834,7 @@ void ArcSessionManager::StartArcAndroidManagementCheck() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(arc_bridge_service()->stopped()); + DCHECK(arc_session_runner_->IsStopped()); DCHECK(state_ == State::SHOWING_TERMS_OF_SERVICE || state_ == State::CHECKING_ANDROID_MANAGEMENT); SetState(State::CHECKING_ANDROID_MANAGEMENT); @@ -830,7 +863,7 @@ StartArc(); break; case policy::AndroidManagementClient::Result::MANAGED: - ShutdownBridge(); + ShutdownSession(); if (support_host_) { support_host_->ShowError( ArcSupportHost::Error::ANDROID_MANAGEMENT_REQUIRED_ERROR, false); @@ -838,7 +871,7 @@ UpdateOptInCancelUMA(OptInCancelReason::ANDROID_MANAGEMENT_REQUIRED); break; case policy::AndroidManagementClient::Result::ERROR: - ShutdownBridge(); + ShutdownSession(); if (support_host_) { support_host_->ShowError( ArcSupportHost::Error::SERVER_COMMUNICATION_ERROR, false); @@ -895,13 +928,13 @@ } else if (!profile_->GetPrefs()->GetBoolean(prefs::kArcTermsAccepted)) { StartTermsOfServiceNegotiation(); } else if (support_host_->ui_page() == ArcSupportHost::UIPage::ERROR && - !arc_bridge_service()->stopped()) { + !arc_session_runner_->IsStopped()) { // ERROR_WITH_FEEDBACK is set in OnSignInFailed(). In the case, stopping // ARC was postponed to contain its internal state into the report. // Here, on retry, stop it, then restart. DCHECK_EQ(State::ACTIVE, state_); support_host_->ShowArcLoading(); - ShutdownBridge(); + ShutdownSession(); reenable_arc_ = true; } else if (state_ == State::ACTIVE) { // This case is handled in ArcAuthService. @@ -920,6 +953,16 @@ chrome::OpenFeedbackDialog(nullptr); } +void ArcSessionManager::SetArcSessionRunnerForTesting( + std::unique_ptr<ArcSessionRunner> arc_session_runner) { + DCHECK(arc_session_runner); + DCHECK(arc_session_runner_); + DCHECK(arc_session_runner_->IsStopped()); + arc_session_runner_->RemoveObserver(this); + arc_session_runner_ = std::move(arc_session_runner); + arc_session_runner_->AddObserver(this); +} + void ArcSessionManager::SetAttemptUserExitCallbackForTesting( const base::Closure& callback) { DCHECK(!callback.is_null());
diff --git a/chrome/browser/chromeos/arc/arc_session_manager.h b/chrome/browser/chromeos/arc/arc_session_manager.h index 59678ace..20ef5ab 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager.h +++ b/chrome/browser/chromeos/arc/arc_session_manager.h
@@ -15,12 +15,10 @@ #include "base/timer/timer.h" #include "chrome/browser/chromeos/arc/arc_support_host.h" #include "chrome/browser/chromeos/policy/android_management_client.h" -#include "components/arc/arc_service.h" #include "components/arc/arc_session_observer.h" #include "components/prefs/pref_change_registrar.h" #include "components/sync_preferences/pref_service_syncable_observer.h" #include "components/sync_preferences/synced_pref_observer.h" -#include "mojo/public/cpp/bindings/binding.h" class ArcAppLauncher; class Profile; @@ -38,14 +36,13 @@ class ArcAndroidManagementChecker; class ArcAuthCodeFetcher; class ArcAuthContext; -class ArcBridgeService; +class ArcSessionRunner; class ArcTermsOfServiceNegotiator; enum class ProvisioningResult : int; // This class proxies the request from the client to fetch an auth code from // LSO. It lives on the UI thread. -class ArcSessionManager : public ArcService, - public ArcSessionObserver, +class ArcSessionManager : public ArcSessionObserver, public ArcSupportHost::Observer, public sync_preferences::PrefServiceSyncableObserver, public sync_preferences::SyncedPrefObserver { @@ -103,7 +100,8 @@ public: virtual ~Observer() = default; - // Called to notify that ARC bridge is shut down. + // Called to notify that ARC session is shut down. + // TODO(hidehiko): Rename the observer callback to OnArcSessionShutdown(). virtual void OnArcBridgeShutdown() {} // Called to notify that ARC enabled state has been updated. @@ -117,7 +115,8 @@ virtual void OnArcDataRemoved() {} }; - explicit ArcSessionManager(ArcBridgeService* bridge_service); + explicit ArcSessionManager( + std::unique_ptr<ArcSessionRunner> arc_session_runner); ~ArcSessionManager() override; static ArcSessionManager* Get(); @@ -154,8 +153,16 @@ void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); - // ArcSessionObserver: - void OnSessionStopped(StopReason reason) override; + // Adds or removes ArcSessionObservers. + // TODO(hidehiko): The observer should be migrated into + // ArcSessionManager::Observer. + void AddSessionObserver(ArcSessionObserver* observer); + void RemoveSessionObserver(ArcSessionObserver* observer); + + // Returns true if ARC instance is running/stopped, respectively. + // See ArcSessionRunner::IsRunning()/IsStopped() for details. + bool IsSessionRunning() const; + bool IsSessionStopped() const; // Called from Arc support platform app when user cancels signing. void CancelAuthCode(); @@ -207,6 +214,9 @@ void OnProvisioningFinished(ProvisioningResult result); + // Injectors for testing. + void SetArcSessionRunnerForTesting( + std::unique_ptr<ArcSessionRunner> arc_session_runner); void SetAttemptUserExitCallbackForTesting(const base::Closure& callback); private: @@ -215,7 +225,7 @@ void OnTermsOfServiceNegotiated(bool accepted); void SetState(State state); - void ShutdownBridge(); + void ShutdownSession(); void OnOptInPreferenceChanged(); void OnAndroidManagementPassed(); void OnArcDataRemoved(bool success); @@ -236,6 +246,12 @@ void OnBackgroundAndroidManagementChecked( policy::AndroidManagementClient::Result result); + // ArcSessionObserver: + void OnSessionReady() override; + void OnSessionStopped(StopReason reason) override; + + std::unique_ptr<ArcSessionRunner> arc_session_runner_; + // Unowned pointer. Keeps current profile. Profile* profile_ = nullptr; @@ -244,6 +260,7 @@ State state_ = State::NOT_INITIALIZED; base::ObserverList<Observer> observer_list_; + base::ObserverList<ArcSessionObserver> arc_session_observer_list_; std::unique_ptr<ArcAppLauncher> playstore_launcher_; bool reenable_arc_ = false; bool provisioning_reported_ = false;
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc b/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc index 8ca0fd5..24c24d5 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager_browsertest.cc
@@ -154,10 +154,6 @@ chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient( std::unique_ptr<chromeos::SessionManagerClient>( fake_session_manager_client)); - - // Mock out ARC instance. - ArcServiceManager::SetArcSessionRunnerForTesting( - base::MakeUnique<ArcSessionRunner>(base::Bind(FakeArcSession::Create))); } void SetUpOnMainThread() override { @@ -166,6 +162,8 @@ // Init ArcSessionManager for testing. ArcSessionManager::DisableUIForTesting(); ArcSessionManager::EnableCheckAndroidManagementForTesting(); + ArcSessionManager::Get()->SetArcSessionRunnerForTesting( + base::MakeUnique<ArcSessionRunner>(base::Bind(FakeArcSession::Create))); EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
diff --git a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc index d49c893..1af0884 100644 --- a/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc +++ b/chrome/browser/chromeos/arc/arc_session_manager_unittest.cc
@@ -29,7 +29,6 @@ #include "chromeos/chromeos_switches.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_session_manager_client.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_service_manager.h" #include "components/arc/arc_session_runner.h" #include "components/arc/test/fake_arc_session.h" @@ -74,14 +73,12 @@ profile_ = profile_builder.Build(); StartPreferenceSyncing(); - ArcServiceManager::SetArcSessionRunnerForTesting( - base::MakeUnique<ArcSessionRunner>(base::Bind(FakeArcSession::Create))); arc_service_manager_ = base::MakeUnique<ArcServiceManager>(nullptr); arc_session_manager_ = base::MakeUnique<ArcSessionManager>( - arc_service_manager_->arc_bridge_service()); + base::MakeUnique<ArcSessionRunner>(base::Bind(FakeArcSession::Create))); // Check initial conditions. - EXPECT_TRUE(bridge_service()->stopped()); + EXPECT_TRUE(arc_session_manager_->IsSessionStopped()); chromeos::WallpaperManager::Initialize(); } @@ -100,9 +97,7 @@ protected: Profile* profile() { return profile_.get(); } - ArcBridgeService* bridge_service() { - return arc_service_manager_->arc_bridge_service(); - } + ArcSessionManager* arc_session_manager() { return arc_session_manager_.get(); } @@ -226,7 +221,7 @@ } TEST_F(ArcSessionManagerTest, BaseWorkflow) { - ASSERT_FALSE(bridge_service()->ready()); + ASSERT_TRUE(arc_session_manager()->IsSessionStopped()); ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, arc_session_manager()->state()); @@ -247,12 +242,12 @@ arc_session_manager()->StartArc(); ASSERT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); - ASSERT_TRUE(bridge_service()->ready()); + ASSERT_TRUE(arc_session_manager()->IsSessionRunning()); arc_session_manager()->Shutdown(); ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, arc_session_manager()->state()); - ASSERT_FALSE(bridge_service()->ready()); + ASSERT_TRUE(arc_session_manager()->IsSessionStopped()); // Send profile and don't provide a code. arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); @@ -339,22 +334,22 @@ prefs->SetBoolean(prefs::kArcTermsAccepted, true); arc_session_manager()->StartArc(); EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); - EXPECT_TRUE(bridge_service()->ready()); + EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn)); arc_session_manager()->OnProvisioningFinished(ProvisioningResult::SUCCESS); EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); - EXPECT_TRUE(bridge_service()->ready()); + EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); // Second start, no fetching code is expected. arc_session_manager()->Shutdown(); EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED, arc_session_manager()->state()); - EXPECT_FALSE(bridge_service()->ready()); + EXPECT_TRUE(arc_session_manager()->IsSessionStopped()); arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); - EXPECT_TRUE(bridge_service()->ready()); + EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); // Report failure. arc_session_manager()->OnProvisioningFinished( @@ -363,7 +358,7 @@ // the ARC is still necessary to run on background for gathering the logs. EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); - EXPECT_TRUE(bridge_service()->ready()); + EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); // Correctly stop service. arc_session_manager()->Shutdown();
diff --git a/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc b/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc index 5d38252..61d53e1 100644 --- a/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc +++ b/chrome/browser/chromeos/arc/notification/arc_boot_error_notification.cc
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/arc/arc_session_manager.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/chrome_pages.h" @@ -90,11 +91,11 @@ ArcBootErrorNotification::ArcBootErrorNotification( ArcBridgeService* bridge_service) : ArcService(bridge_service) { - arc_bridge_service()->AddObserver(this); + ArcSessionManager::Get()->AddSessionObserver(this); } ArcBootErrorNotification::~ArcBootErrorNotification() { - arc_bridge_service()->RemoveObserver(this); + ArcSessionManager::Get()->RemoveSessionObserver(this); } void ArcBootErrorNotification::OnSessionStopped(StopReason reason) {
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 2abfffa..3de03b3 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -209,8 +209,6 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_session_manager_client.h" #include "chromeos/dbus/session_manager_client.h" -#include "components/arc/arc_bridge_service.h" -#include "components/arc/arc_service_manager.h" #include "components/arc/arc_session_runner.h" #include "components/arc/test/fake_arc_session.h" #include "components/signin/core/account_id/account_id.h" @@ -4052,6 +4050,9 @@ protected: void SetUpTest() { arc::ArcSessionManager::DisableUIForTesting(); + arc::ArcSessionManager::Get()->SetArcSessionRunnerForTesting( + base::MakeUnique<arc::ArcSessionRunner>( + base::Bind(arc::FakeArcSession::Create))); browser()->profile()->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); browser()->profile()->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, @@ -4067,10 +4068,6 @@ chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient( std::unique_ptr<chromeos::SessionManagerClient>( fake_session_manager_client_)); - - arc::ArcServiceManager::SetArcSessionRunnerForTesting( - base::MakeUnique<arc::ArcSessionRunner>( - base::Bind(arc::FakeArcSession::Create))); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -4103,20 +4100,19 @@ SetUpTest(); const PrefService* const pref = browser()->profile()->GetPrefs(); - const arc::ArcBridgeService* const arc_bridge_service = - arc::ArcServiceManager::Get()->arc_bridge_service(); + const auto* const arc_session_manager = arc::ArcSessionManager::Get(); // ARC is switched off by default. - EXPECT_TRUE(arc_bridge_service->stopped()); + EXPECT_TRUE(arc_session_manager->IsSessionStopped()); EXPECT_FALSE(pref->GetBoolean(prefs::kArcEnabled)); // Enable ARC. SetArcEnabledByPolicy(true); - EXPECT_TRUE(arc_bridge_service->ready()); + EXPECT_TRUE(arc_session_manager->IsSessionRunning()); // Disable ARC. SetArcEnabledByPolicy(false); - EXPECT_TRUE(arc_bridge_service->stopped()); + EXPECT_TRUE(arc_session_manager->IsSessionStopped()); TearDownTest(); }
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc index a3b52e3f..2f581887 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_browsertest.cc
@@ -65,17 +65,25 @@ struct ResourceSummary { ResourceSummary() - : is_no_store(false), - version(0), + : version(0), + is_no_store(false), is_external(false), - should_be_recorded(true) {} + is_observable(true), + is_prohibited(false) {} ResourcePrefetchPredictor::URLRequestSummary request; std::string content; - bool is_no_store; + // Allows to update HTTP ETag. size_t version; + // True iff "Cache-control: no-store" header is present. + bool is_no_store; + // True iff a request for this resource must be ignored by the custom handler. bool is_external; - bool should_be_recorded; + // True iff the LearningObserver must observe this resource. + bool is_observable; + // A request with |is_prohibited| set to true makes the test that originates + // the request fail. + bool is_prohibited; }; struct RedirectEdge { @@ -175,6 +183,10 @@ testing::UnorderedElementsAreArray(expected_subresources)); } +std::string CreateVersionedETag(size_t version, const std::string& path) { + return base::StringPrintf("'%zu%s'", version, path.c_str()); +} + } // namespace // Helper class to track and allow waiting for a single OnNavigationLearned @@ -270,6 +282,9 @@ embedded_test_server()->RegisterRequestHandler( base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest, base::Unretained(this))); + embedded_test_server()->RegisterRequestMonitor(base::Bind( + &ResourcePrefetchPredictorBrowserTest::MonitorResourceRequest, + base::Unretained(this))); ASSERT_TRUE(embedded_test_server()->Start()); predictor_ = ResourcePrefetchPredictorFactory::GetForProfile(browser()->profile()); @@ -287,7 +302,17 @@ // Prefetch all needed resources and change expectations so that all // cacheable resources should be served from cache next navigation. PrefetchURL(main_frame_url); + // To be sure that the browser send no requests to the server after + // prefetching. + for (auto& kv : resources_) { + if (kv.second.is_observable) + kv.second.is_prohibited = true; + } NavigateToURLAndCheckSubresources(main_frame_url); + for (auto& kv : resources_) { + if (kv.second.is_observable) + kv.second.is_prohibited = false; + } } void NavigateToURLAndCheckSubresources( @@ -296,10 +321,10 @@ GURL endpoint_url = GetRedirectEndpoint(main_frame_url); std::vector<URLRequestSummary> url_request_summaries; for (const auto& kv : resources_) { - if (kv.second.is_no_store || !kv.second.should_be_recorded) - continue; - url_request_summaries.push_back( - GetURLRequestSummaryForResource(endpoint_url, kv.second)); + if (kv.second.is_observable) { + url_request_summaries.push_back( + GetURLRequestSummaryForResource(endpoint_url, kv.second)); + } } bool match_navigation_id = @@ -315,7 +340,7 @@ ui_test_utils::BROWSER_TEST_NONE); observer.Wait(); for (auto& kv : resources_) { - if (!kv.second.is_no_store && kv.second.should_be_recorded) + if (kv.second.is_observable) kv.second.request.was_cached = true; } for (const auto& nav : observer.current_navigation_ids()) @@ -327,7 +352,7 @@ predictor_->StartPrefetching(main_frame_url, PrefetchOrigin::EXTERNAL); observer.Wait(); for (auto& kv : resources_) { - if (!kv.second.is_no_store && kv.second.should_be_recorded) + if (kv.second.is_observable) kv.second.request.was_cached = true; } } @@ -355,12 +380,12 @@ return resource; } - void AddUnrecordedResources(const std::vector<GURL>& resource_urls) { + void AddUnobservableResources(const std::vector<GURL>& resource_urls) { for (const GURL& resource_url : resource_urls) { auto resource = AddResource(resource_url, content::RESOURCE_TYPE_SUB_RESOURCE, net::DEFAULT_PRIORITY); - resource->should_be_recorded = false; + resource->is_observable = false; } } @@ -407,6 +432,9 @@ https_server()->RegisterRequestHandler( base::Bind(&ResourcePrefetchPredictorBrowserTest::HandleResourceRequest, base::Unretained(this))); + https_server()->RegisterRequestMonitor(base::Bind( + &ResourcePrefetchPredictorBrowserTest::MonitorResourceRequest, + base::Unretained(this))); ASSERT_TRUE(https_server()->Start()); } @@ -453,7 +481,8 @@ GURL GetRedirectEndpoint(const GURL& initial_url) const { GURL current = initial_url; while (true) { - auto it = redirects_.find(current); + std::map<GURL, RedirectEdge>::const_iterator it = + redirects_.find(current); if (it == redirects_.end()) break; current = it->second.url; @@ -461,6 +490,26 @@ return current; } + void MonitorResourceRequest( + const net::test_server::HttpRequest& request) const { + std::map<GURL, ResourceSummary>::const_iterator resource_it = + resources_.find(request.GetURL()); + if (resource_it == resources_.end()) + return; + + const ResourceSummary& summary = resource_it->second; + EXPECT_FALSE(summary.is_prohibited) << request.GetURL() << "\n" + << request.all_headers; + } + + // The custom handler for resource requests from the browser to an + // EmbeddedTestServer. Runs on the EmbeddedTestServer IO thread. + // Finds the data to serve requests in |resources_| map keyed by a request + // URL. + // Uses also the following headers from the |request|: + // - "Host" to retrieve the host that actually was issued by the browser. + // - "If-None-Match" to determine if the resource is still valid. If the + // ETag values match, the handler responds with a HTTP 304 status. std::unique_ptr<net::test_server::HttpResponse> HandleResourceRequest( const net::test_server::HttpRequest& request) const { GURL resource_url = request.GetURL(); @@ -477,7 +526,8 @@ << resource_url.spec(); } - auto resource_it = resources_.find(resource_url); + std::map<GURL, ResourceSummary>::const_iterator resource_it = + resources_.find(resource_url); if (resource_it == resources_.end()) return nullptr; @@ -487,7 +537,15 @@ auto http_response = base::MakeUnique<net::test_server::BasicHttpResponse>(); - http_response->set_code(net::HTTP_OK); + + if (request.headers.find("If-None-Match") != request.headers.end() && + request.headers.at("If-None-Match") == + CreateVersionedETag(summary.version, request.relative_url)) { + http_response->set_code(net::HTTP_NOT_MODIFIED); + } else { + http_response->set_code(net::HTTP_OK); + } + if (!summary.request.mime_type.empty()) http_response->set_content_type(summary.request.mime_type); if (!summary.content.empty()) @@ -496,8 +554,7 @@ http_response->AddCustomHeader("Cache-Control", "no-store"); if (summary.request.has_validators) { http_response->AddCustomHeader( - "ETag", base::StringPrintf("'%zu%s'", summary.version, - request.relative_url.c_str())); + "ETag", CreateVersionedETag(summary.version, request.relative_url)); } if (summary.request.always_revalidate) http_response->AddCustomHeader("Cache-Control", "no-cache"); @@ -506,9 +563,14 @@ return std::move(http_response); } + // The custom handler for redirect requests from the browser to an + // EmbeddedTestServer. Running on the EmbeddedTestServer IO thread. + // Finds the data to serve requests in |redirects_| map keyed by a request + // URL. std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest( const net::test_server::HttpRequest& request) const { - auto redirect_it = redirects_.find(request.GetURL()); + std::map<GURL, RedirectEdge>::const_iterator redirect_it = + redirects_.find(request.GetURL()); if (redirect_it == redirects_.end()) return nullptr; @@ -623,7 +685,7 @@ net::HIGHEST); // https://www.w3.org/TR/2014/REC-html5-20141028/scripting-1.html#the-script-element // Script elements don't execute when inserted using innerHTML attribute. - AddUnrecordedResources({GetURL(kScriptPath)}); + AddUnobservableResources({GetURL(kScriptPath)}); TestLearningAndPrefetching(GetURL(kHtmlInnerHtmlPath)); } @@ -653,9 +715,10 @@ AddResource(GetURL(kStylePath2), content::RESOURCE_TYPE_STYLESHEET, net::HIGHEST); AddResource(GetURL(kScriptPath2), content::RESOURCE_TYPE_SCRIPT, net::MEDIUM); - // Included from <iframe src="html_subresources.html"> and not recored. - AddUnrecordedResources({GetURL(kImagePath), GetURL(kStylePath), - GetURL(kScriptPath), GetURL(kFontPath)}); + // Included from <iframe src="html_subresources.html"> and shouldn't be + // observed. + AddUnobservableResources({GetURL(kImagePath), GetURL(kStylePath), + GetURL(kScriptPath), GetURL(kFontPath)}); TestLearningAndPrefetching(GetURL(kHtmlIframePath)); } @@ -718,4 +781,20 @@ EXPECT_EQ(navigation_ids_history_size(), 4U); } +IN_PROC_BROWSER_TEST_F(ResourcePrefetchPredictorBrowserTest, AlwaysRevalidate) { + std::vector<ResourceSummary*> resources = { + AddResource(GetURL(kImagePath), content::RESOURCE_TYPE_IMAGE, + net::LOWEST), + AddResource(GetURL(kStylePath), content::RESOURCE_TYPE_STYLESHEET, + net::HIGHEST), + AddResource(GetURL(kScriptPath), content::RESOURCE_TYPE_SCRIPT, + net::MEDIUM), + AddResource(GetURL(kFontPath), content::RESOURCE_TYPE_FONT_RESOURCE, + net::HIGHEST), + }; + for (auto& resource : resources) + resource->request.always_revalidate = true; + TestLearningAndPrefetching(GetURL(kHtmlSubresourcesPath)); +} + } // namespace predictors
diff --git a/chrome/browser/ui/app_list/arc/arc_app_test.cc b/chrome/browser/ui/app_list/arc/arc_app_test.cc index 1a9d9581..0d21c988 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_test.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_test.cc
@@ -79,12 +79,10 @@ ArcAppListPrefsFactory::GetInstance()->RecreateServiceInstanceForTesting( profile_); } - arc::ArcServiceManager::SetArcSessionRunnerForTesting( - base::MakeUnique<arc::ArcSessionRunner>( - base::Bind(arc::FakeArcSession::Create))); arc_service_manager_ = base::MakeUnique<arc::ArcServiceManager>(nullptr); arc_session_manager_ = base::MakeUnique<arc::ArcSessionManager>( - arc_service_manager_->arc_bridge_service()); + base::MakeUnique<arc::ArcSessionRunner>( + base::Bind(arc::FakeArcSession::Create))); DCHECK(arc::ArcSessionManager::Get()); arc::ArcSessionManager::DisableUIForTesting(); arc_session_manager_->OnPrimaryUserProfilePrepared(profile_); @@ -96,12 +94,12 @@ run_loop.Run(); arc_session_manager_->EnableArc(); + // Check initial conditions. + EXPECT_FALSE(arc_session_manager_->IsSessionRunning()); + app_instance_.reset(new arc::FakeAppInstance(arc_app_list_pref_)); arc_service_manager_->arc_bridge_service()->app()->SetInstance( app_instance_.get()); - - // Check initial conditions. - EXPECT_FALSE(arc_service_manager_->arc_bridge_service()->ready()); } void ArcAppTest::CreateFakeAppsAndPackages() {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc index c11611a..49efa1f 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc
@@ -15,7 +15,6 @@ #if defined(OS_CHROMEOS) #include "base/memory/ptr_util.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_session_runner.h" #include "components/arc/test/fake_arc_session.h" #endif @@ -36,12 +35,9 @@ ash::test::AshTestBase::SetUp(); #if defined(OS_CHROMEOS) arc::ArcSessionManager::DisableUIForTesting(); - bridge_service_ = base::MakeUnique<arc::ArcBridgeService>(); - bridge_service_->InitializeArcSessionRunner( + arc_session_manager_ = base::MakeUnique<arc::ArcSessionManager>( base::MakeUnique<arc::ArcSessionRunner>( base::Bind(arc::FakeArcSession::Create))); - arc_session_manager_ = - base::MakeUnique<arc::ArcSessionManager>(bridge_service_.get()); arc_session_manager_->OnPrimaryUserProfilePrepared( extension_environment_.profile()); #endif @@ -68,7 +64,6 @@ views::Widget* widget_ = nullptr; AppInfoDialog* dialog_ = nullptr; // Owned by |widget_|'s views hierarchy. #if defined(OS_CHROMEOS) - std::unique_ptr<arc::ArcBridgeService> bridge_service_; std::unique_ptr<arc::ArcSessionManager> arc_session_manager_; #endif
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc index 48028e28..73ad28d 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_unittest.cc
@@ -26,7 +26,6 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/arc/arc_session_manager.h" -#include "components/arc/arc_bridge_service.h" #include "components/arc/arc_session_runner.h" #include "components/arc/test/fake_arc_session.h" #endif @@ -71,12 +70,9 @@ BrowserWithTestWindowTest::SetUp(); #if defined(OS_CHROMEOS) arc::ArcSessionManager::DisableUIForTesting(); - bridge_service_ = base::MakeUnique<arc::ArcBridgeService>(); - bridge_service_->InitializeArcSessionRunner( + arc_session_manager_ = base::MakeUnique<arc::ArcSessionManager>( base::MakeUnique<arc::ArcSessionRunner>( base::Bind(arc::FakeArcSession::Create))); - arc_session_manager_ = - base::MakeUnique<arc::ArcSessionManager>(bridge_service_.get()); arc_session_manager_->OnPrimaryUserProfilePrepared( extension_environment_.profile()); #endif @@ -143,7 +139,6 @@ scoped_refptr<extensions::Extension> extension_; extensions::TestExtensionEnvironment extension_environment_; #if defined(OS_CHROMEOS) - std::unique_ptr<arc::ArcBridgeService> bridge_service_; std::unique_ptr<arc::ArcSessionManager> arc_session_manager_; #endif
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 1c5cf88..0d51d3d 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -9122.0.0 \ No newline at end of file +9125.0.0 \ No newline at end of file
diff --git a/components/arc/arc_bridge_service.cc b/components/arc/arc_bridge_service.cc index 3044d1e..f17d3d6 100644 --- a/components/arc/arc_bridge_service.cc +++ b/components/arc/arc_bridge_service.cc
@@ -11,7 +11,6 @@ #include "base/sequenced_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "chromeos/chromeos_switches.h" -#include "components/arc/arc_session_runner.h" namespace arc { @@ -38,45 +37,4 @@ return command_line->HasSwitch(chromeos::switches::kArcAvailable); } -void ArcBridgeService::InitializeArcSessionRunner( - std::unique_ptr<ArcSessionRunner> arc_session_runner) { - DCHECK(!arc_session_runner_); - arc_session_runner_ = std::move(arc_session_runner); -} - -void ArcBridgeService::AddObserver(ArcSessionObserver* observer) { - DCHECK(arc_session_runner_); - arc_session_runner_->AddObserver(observer); -} - -void ArcBridgeService::RemoveObserver(ArcSessionObserver* observer) { - DCHECK(arc_session_runner_); - arc_session_runner_->RemoveObserver(observer); -} - -void ArcBridgeService::RequestStart() { - DCHECK(arc_session_runner_); - arc_session_runner_->RequestStart(); -} - -void ArcBridgeService::RequestStop() { - DCHECK(arc_session_runner_); - arc_session_runner_->RequestStop(); -} - -void ArcBridgeService::OnShutdown() { - DCHECK(arc_session_runner_); - arc_session_runner_->OnShutdown(); -} - -bool ArcBridgeService::ready() const { - DCHECK(arc_session_runner_); - return arc_session_runner_->IsRunning(); -} - -bool ArcBridgeService::stopped() const { - DCHECK(arc_session_runner_); - return arc_session_runner_->IsStopped(); -} - } // namespace arc
diff --git a/components/arc/arc_bridge_service.h b/components/arc/arc_bridge_service.h index b74bea6a..3f4a5f5a3 100644 --- a/components/arc/arc_bridge_service.h +++ b/components/arc/arc_bridge_service.h
@@ -48,41 +48,19 @@ } // namespace mojom -class ArcSessionObserver; -class ArcSessionRunner; - -// The Chrome-side service that handles ARC instances and ARC bridge creation. -// This service handles the lifetime of ARC instances and sets up the -// communication channel (the ARC bridge) used to send and receive messages. +// Holds Mojo channels which proxy to ARC side implementation. The actual +// instances are set/removed via ArcBridgeHostImpl. class ArcBridgeService { public: ArcBridgeService(); - virtual ~ArcBridgeService(); + ~ArcBridgeService(); - // Return true if ARC has been enabled through a commandline - // switch. + // Returns true if ARC has been enabled through a commandline switch. static bool GetEnabled(const base::CommandLine* command_line); - // Return true if ARC is available on the current board. + // Returns true if ARC is available on the current board. static bool GetAvailable(const base::CommandLine* command_line); - // Initializes the ArcSessionRunner with the given instance. - // This must be called before following proxy methods. - void InitializeArcSessionRunner( - std::unique_ptr<ArcSessionRunner> arc_session_runner); - - // Proxies the method to ArcSessionRunner. See details in the - // ArcSessionRunner's comment. - // TODO(hidehiko): Move the ownership from ArcBridgeService to - // ArcSessionManager, and remove these methods. - void AddObserver(ArcSessionObserver* observer); - void RemoveObserver(ArcSessionObserver* observer); - void RequestStart(); - void RequestStop(); - void OnShutdown(); - bool ready() const; - bool stopped() const; - InstanceHolder<mojom::AppInstance>* app() { return &app_; } InstanceHolder<mojom::AudioInstance>* audio() { return &audio_; } InstanceHolder<mojom::AuthInstance>* auth() { return &auth_; } @@ -125,7 +103,6 @@ InstanceHolder<mojom::WallpaperInstance>* wallpaper() { return &wallpaper_; } private: - // Instance holders. InstanceHolder<mojom::AppInstance> app_; InstanceHolder<mojom::AudioInstance> audio_; InstanceHolder<mojom::AuthInstance> auth_; @@ -151,8 +128,6 @@ InstanceHolder<mojom::VideoInstance> video_; InstanceHolder<mojom::WallpaperInstance> wallpaper_; - std::unique_ptr<ArcSessionRunner> arc_session_runner_; - DISALLOW_COPY_AND_ASSIGN(ArcBridgeService); };
diff --git a/components/arc/arc_service_manager.cc b/components/arc/arc_service_manager.cc index df5250c..9204fef 100644 --- a/components/arc/arc_service_manager.cc +++ b/components/arc/arc_service_manager.cc
@@ -20,9 +20,6 @@ // Weak pointer. This class is owned by arc::ArcServiceLauncher. ArcServiceManager* g_arc_service_manager = nullptr; -// This pointer is owned by ArcServiceManager. -ArcSessionRunner* g_arc_session_runner_for_testing = nullptr; - } // namespace class ArcServiceManager::IntentHelperObserverImpl @@ -52,30 +49,17 @@ scoped_refptr<base::TaskRunner> blocking_task_runner) : blocking_task_runner_(blocking_task_runner), intent_helper_observer_(base::MakeUnique<IntentHelperObserverImpl>(this)), + arc_bridge_service_(base::MakeUnique<ArcBridgeService>()), icon_loader_(new ActivityIconLoader()), activity_resolver_(new LocalActivityResolver()) { DCHECK(!g_arc_service_manager); g_arc_service_manager = this; - - arc_bridge_service_ = base::MakeUnique<ArcBridgeService>(); - if (g_arc_session_runner_for_testing) { - arc_bridge_service_->InitializeArcSessionRunner( - base::WrapUnique(g_arc_session_runner_for_testing)); - g_arc_session_runner_for_testing = nullptr; - } else { - arc_bridge_service_->InitializeArcSessionRunner( - base::MakeUnique<ArcSessionRunner>(base::Bind(&ArcSession::Create, - arc_bridge_service_.get(), - blocking_task_runner))); - } } ArcServiceManager::~ArcServiceManager() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(g_arc_service_manager == this); + DCHECK_EQ(g_arc_service_manager, this); g_arc_service_manager = nullptr; - if (g_arc_session_runner_for_testing) - delete g_arc_session_runner_for_testing; } // static @@ -116,15 +100,6 @@ icon_loader_ = nullptr; activity_resolver_ = nullptr; services_.clear(); - arc_bridge_service_->OnShutdown(); -} - -// static -void ArcServiceManager::SetArcSessionRunnerForTesting( - std::unique_ptr<ArcSessionRunner> arc_session_runner) { - if (g_arc_session_runner_for_testing) - delete g_arc_session_runner_for_testing; - g_arc_session_runner_for_testing = arc_session_runner.release(); } } // namespace arc
diff --git a/components/arc/arc_service_manager.h b/components/arc/arc_service_manager.h index 68df26a..81a4ea9 100644 --- a/components/arc/arc_service_manager.h +++ b/components/arc/arc_service_manager.h
@@ -21,7 +21,6 @@ class ArcBridgeService; class ArcIntentHelperObserver; class ArcService; -class ArcSessionRunner; // Manages creation and destruction of services that communicate with the ARC // instance via the ArcBridgeService. @@ -66,11 +65,6 @@ return blocking_task_runner_; } - // Set ArcSessionRunner instance for testing. Call before ArcServiceManager - // creation. - static void SetArcSessionRunnerForTesting( - std::unique_ptr<ArcSessionRunner> arc_session_runner); - // Returns the icon loader owned by ArcServiceManager and shared by services. scoped_refptr<ActivityIconLoader> icon_loader() { return icon_loader_; }
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc index 7a1626a..af61d9c 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -420,10 +420,18 @@ DCHECK(job_.get()); DCHECK(context_); + // When this request handler was created, the provider host had a controller + // and hence an active version, but by the time MaybeCreateJob() is called + // the active version may have been lost. This happens when + // ServiceWorkerRegistration::DeleteVersion() was called to delete the worker + // because a permanent failure occurred when trying to start it. + // + // As this is an exceptional case, just error out. + // TODO(falken): Figure out if |active_version| can change to + // |controlling_version| and do it or document the findings. if (!provider_host_->active_version()) { - // TODO(falken): For debugging. Remove once https://crbug.com/655910 is - // resolved. - CHECK(provider_host_->controller_was_deleted()); + job_->FailDueToLostController(); + return; } MaybeForwardToServiceWorker(job_.get(), provider_host_->active_version()); @@ -462,7 +470,7 @@ void ServiceWorkerControlleeRequestHandler::MainResourceLoadFailed() { DCHECK(provider_host_); // Detach the controller so subresource requests also skip the worker. - provider_host_->NotifyControllerLost(false /* was_deleted */); + provider_host_->NotifyControllerLost(); } void ServiceWorkerControlleeRequestHandler::ClearJob() {
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc index 17d580e1..8132f4d9 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -301,6 +301,48 @@ EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker()); } +// Tests the scenario where a controllee request handler was created +// for a subresource request, but before MaybeCreateJob() is run, the +// controller/active version becomes null. +TEST_P(ServiceWorkerControlleeRequestHandlerTestP, LostActiveVersion) { + // Store an activated worker. + version_->set_fetch_handler_existence( + ServiceWorkerVersion::FetchHandlerExistence::EXISTS); + version_->SetStatus(ServiceWorkerVersion::ACTIVATED); + registration_->SetActiveVersion(version_); + context()->storage()->StoreRegistration( + registration_.get(), version_.get(), + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback)); + base::RunLoop().RunUntilIdle(); + + // Conduct a main resource load to set the controller. + ServiceWorkerRequestTestResources main_test_resources( + this, GURL("https://host/scope/doc"), RESOURCE_TYPE_MAIN_FRAME); + main_test_resources.MaybeCreateJob(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(version_->HasControllee()); + EXPECT_EQ(version_, provider_host_->controlling_version()); + EXPECT_EQ(version_, provider_host_->active_version()); + + // Unset the active version. + provider_host_->NotifyControllerLost(); + registration_->SetActiveVersion(nullptr); + EXPECT_FALSE(version_->HasControllee()); + EXPECT_FALSE(provider_host_->controlling_version()); + EXPECT_FALSE(provider_host_->active_version()); + + // Conduct a subresource load. + ServiceWorkerRequestTestResources sub_test_resources( + this, GURL("https://host/scope/doc"), RESOURCE_TYPE_IMAGE); + ServiceWorkerURLRequestJob* sub_job = sub_test_resources.MaybeCreateJob(); + base::RunLoop().RunUntilIdle(); + + // Verify that the job errored. + EXPECT_EQ( + ServiceWorkerURLRequestJob::ResponseType::FAIL_DUE_TO_LOST_CONTROLLER, + sub_job->response_type_); +} + TEST_P(ServiceWorkerControlleeRequestHandlerTestP, FallbackWithNoFetchHandler) { version_->set_fetch_handler_existence( ServiceWorkerVersion::FetchHandlerExistence::DOES_NOT_EXIST);
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index 92c46ff4e..a32fdd3 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -118,8 +118,7 @@ parent_frame_security_level_(parent_frame_security_level), context_(context), dispatcher_host_(dispatcher_host), - allow_association_(true), - controller_was_deleted_(false) { + allow_association_(true) { DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN, provider_type_); // PlzNavigate @@ -211,9 +210,7 @@ if (!controlling_version_) return; ServiceWorkerVersion* active_version = registration->active_version(); - // TODO(falken): Change to DCHECK once https://crbug.com/655910 is - // resolved. - CHECK(active_version); + DCHECK(active_version); DCHECK_EQ(active_version->status(), ServiceWorkerVersion::ACTIVATING); SetControllerVersionAttribute(active_version, true /* notify_controllerchange */); @@ -360,9 +357,7 @@ return nullptr; } -void ServiceWorkerProviderHost::NotifyControllerLost(bool was_deleted) { - if (was_deleted) - controller_was_deleted_ = true; +void ServiceWorkerProviderHost::NotifyControllerLost() { SetControllerVersionAttribute(nullptr, true /* notify_controllerchange */); } @@ -472,8 +467,7 @@ void ServiceWorkerProviderHost::ClaimedByRegistration( ServiceWorkerRegistration* registration) { - // TODO(falken): Change to DCHECK once https://crbug.com/655910 is resolved. - CHECK(registration->active_version()); + DCHECK(registration->active_version()); if (registration == associated_registration_) { SetControllerVersionAttribute(registration->active_version(), true /* notify_controllerchange */);
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h index 35ed99d..4879e4f 100644 --- a/content/browser/service_worker/service_worker_provider_host.h +++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -122,29 +122,53 @@ return running_hosted_version_.get() != NULL; } + // Returns this provider's controller. The controller is typically the same as + // active_version() but can differ in the following cases: + // (1) The client was created before the registration existed or had an active + // version (in spec language, it is not "using" the registration). + // (2) The client had a controller but NotifyControllerLost() was called due + // to an exceptional circumstance (here also it is not "using" the + // registration). + // (3) During algorithms such as the update, skipWaiting(), and claim() steps, + // the active_version and controlling_version may temporarily differ. For + // example, to perform skipWaiting(), the registration's active version is + // updated first and then the provider host's controlling version is updated + // to match it. ServiceWorkerVersion* controlling_version() const { + // Only clients can have controllers. + DCHECK(!controlling_version_ || IsProviderForClient()); return controlling_version_.get(); } + ServiceWorkerVersion* active_version() const { return associated_registration_.get() ? associated_registration_->active_version() : NULL; } + ServiceWorkerVersion* waiting_version() const { return associated_registration_.get() ? associated_registration_->waiting_version() : NULL; } + ServiceWorkerVersion* installing_version() const { return associated_registration_.get() ? associated_registration_->installing_version() : NULL; } + // Returns the associated registration. The provider host listens to this + // registration to resolve the .ready promise and set its controller. ServiceWorkerRegistration* associated_registration() const { + // Only clients can have an associated registration. + DCHECK(!associated_registration_ || IsProviderForClient()); return associated_registration_.get(); } // The running version, if any, that this provider is providing resource // loads for. ServiceWorkerVersion* running_hosted_version() const { + // Only providers for controllers can host a running version. + DCHECK(!running_hosted_version_ || + provider_type_ == SERVICE_WORKER_PROVIDER_FOR_CONTROLLER); return running_hosted_version_.get(); } @@ -268,8 +292,7 @@ // Called when our controller has been terminated and doomed due to an // exceptional condition like it could no longer be read from the script // cache. - void NotifyControllerLost(bool was_deleted); - bool controller_was_deleted() { return controller_was_deleted_; } + void NotifyControllerLost(); private: friend class ForeignFetchRequestHandlerTest; @@ -390,8 +413,6 @@ base::WeakPtr<ServiceWorkerContextCore> context_; ServiceWorkerDispatcherHost* dispatcher_host_; bool allow_association_; - // TODO(falken): Remove once https://crbug.com/655910 is resolved. - bool controller_was_deleted_; std::vector<base::Closure> queued_events_;
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc index e993a27..de9f481 100644 --- a/content/browser/service_worker/service_worker_registration.cc +++ b/content/browser/service_worker/service_worker_registration.cc
@@ -358,7 +358,7 @@ !it->IsAtEnd(); it->Advance()) { ServiceWorkerProviderHost* host = it->GetProviderHost(); if (host->controlling_version() == version) - host->NotifyControllerLost(true /* was_deleted */); + host->NotifyControllerLost(); } version->Doom();
diff --git a/content/browser/service_worker/service_worker_url_request_job.cc b/content/browser/service_worker/service_worker_url_request_job.cc index 05b69ed..da9a6f9 100644 --- a/content/browser/service_worker/service_worker_url_request_job.cc +++ b/content/browser/service_worker/service_worker_url_request_job.cc
@@ -297,6 +297,12 @@ MaybeStartRequest(); } +void ServiceWorkerURLRequestJob::FailDueToLostController() { + DCHECK_EQ(NOT_DETERMINED, response_type_); + response_type_ = FAIL_DUE_TO_LOST_CONTROLLER; + MaybeStartRequest(); +} + void ServiceWorkerURLRequestJob::Start() { is_started_ = true; MaybeStartRequest(); @@ -427,6 +433,12 @@ NOTREACHED(); return; + case FAIL_DUE_TO_LOST_CONTROLLER: + request()->net_log().AddEvent( + net::NetLogEventType::SERVICE_WORKER_ERROR_NO_ACTIVE_VERSION); + NotifyStartError(net::URLRequestStatus::FromError(net::ERR_FAILED)); + return; + case FALLBACK_TO_NETWORK: FinalizeFallbackToNetwork(); return; @@ -792,30 +804,41 @@ } void ServiceWorkerURLRequestJob::OnStartCompleted() const { - if (response_type_ != FORWARD_TO_SERVICE_WORKER && - response_type_ != FALLBACK_TO_RENDERER) { - ServiceWorkerResponseInfo::ForRequest(request_, true) - ->OnStartCompleted( - false /* was_fetched_via_service_worker */, - false /* was_fetched_via_foreign_fetch */, - false /* was_fallback_required */, - std::vector<GURL>() /* url_list_via_service_worker */, - blink::WebServiceWorkerResponseTypeDefault, - base::TimeTicks() /* service_worker_start_time */, - base::TimeTicks() /* service_worker_ready_time */, - false /* respons_is_in_cache_storage */, - std::string() /* response_cache_storage_cache_name */, - ServiceWorkerHeaderList() /* cors_exposed_header_names */); - return; + switch (response_type_) { + case NOT_DETERMINED: + NOTREACHED(); + return; + case FAIL_DUE_TO_LOST_CONTROLLER: + case FALLBACK_TO_NETWORK: + // Indicate that the service worker did not respond to the request. + ServiceWorkerResponseInfo::ForRequest(request_, true) + ->OnStartCompleted( + false /* was_fetched_via_service_worker */, + false /* was_fetched_via_foreign_fetch */, + false /* was_fallback_required */, + std::vector<GURL>() /* url_list_via_service_worker */, + blink::WebServiceWorkerResponseTypeDefault, + base::TimeTicks() /* service_worker_start_time */, + base::TimeTicks() /* service_worker_ready_time */, + false /* response_is_in_cache_storage */, + std::string() /* response_cache_storage_cache_name */, + ServiceWorkerHeaderList() /* cors_exposed_header_names */); + break; + case FALLBACK_TO_RENDERER: + case FORWARD_TO_SERVICE_WORKER: + // Indicate that the service worker responded to the request, which is + // considered true if "fallback to renderer" was required since the + // renderer expects that. + ServiceWorkerResponseInfo::ForRequest(request_, true) + ->OnStartCompleted( + true /* was_fetched_via_service_worker */, + fetch_type_ == ServiceWorkerFetchType::FOREIGN_FETCH, + fall_back_required_, response_url_list_, + service_worker_response_type_, worker_start_time_, + worker_ready_time_, response_is_in_cache_storage_, + response_cache_storage_cache_name_, cors_exposed_header_names_); + break; } - ServiceWorkerResponseInfo::ForRequest(request_, true) - ->OnStartCompleted(true /* was_fetched_via_service_worker */, - fetch_type_ == ServiceWorkerFetchType::FOREIGN_FETCH, - fall_back_required_, response_url_list_, - service_worker_response_type_, worker_start_time_, - worker_ready_time_, response_is_in_cache_storage_, - response_cache_storage_cache_name_, - cors_exposed_header_names_); } bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const {
diff --git a/content/browser/service_worker/service_worker_url_request_job.h b/content/browser/service_worker/service_worker_url_request_job.h index 5eb8f00..89703fe 100644 --- a/content/browser/service_worker/service_worker_url_request_job.h +++ b/content/browser/service_worker/service_worker_url_request_job.h
@@ -114,6 +114,10 @@ void FallbackToNetwork(); void FallbackToNetworkOrRenderer(); void ForwardToServiceWorker(); + // Tells the job to abort with a start error. Currently this is only called + // because the controller was lost. This function could be made more generic + // if needed later. + void FailDueToLostController(); bool ShouldFallbackToNetwork() const { return response_type_ == FALLBACK_TO_NETWORK; @@ -145,12 +149,15 @@ private: class FileSizeResolver; + FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTestP, + LostActiveVersion); enum ResponseType { NOT_DETERMINED, + FAIL_DUE_TO_LOST_CONTROLLER, FALLBACK_TO_NETWORK, FALLBACK_TO_RENDERER, // Use this when falling back with CORS check - FORWARD_TO_SERVICE_WORKER, + FORWARD_TO_SERVICE_WORKER }; enum ResponseBodyType {
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc index 6e518ae..0ce78e4 100644 --- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc +++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -291,7 +291,7 @@ void MainResourceLoadFailed() override { CHECK(provider_host_); // Detach the controller so subresource requests also skip the worker. - provider_host_->NotifyControllerLost(false /* was_deleted */); + provider_host_->NotifyControllerLost(); } // Runs a request where the active worker starts a request in ACTIVATING state
diff --git a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc index 9215ade..d1e2328f2 100644 --- a/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc +++ b/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -293,7 +293,7 @@ std::unique_ptr<ServiceWorkerProviderHost> host( new ServiceWorkerProviderHost( process_id, MSG_ROUTING_NONE, provider_id, - SERVICE_WORKER_PROVIDER_FOR_WORKER, + SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, ServiceWorkerProviderHost::FrameSecurityLevel::SECURE, context()->AsWeakPtr(), nullptr)); base::WeakPtr<ServiceWorkerProviderHost> provider_host = host->AsWeakPtr();
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 50100a9..8e9e914 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -73,9 +73,9 @@ HostZoomLevelContext* GetHostZoomLevelContext() override; ZoomLevelDelegate* GetZoomLevelDelegate() override; PlatformNotificationContextImpl* GetPlatformNotificationContext() override; + PaymentAppContextImpl* GetPaymentAppContext() override; BackgroundSyncContext* GetBackgroundSyncContext(); - PaymentAppContextImpl* GetPaymentAppContext(); BroadcastChannelProvider* GetBroadcastChannelProvider(); // mojom::StoragePartitionService interface.
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index 3cbc9ff..24afd8a 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -483,9 +483,14 @@ } if (value) { request_info->is_deferred = value; + if (request_info->url_loader_client) + request_info->url_loader_client->SetDefersLoading(); } else if (request_info->is_deferred) { request_info->is_deferred = false; + if (request_info->url_loader_client) + request_info->url_loader_client->UnsetDefersLoading(); + FollowPendingRedirect(request_id, request_info); main_thread_task_runner_->PostTask( @@ -553,6 +558,13 @@ PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); if (!request_info || request_info->is_deferred) return; + + if (request_info->url_loader) { + DCHECK(request_info->deferred_message_queue.empty()); + request_info->url_loader_client->FlushDeferredMessages(); + return; + } + // Because message handlers could result in request_info being destroyed, // we need to work with a stack reference to the deferred queue. MessageQueue q;
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h index 39557b2..8e4c212 100644 --- a/content/child/resource_dispatcher.h +++ b/content/child/resource_dispatcher.h
@@ -153,6 +153,7 @@ void OnTransferSizeUpdated(int request_id, int32_t transfer_size_diff); private: + friend class URLLoaderClientImpl; friend class URLResponseBodyConsumer; friend class ResourceDispatcherTest;
diff --git a/content/child/test_request_peer.cc b/content/child/test_request_peer.cc index 25200d53..47add960 100644 --- a/content/child/test_request_peer.cc +++ b/content/child/test_request_peer.cc
@@ -68,6 +68,8 @@ if (context_->cancelled) return; context_->total_encoded_data_length += transfer_size_diff; + if (context_->defer_on_transfer_size_updated) + dispatcher_->SetDefersLoading(context_->request_id, true); } void TestRequestPeer::OnCompletedRequest(int error_code,
diff --git a/content/child/test_request_peer.h b/content/child/test_request_peer.h index 81162ac..e076b0d 100644 --- a/content/child/test_request_peer.h +++ b/content/child/test_request_peer.h
@@ -65,6 +65,8 @@ // Total encoded data length, regardless of whether downloading to a file or // not. int total_encoded_data_length = 0; + bool defer_on_transfer_size_updated = false; + // Total length when downloading to a file. int total_downloaded_data_length = 0;
diff --git a/content/child/url_loader_client_impl.cc b/content/child/url_loader_client_impl.cc index b9305043..04aee61 100644 --- a/content/child/url_loader_client_impl.cc +++ b/content/child/url_loader_client_impl.cc
@@ -21,7 +21,8 @@ : binding_(this), request_id_(request_id), resource_dispatcher_(resource_dispatcher), - task_runner_(std::move(task_runner)) {} + task_runner_(std::move(task_runner)), + weak_factory_(this) {} URLLoaderClientImpl::~URLLoaderClientImpl() { if (body_consumer_) @@ -34,6 +35,81 @@ binding_.Bind(client_ptr_info, associated_group); } +void URLLoaderClientImpl::SetDefersLoading() { + is_deferred_ = true; + if (body_consumer_) + body_consumer_->SetDefersLoading(); +} + +void URLLoaderClientImpl::UnsetDefersLoading() { + is_deferred_ = false; +} + +void URLLoaderClientImpl::FlushDeferredMessages() { + DCHECK(!is_deferred_); + std::vector<IPC::Message> messages; + messages.swap(deferred_messages_); + bool has_completion_message = false; + base::WeakPtr<URLLoaderClientImpl> weak_this = weak_factory_.GetWeakPtr(); + // First, dispatch all messages excluding the followings: + // - response body (dispatched by |body_consumer_|) + // - transfer size change (dispatched later) + // - completion (dispatched by |body_consumer_| or dispatched later) + for (size_t index = 0; index < messages.size(); ++index) { + if (messages[index].type() == ResourceMsg_RequestComplete::ID) { + // The completion message arrives at the end of the message queue. + DCHECK(!has_completion_message); + DCHECK_EQ(index, messages.size() - 1); + has_completion_message = true; + break; + } + Dispatch(messages[index]); + if (!weak_this) + return; + if (is_deferred_) { + deferred_messages_.insert(deferred_messages_.begin(), + messages.begin() + index + 1, messages.end()); + return; + } + } + + // Dispatch the transfer size update. + if (accumulated_transfer_size_diff_during_deferred_ > 0) { + auto transfer_size_diff = accumulated_transfer_size_diff_during_deferred_; + accumulated_transfer_size_diff_during_deferred_ = 0; + resource_dispatcher_->OnTransferSizeUpdated(request_id_, + transfer_size_diff); + if (!weak_this) + return; + if (is_deferred_) { + if (has_completion_message) { + DCHECK_GT(messages.size(), 0u); + DCHECK_EQ(messages.back().type(), + static_cast<uint32_t>(ResourceMsg_RequestComplete::ID)); + deferred_messages_.emplace_back(std::move(messages.back())); + } + return; + } + } + + if (body_consumer_) { + // When we have |body_consumer_|, the completion message is dispatched by + // it, not by this object. + DCHECK(!has_completion_message); + // Dispatch the response body. + body_consumer_->UnsetDefersLoading(); + return; + } + + // Dispatch the completion message. + if (has_completion_message) { + DCHECK_GT(messages.size(), 0u); + DCHECK_EQ(messages.back().type(), + static_cast<uint32_t>(ResourceMsg_RequestComplete::ID)); + Dispatch(messages.back()); + } +} + void URLLoaderClientImpl::OnReceiveResponse( const ResourceResponseHead& response_head, mojom::DownloadedTempFilePtr downloaded_file) { @@ -59,8 +135,12 @@ } void URLLoaderClientImpl::OnTransferSizeUpdated(int32_t transfer_size_diff) { - resource_dispatcher_->OnTransferSizeUpdated(request_id_, - transfer_size_diff); + if (is_deferred_) { + accumulated_transfer_size_diff_during_deferred_ += transfer_size_diff; + } else { + resource_dispatcher_->OnTransferSizeUpdated(request_id_, + transfer_size_diff); + } } void URLLoaderClientImpl::OnStartLoadingResponseBody( @@ -70,6 +150,8 @@ request_id_, resource_dispatcher_, std::move(body), task_runner_); if (has_received_response_) body_consumer_->Start(); + if (is_deferred_) + body_consumer_->SetDefersLoading(); } void URLLoaderClientImpl::OnComplete( @@ -82,7 +164,14 @@ } void URLLoaderClientImpl::Dispatch(const IPC::Message& message) { - resource_dispatcher_->OnMessageReceived(message); + if (is_deferred_) { + deferred_messages_.push_back(message); + } else if (deferred_messages_.size() > 0) { + deferred_messages_.push_back(message); + FlushDeferredMessages(); + } else { + resource_dispatcher_->DispatchMessage(message); + } } } // namespace content
diff --git a/content/child/url_loader_client_impl.h b/content/child/url_loader_client_impl.h index 3710c07..ada64af 100644 --- a/content/child/url_loader_client_impl.h +++ b/content/child/url_loader_client_impl.h
@@ -6,8 +6,10 @@ #define CONTENT_CHILD_URL_LOADER_CLIENT_IMPL_H_ #include <stdint.h> +#include <vector> #include "base/callback_forward.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "content/common/content_export.h" #include "content/common/url_loader.mojom.h" #include "ipc/ipc_message.h" @@ -42,6 +44,16 @@ void Bind(mojom::URLLoaderClientAssociatedPtrInfo* client_ptr_info, mojo::AssociatedGroup* associated_group); + // Sets |is_deferred_|. From now, the received messages are not dispatched + // to clients until UnsetDefersLoading is called. + void SetDefersLoading(); + + // Unsets |is_deferred_|. + void UnsetDefersLoading(); + + // Disaptches the messages received after SetDefersLoading is called. + void FlushDeferredMessages(); + // mojom::URLLoaderClient implementation void OnReceiveResponse(const ResourceResponseHead& response_head, mojom::DownloadedTempFilePtr downloaded_file) override; @@ -53,16 +65,20 @@ mojo::ScopedDataPipeConsumerHandle body) override; void OnComplete(const ResourceRequestCompletionStatus& status) override; -private: + private: void Dispatch(const IPC::Message& message); mojo::AssociatedBinding<mojom::URLLoaderClient> binding_; scoped_refptr<URLResponseBodyConsumer> body_consumer_; mojom::DownloadedTempFilePtr downloaded_file_; + std::vector<IPC::Message> deferred_messages_; const int request_id_; bool has_received_response_ = false; + bool is_deferred_ = false; + int32_t accumulated_transfer_size_diff_during_deferred_ = 0; ResourceDispatcher* const resource_dispatcher_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::WeakPtrFactory<URLLoaderClientImpl> weak_factory_; }; } // namespace content
diff --git a/content/child/url_loader_client_impl_unittest.cc b/content/child/url_loader_client_impl_unittest.cc index cec32a7..a26febf 100644 --- a/content/child/url_loader_client_impl_unittest.cc +++ b/content/child/url_loader_client_impl_unittest.cc
@@ -351,4 +351,221 @@ EXPECT_TRUE(request_peer_context_.cancelled); } +TEST_F(URLLoaderClientImplTest, Defer) { + ResourceResponseHead response_head; + ResourceRequestCompletionStatus completion_status; + + url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnComplete(completion_status); + + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + + dispatcher_->SetDefersLoading(request_id_, true); + + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + + dispatcher_->SetDefersLoading(request_id_, false); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(request_peer_context_.received_response); + EXPECT_TRUE(request_peer_context_.complete); +} + +TEST_F(URLLoaderClientImplTest, DeferWithResponseBody) { + ResourceResponseHead response_head; + ResourceRequestCompletionStatus completion_status; + + url_loader_client_->OnReceiveResponse(response_head, nullptr); + mojo::DataPipe data_pipe(DataPipeOptions()); + uint32_t size = 5; + MojoResult result = + mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, + MOJO_WRITE_DATA_FLAG_NONE); + ASSERT_EQ(MOJO_RESULT_OK, result); + EXPECT_EQ(5u, size); + data_pipe.producer_handle.reset(); + + url_loader_client_->OnStartLoadingResponseBody( + std::move(data_pipe.consumer_handle)); + url_loader_client_->OnComplete(completion_status); + + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + + dispatcher_->SetDefersLoading(request_id_, true); + + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + + dispatcher_->SetDefersLoading(request_id_, false); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(request_peer_context_.received_response); + EXPECT_TRUE(request_peer_context_.complete); + EXPECT_EQ("hello", request_peer_context_.data); +} + +// As "transfer size update" message is handled specially in the implementation, +// we have a separate test. +TEST_F(URLLoaderClientImplTest, DeferWithTransferSizeUpdated) { + ResourceResponseHead response_head; + ResourceRequestCompletionStatus completion_status; + + url_loader_client_->OnReceiveResponse(response_head, nullptr); + mojo::DataPipe data_pipe(DataPipeOptions()); + uint32_t size = 5; + MojoResult result = + mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, + MOJO_WRITE_DATA_FLAG_NONE); + ASSERT_EQ(MOJO_RESULT_OK, result); + EXPECT_EQ(5u, size); + data_pipe.producer_handle.reset(); + + url_loader_client_->OnStartLoadingResponseBody( + std::move(data_pipe.consumer_handle)); + url_loader_client_->OnTransferSizeUpdated(4); + url_loader_client_->OnComplete(completion_status); + + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + dispatcher_->SetDefersLoading(request_id_, true); + + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + dispatcher_->SetDefersLoading(request_id_, false); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(request_peer_context_.received_response); + EXPECT_TRUE(request_peer_context_.complete); + EXPECT_EQ("hello", request_peer_context_.data); + EXPECT_EQ(4, request_peer_context_.total_encoded_data_length); +} + +TEST_F(URLLoaderClientImplTest, SetDeferredDuringFlushingDeferredMessage) { + request_peer_context_.defer_on_redirect = true; + + net::RedirectInfo redirect_info; + ResourceResponseHead response_head; + ResourceRequestCompletionStatus completion_status; + + url_loader_client_->OnReceiveRedirect(redirect_info, response_head); + url_loader_client_->OnReceiveResponse(response_head, nullptr); + mojo::DataPipe data_pipe(DataPipeOptions()); + uint32_t size = 5; + MojoResult result = + mojo::WriteDataRaw(data_pipe.producer_handle.get(), "hello", &size, + MOJO_WRITE_DATA_FLAG_NONE); + ASSERT_EQ(MOJO_RESULT_OK, result); + EXPECT_EQ(5u, size); + data_pipe.producer_handle.reset(); + + url_loader_client_->OnStartLoadingResponseBody( + std::move(data_pipe.consumer_handle)); + url_loader_client_->OnTransferSizeUpdated(4); + url_loader_client_->OnComplete(completion_status); + + EXPECT_EQ(0, request_peer_context_.seen_redirects); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + dispatcher_->SetDefersLoading(request_id_, true); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(0, request_peer_context_.seen_redirects); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + dispatcher_->SetDefersLoading(request_id_, false); + EXPECT_EQ(0, request_peer_context_.seen_redirects); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, request_peer_context_.seen_redirects); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ("", request_peer_context_.data); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + EXPECT_FALSE(request_peer_context_.cancelled); + + dispatcher_->SetDefersLoading(request_id_, false); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, request_peer_context_.seen_redirects); + EXPECT_TRUE(request_peer_context_.received_response); + EXPECT_TRUE(request_peer_context_.complete); + EXPECT_EQ("hello", request_peer_context_.data); + EXPECT_EQ(4, request_peer_context_.total_encoded_data_length); + EXPECT_FALSE(request_peer_context_.cancelled); +} + +TEST_F(URLLoaderClientImplTest, + SetDeferredDuringFlushingDeferredMessageOnTransferSizeUpdated) { + request_peer_context_.defer_on_transfer_size_updated = true; + + ResourceResponseHead response_head; + ResourceRequestCompletionStatus completion_status; + + url_loader_client_->OnReceiveResponse(response_head, nullptr); + + url_loader_client_->OnTransferSizeUpdated(4); + url_loader_client_->OnComplete(completion_status); + + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + dispatcher_->SetDefersLoading(request_id_, true); + + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + dispatcher_->SetDefersLoading(request_id_, false); + EXPECT_FALSE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(request_peer_context_.received_response); + EXPECT_FALSE(request_peer_context_.complete); + EXPECT_EQ(4, request_peer_context_.total_encoded_data_length); + EXPECT_FALSE(request_peer_context_.cancelled); + + dispatcher_->SetDefersLoading(request_id_, false); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(request_peer_context_.received_response); + EXPECT_TRUE(request_peer_context_.complete); + EXPECT_EQ(4, request_peer_context_.total_encoded_data_length); + EXPECT_FALSE(request_peer_context_.cancelled); +} + } // namespace content
diff --git a/content/child/url_response_body_consumer.cc b/content/child/url_response_body_consumer.cc index 9d5c017..5014eeb 100644 --- a/content/child/url_response_body_consumer.cc +++ b/content/child/url_response_body_consumer.cc
@@ -76,6 +76,15 @@ handle_watcher_.Cancel(); } +void URLResponseBodyConsumer::SetDefersLoading() { + is_deferred_ = true; +} + +void URLResponseBodyConsumer::UnsetDefersLoading() { + is_deferred_ = false; + OnReadable(MOJO_RESULT_OK); +} + void URLResponseBodyConsumer::Reclaim(uint32_t size) { MojoResult result = mojo::EndReadDataRaw(handle_.get(), size); DCHECK_EQ(MOJO_RESULT_OK, result); @@ -89,17 +98,16 @@ } void URLResponseBodyConsumer::OnReadable(MojoResult unused) { - DCHECK(!is_in_on_readable_); - - if (has_been_cancelled_ || has_seen_end_of_data_) + if (has_been_cancelled_ || has_seen_end_of_data_ || is_deferred_) return; + DCHECK(!is_in_on_readable_); + // Protect |this| as RequestPeer::OnReceivedData may call deref. scoped_refptr<URLResponseBodyConsumer> protect(this); base::AutoReset<bool> is_in_on_readable(&is_in_on_readable_, true); - // TODO(yhirano): Suppress notification when deferred. - while (!has_been_cancelled_) { + while (!has_been_cancelled_ && !is_deferred_) { const void* buffer = nullptr; uint32_t available = 0; MojoResult result = mojo::BeginReadDataRaw( @@ -134,7 +142,7 @@ // Cancel this instance in order not to notify twice. Cancel(); - resource_dispatcher_->OnMessageReceived( + resource_dispatcher_->DispatchMessage( ResourceMsg_RequestComplete(request_id_, completion_status_)); // |this| may be deleted. }
diff --git a/content/child/url_response_body_consumer.h b/content/child/url_response_body_consumer.h index 09a988bdd..1947cb66 100644 --- a/content/child/url_response_body_consumer.h +++ b/content/child/url_response_body_consumer.h
@@ -51,6 +51,9 @@ // cancelled or done. void Cancel(); + void SetDefersLoading(); + void UnsetDefersLoading(); + private: friend class base::RefCounted<URLResponseBodyConsumer>; ~URLResponseBodyConsumer(); @@ -71,6 +74,7 @@ bool has_received_completion_ = false; bool has_been_cancelled_ = false; bool has_seen_end_of_data_; + bool is_deferred_ = false; bool is_in_on_readable_ = false; DISALLOW_COPY_AND_ASSIGN(URLResponseBodyConsumer);
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h index 909b370..9cb62329 100644 --- a/content/public/browser/storage_partition.h +++ b/content/public/browser/storage_partition.h
@@ -47,6 +47,7 @@ class HostZoomLevelContext; class HostZoomMap; class IndexedDBContext; +class PaymentAppContext; class PlatformNotificationContext; class ServiceWorkerContext; class ZoomLevelDelegate; @@ -74,6 +75,7 @@ virtual HostZoomLevelContext* GetHostZoomLevelContext() = 0; virtual ZoomLevelDelegate* GetZoomLevelDelegate() = 0; virtual PlatformNotificationContext* GetPlatformNotificationContext() = 0; + virtual PaymentAppContext* GetPaymentAppContext() = 0; enum : uint32_t { REMOVE_DATA_MASK_APPCACHE = 1 << 0,
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index b90db49..2823565 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -279,8 +279,6 @@ "origin_trials/web_trial_token_validator_impl.h", "peripheral_content_heuristic.cc", "peripheral_content_heuristic.h", - "presentation/presentation_connection_client.cc", - "presentation/presentation_connection_client.h", "presentation/presentation_dispatcher.cc", "presentation/presentation_dispatcher.h", "push_messaging/push_messaging_dispatcher.cc",
diff --git a/content/renderer/presentation/presentation_connection_client.cc b/content/renderer/presentation/presentation_connection_client.cc deleted file mode 100644 index 145e08d..0000000 --- a/content/renderer/presentation/presentation_connection_client.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2015 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. - -#include "content/renderer/presentation/presentation_connection_client.h" - -#include "base/logging.h" -#include "third_party/WebKit/public/platform/WebString.h" -#include "third_party/WebKit/public/platform/WebURL.h" - -namespace content { - -PresentationConnectionClient::PresentationConnectionClient( - blink::mojom::PresentationSessionInfoPtr session_info) - : url_(session_info->url), - id_(blink::WebString::fromUTF8(session_info->id)) {} - -PresentationConnectionClient::PresentationConnectionClient( - const GURL& url, - const mojo::String& id) - : url_(url), - id_(blink::WebString::fromUTF8(id)) {} - -PresentationConnectionClient::~PresentationConnectionClient() { -} - -blink::WebURL PresentationConnectionClient::getUrl() { - return url_; -} - -blink::WebString PresentationConnectionClient::getId() { - return id_; -} - -} // namespace content
diff --git a/content/renderer/presentation/presentation_connection_client.h b/content/renderer/presentation/presentation_connection_client.h deleted file mode 100644 index f8e0bac0..0000000 --- a/content/renderer/presentation/presentation_connection_client.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2015 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. - -#ifndef CONTENT_RENDERER_PRESENTATION_PRESENTATION_SESSION_CLIENT_H_ -#define CONTENT_RENDERER_PRESENTATION_PRESENTATION_SESSION_CLIENT_H_ - -#include "base/compiler_specific.h" -#include "content/common/content_export.h" -#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionClient.h" -#include "third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h" -#include "url/gurl.h" - -namespace content { - -// PresentationConnectionClient is passed to the Blink layer if presentation -// session has been created successfully. Owned by the callback. -class CONTENT_EXPORT PresentationConnectionClient - : public NON_EXPORTED_BASE(blink::WebPresentationConnectionClient) { - public: - explicit PresentationConnectionClient( - blink::mojom::PresentationSessionInfoPtr session_info); - explicit PresentationConnectionClient(const GURL& url, - const mojo::String& id); - ~PresentationConnectionClient() override; - - // WebPresentationConnectionClient implementation. - blink::WebURL getUrl() override; - blink::WebString getId() override; - - private: - blink::WebURL url_; - blink::WebString id_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_PRESENTATION_PRESENTATION_SESSION_CLIENT_H_
diff --git a/content/renderer/presentation/presentation_dispatcher.cc b/content/renderer/presentation/presentation_dispatcher.cc index 77a1fca..2e084ee 100644 --- a/content/renderer/presentation/presentation_dispatcher.cc +++ b/content/renderer/presentation/presentation_dispatcher.cc
@@ -14,7 +14,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/public/common/presentation_constants.h" #include "content/public/renderer/render_frame.h" -#include "content/renderer/presentation/presentation_connection_client.h" +#include "mojo/public/cpp/bindings/type_converter.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" @@ -23,10 +23,26 @@ #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationError.h" #include "third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h" +#include "third_party/WebKit/public/platform/modules/presentation/WebPresentationSessionInfo.h" #include "third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "url/gurl.h" +namespace mojo { + +// Temporary type converter since Presentation API has not been Onion Soup-ed. +template <> +struct TypeConverter<blink::WebPresentationSessionInfo, + blink::mojom::PresentationSessionInfoPtr> { + static blink::WebPresentationSessionInfo Convert( + const blink::mojom::PresentationSessionInfoPtr& input) { + return blink::WebPresentationSessionInfo( + blink::WebURL(input->url), blink::WebString::fromUTF8(input->id)); + } +}; + +} // namespace mojo + namespace { blink::WebPresentationError::ErrorType GetWebPresentationErrorTypeFromMojo( @@ -105,7 +121,7 @@ void PresentationDispatcher::startSession( const blink::WebVector<blink::WebURL>& presentationUrls, - std::unique_ptr<blink::WebPresentationConnectionClientCallbacks> callback) { + std::unique_ptr<blink::WebPresentationConnectionCallback> callback) { DCHECK(callback); ConnectToPresentationServiceIfNeeded(); @@ -124,7 +140,7 @@ void PresentationDispatcher::joinSession( const blink::WebVector<blink::WebURL>& presentationUrls, const blink::WebString& presentationId, - std::unique_ptr<blink::WebPresentationConnectionClientCallbacks> callback) { + std::unique_ptr<blink::WebPresentationConnectionCallback> callback) { DCHECK(callback); ConnectToPresentationServiceIfNeeded(); @@ -380,12 +396,12 @@ if (!session_info.is_null()) { presentation_service_->ListenForConnectionMessages(session_info.Clone()); controller_->didStartDefaultSession( - new PresentationConnectionClient(std::move(session_info))); + mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info)); } } void PresentationDispatcher::OnSessionCreated( - std::unique_ptr<blink::WebPresentationConnectionClientCallbacks> callback, + std::unique_ptr<blink::WebPresentationConnectionCallback> callback, blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationErrorPtr error) { DCHECK(callback); @@ -400,39 +416,37 @@ DCHECK(!session_info.is_null()); presentation_service_->ListenForConnectionMessages(session_info.Clone()); callback->onSuccess( - base::MakeUnique<PresentationConnectionClient>(std::move(session_info))); + mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info)); } void PresentationDispatcher::OnReceiverConnectionAvailable( blink::mojom::PresentationSessionInfoPtr session_info) { if (receiver_) { receiver_->onReceiverConnectionAvailable( - new PresentationConnectionClient(std::move(session_info))); + mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info)); } } void PresentationDispatcher::OnConnectionStateChanged( - blink::mojom::PresentationSessionInfoPtr connection, + blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationConnectionState state) { if (!controller_) return; - DCHECK(!connection.is_null()); controller_->didChangeSessionState( - new PresentationConnectionClient(std::move(connection)), + mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info), GetWebPresentationConnectionStateFromMojo(state)); } void PresentationDispatcher::OnConnectionClosed( - blink::mojom::PresentationSessionInfoPtr connection, + blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationConnectionCloseReason reason, const std::string& message) { if (!controller_) return; - DCHECK(!connection.is_null()); controller_->didCloseConnection( - new PresentationConnectionClient(std::move(connection)), + mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info), GetWebPresentationConnectionCloseReasonFromMojo(reason), blink::WebString::fromUTF8(message)); } @@ -446,20 +460,20 @@ for (size_t i = 0; i < messages.size(); ++i) { // Note: Passing batches of messages to the Blink layer would be more // efficient. - std::unique_ptr<PresentationConnectionClient> session_client( - new PresentationConnectionClient(session_info->url, session_info->id)); + auto web_session_info = + mojo::ConvertTo<blink::WebPresentationSessionInfo>(session_info); switch (messages[i]->type) { case blink::mojom::PresentationMessageType::TEXT: { // TODO(mfoltz): Do we need to DCHECK(messages[i]->message)? controller_->didReceiveSessionTextMessage( - session_client.release(), + web_session_info, blink::WebString::fromUTF8(messages[i]->message.value())); break; } case blink::mojom::PresentationMessageType::BINARY: { // TODO(mfoltz): Do we need to DCHECK(messages[i]->data)? controller_->didReceiveSessionBinaryMessage( - session_client.release(), &(messages[i]->data->front()), + web_session_info, &(messages[i]->data->front()), messages[i]->data->size()); break; }
diff --git a/content/renderer/presentation/presentation_dispatcher.h b/content/renderer/presentation/presentation_dispatcher.h index 03cdf46..91dba49 100644 --- a/content/renderer/presentation/presentation_dispatcher.h +++ b/content/renderer/presentation/presentation_dispatcher.h
@@ -71,15 +71,13 @@ void setController(blink::WebPresentationController* controller) override; void setReceiver(blink::WebPresentationReceiver*) override; - void startSession( - const blink::WebVector<blink::WebURL>& presentationUrls, - std::unique_ptr<blink::WebPresentationConnectionClientCallbacks> callback) - override; - void joinSession( - const blink::WebVector<blink::WebURL>& presentationUrls, - const blink::WebString& presentationId, - std::unique_ptr<blink::WebPresentationConnectionClientCallbacks> callback) - override; + void startSession(const blink::WebVector<blink::WebURL>& presentationUrls, + std::unique_ptr<blink::WebPresentationConnectionCallback> + callback) override; + void joinSession(const blink::WebVector<blink::WebURL>& presentationUrls, + const blink::WebString& presentationId, + std::unique_ptr<blink::WebPresentationConnectionCallback> + callback) override; void sendString(const blink::WebURL& presentationUrl, const blink::WebString& presentationId, const blink::WebString& message) override; @@ -114,10 +112,10 @@ void OnScreenAvailabilityNotSupported(const GURL& url) override; void OnScreenAvailabilityUpdated(const GURL& url, bool available) override; void OnConnectionStateChanged( - blink::mojom::PresentationSessionInfoPtr connection, + blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationConnectionState state) override; void OnConnectionClosed( - blink::mojom::PresentationSessionInfoPtr connection, + blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationConnectionCloseReason reason, const std::string& message) override; void OnConnectionMessagesReceived( @@ -127,7 +125,7 @@ blink::mojom::PresentationSessionInfoPtr session_info) override; void OnSessionCreated( - std::unique_ptr<blink::WebPresentationConnectionClientCallbacks> callback, + std::unique_ptr<blink::WebPresentationConnectionCallback> callback, blink::mojom::PresentationSessionInfoPtr session_info, blink::mojom::PresentationErrorPtr error); void OnReceiverConnectionAvailable(
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc index 6b93df46..56d598fc 100644 --- a/gpu/config/gpu_driver_bug_list_json.cc +++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -200,9 +200,9 @@ { "id": 31, "cr_bugs": [154715, 10068, 269829, 294779, 285292], - "description": "The Mali-Txxx driver does not guarantee flush ordering", + "description": "The Mali-xxx driver does not guarantee flush ordering", "gl_vendor": "ARM.*", - "gl_renderer": "Mali-T.*", + "gl_renderer": "Mali.*", "features": [ "use_virtualized_gl_contexts" ]
diff --git a/ios/chrome/browser/reading_list/reading_list_web_state_observer.mm b/ios/chrome/browser/reading_list/reading_list_web_state_observer.mm index 6d2277e..db32a0a3 100644 --- a/ios/chrome/browser/reading_list/reading_list_web_state_observer.mm +++ b/ios/chrome/browser/reading_list/reading_list_web_state_observer.mm
@@ -7,6 +7,7 @@ #import <Foundation/Foundation.h> #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "components/reading_list/ios/reading_list_model.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" @@ -200,6 +201,7 @@ if (load_completion_status == web::PageLoadCompletionStatus::SUCCESS) { reading_list_model_->SetReadStatus(pending_url_, true); + UMA_HISTOGRAM_BOOLEAN("ReadingList.OfflineVersionDisplayed", false); } else { LoadOfflineReadingListEntry(item); } @@ -272,4 +274,5 @@ item->SetVirtualURL(pending_url_); web_state()->GetNavigationManager()->Reload(false); reading_list_model_->SetReadStatus(entry->URL(), true); + UMA_HISTOGRAM_BOOLEAN("ReadingList.OfflineVersionDisplayed", true); }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h index 29a5a46..ddcb471 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Binding.h +++ b/third_party/WebKit/Source/bindings/core/v8/V8Binding.h
@@ -658,9 +658,7 @@ inline v8::MaybeLocal<v8::Value> v8DateOrNaN(v8::Isolate* isolate, double value) { ASSERT(isolate); - return v8::Date::New( - isolate->GetCurrentContext(), - std::isfinite(value) ? value : std::numeric_limits<double>::quiet_NaN()); + return v8::Date::New(isolate->GetCurrentContext(), value); } // FIXME: Remove the special casing for NodeFilter and XPathNSResolver.
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp index 67f98aace..cbcb2d105 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.cpp
@@ -25,7 +25,6 @@ #include "modules/presentation/PresentationController.h" #include "modules/presentation/PresentationReceiver.h" #include "modules/presentation/PresentationRequest.h" -#include "public/platform/modules/presentation/WebPresentationConnectionClient.h" #include "wtf/Assertions.h" #include "wtf/text/AtomicString.h" #include <memory> @@ -163,10 +162,9 @@ // static PresentationConnection* PresentationConnection::take( ScriptPromiseResolver* resolver, - std::unique_ptr<WebPresentationConnectionClient> client, + const WebPresentationSessionInfo& sessionInfo, PresentationRequest* request) { ASSERT(resolver); - ASSERT(client); ASSERT(request); ASSERT(resolver->getExecutionContext()->isDocument()); @@ -179,19 +177,19 @@ if (!controller) return nullptr; - return take(controller, std::move(client), request); + return take(controller, sessionInfo, request); } // static PresentationConnection* PresentationConnection::take( PresentationController* controller, - std::unique_ptr<WebPresentationConnectionClient> client, + const WebPresentationSessionInfo& sessionInfo, PresentationRequest* request) { ASSERT(controller); ASSERT(request); PresentationConnection* connection = new PresentationConnection( - controller->frame(), client->getId(), client->getUrl()); + controller->frame(), sessionInfo.id, sessionInfo.url); controller->registerConnection(connection); // Fire onconnectionavailable event asynchronously. @@ -208,12 +206,11 @@ // static PresentationConnection* PresentationConnection::take( PresentationReceiver* receiver, - std::unique_ptr<WebPresentationConnectionClient> client) { + const WebPresentationSessionInfo& sessionInfo) { DCHECK(receiver); - DCHECK(client); PresentationConnection* connection = new PresentationConnection( - receiver->frame(), client->getId(), client->getUrl()); + receiver->frame(), sessionInfo.id, sessionInfo.url); receiver->registerConnection(connection); return connection; @@ -407,9 +404,8 @@ } bool PresentationConnection::matches( - WebPresentationConnectionClient* client) const { - return client && m_url == KURL(client->getUrl()) && - m_id == static_cast<String>(client->getId()); + const WebPresentationSessionInfo& sessionInfo) const { + return m_url == KURL(sessionInfo.url) && m_id == String(sessionInfo.id); } void PresentationConnection::didChangeState(
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnection.h b/third_party/WebKit/Source/modules/presentation/PresentationConnection.h index 2a995c3d..d09b9cd 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnection.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnection.h
@@ -11,7 +11,8 @@ #include "core/fileapi/FileError.h" #include "platform/heap/Handle.h" #include "platform/weborigin/KURL.h" -#include "public/platform/modules/presentation/WebPresentationConnectionClient.h" +#include "public/platform/modules/presentation/WebPresentationController.h" +#include "public/platform/modules/presentation/WebPresentationSessionInfo.h" #include "wtf/text/WTFString.h" #include <memory> @@ -34,19 +35,14 @@ public: // For CallbackPromiseAdapter. - using WebType = std::unique_ptr<WebPresentationConnectionClient>; - - static PresentationConnection* take( - ScriptPromiseResolver*, - std::unique_ptr<WebPresentationConnectionClient>, - PresentationRequest*); - static PresentationConnection* take( - PresentationController*, - std::unique_ptr<WebPresentationConnectionClient>, - PresentationRequest*); - static PresentationConnection* take( - PresentationReceiver*, - std::unique_ptr<WebPresentationConnectionClient>); + static PresentationConnection* take(ScriptPromiseResolver*, + const WebPresentationSessionInfo&, + PresentationRequest*); + static PresentationConnection* take(PresentationController*, + const WebPresentationSessionInfo&, + PresentationRequest*); + static PresentationConnection* take(PresentationReceiver*, + const WebPresentationSessionInfo&); ~PresentationConnection() override; // EventTarget implementation. @@ -73,9 +69,9 @@ DEFINE_ATTRIBUTE_EVENT_LISTENER(close); DEFINE_ATTRIBUTE_EVENT_LISTENER(terminate); - // Returns true if and only if the WebPresentationConnectionClient represents - // this connection. - bool matches(WebPresentationConnectionClient*) const; + // Returns true if and only if the the session info represents this + // connection. + bool matches(const WebPresentationSessionInfo&) const; // Notifies the connection about its state change. void didChangeState(WebPresentationConnectionState);
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp index a9d2404..8de07df2 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.cpp
@@ -9,7 +9,6 @@ #include "modules/presentation/PresentationConnection.h" #include "modules/presentation/PresentationError.h" #include "modules/presentation/PresentationRequest.h" -#include "public/platform/modules/presentation/WebPresentationConnectionClient.h" #include "public/platform/modules/presentation/WebPresentationError.h" #include "wtf/PtrUtil.h" #include <memory> @@ -25,16 +24,12 @@ } void PresentationConnectionCallbacks::onSuccess( - std::unique_ptr<WebPresentationConnectionClient> - PresentationConnectionClient) { - std::unique_ptr<WebPresentationConnectionClient> result( - WTF::wrapUnique(PresentationConnectionClient.release())); - + const WebPresentationSessionInfo& sessionInfo) { if (!m_resolver->getExecutionContext() || m_resolver->getExecutionContext()->isContextDestroyed()) return; - m_resolver->resolve(PresentationConnection::take( - m_resolver.get(), std::move(result), m_request)); + m_resolver->resolve( + PresentationConnection::take(m_resolver.get(), sessionInfo, m_request)); } void PresentationConnectionCallbacks::onError(
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h index 257e50b..79b33160 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationConnectionCallbacks.h
@@ -13,7 +13,7 @@ class PresentationRequest; class ScriptPromiseResolver; -class WebPresentationConnectionClient; +struct WebPresentationSessionInfo; struct WebPresentationError; // PresentationConnectionCallbacks extends WebCallbacks to resolve the @@ -21,13 +21,13 @@ // the PresentationRequest object that originated the call in its constructor // and will pass it to the created PresentationConnection. class PresentationConnectionCallbacks final - : public WebCallbacks<std::unique_ptr<WebPresentationConnectionClient>, + : public WebCallbacks<const WebPresentationSessionInfo&, const WebPresentationError&> { public: PresentationConnectionCallbacks(ScriptPromiseResolver*, PresentationRequest*); ~PresentationConnectionCallbacks() override = default; - void onSuccess(std::unique_ptr<WebPresentationConnectionClient>) override; + void onSuccess(const WebPresentationSessionInfo&) override; void onError(const WebPresentationError&) override; private:
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp index 65d4ede..0655e0f2 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationController.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationController.cpp
@@ -63,58 +63,46 @@ } void PresentationController::didStartDefaultSession( - WebPresentationConnectionClient* connectionClient) { + const WebPresentationSessionInfo& sessionInfo) { if (!m_presentation || !m_presentation->defaultRequest()) return; - PresentationConnection::take(this, WTF::wrapUnique(connectionClient), + PresentationConnection::take(this, sessionInfo, m_presentation->defaultRequest()); } void PresentationController::didChangeSessionState( - WebPresentationConnectionClient* connectionClient, + const WebPresentationSessionInfo& sessionInfo, WebPresentationConnectionState state) { - std::unique_ptr<WebPresentationConnectionClient> client = - WTF::wrapUnique(connectionClient); - - PresentationConnection* connection = findConnection(client.get()); + PresentationConnection* connection = findConnection(sessionInfo); if (!connection) return; connection->didChangeState(state); } void PresentationController::didCloseConnection( - WebPresentationConnectionClient* connectionClient, + const WebPresentationSessionInfo& sessionInfo, WebPresentationConnectionCloseReason reason, const WebString& message) { - std::unique_ptr<WebPresentationConnectionClient> client = - WTF::wrapUnique(connectionClient); - - PresentationConnection* connection = findConnection(client.get()); + PresentationConnection* connection = findConnection(sessionInfo); if (!connection) return; connection->didClose(reason, message); } void PresentationController::didReceiveSessionTextMessage( - WebPresentationConnectionClient* connectionClient, + const WebPresentationSessionInfo& sessionInfo, const WebString& message) { - std::unique_ptr<WebPresentationConnectionClient> client = - WTF::wrapUnique(connectionClient); - - PresentationConnection* connection = findConnection(client.get()); + PresentationConnection* connection = findConnection(sessionInfo); if (!connection) return; connection->didReceiveTextMessage(message); } void PresentationController::didReceiveSessionBinaryMessage( - WebPresentationConnectionClient* connectionClient, + const WebPresentationSessionInfo& sessionInfo, const uint8_t* data, size_t length) { - std::unique_ptr<WebPresentationConnectionClient> client = - WTF::wrapUnique(connectionClient); - - PresentationConnection* connection = findConnection(client.get()); + PresentationConnection* connection = findConnection(sessionInfo); if (!connection) return; connection->didReceiveBinaryMessage(data, length); @@ -149,9 +137,9 @@ } PresentationConnection* PresentationController::findConnection( - WebPresentationConnectionClient* connectionClient) { + const WebPresentationSessionInfo& sessionInfo) { for (const auto& connection : m_connections) { - if (connection->matches(connectionClient)) + if (connection->matches(sessionInfo)) return connection.get(); }
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationController.h b/third_party/WebKit/Source/modules/presentation/PresentationController.h index 9aecc0f4..80a141e 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationController.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationController.h
@@ -18,9 +18,6 @@ namespace blink { class PresentationConnection; -class WebPresentationConnectionClient; -enum class WebPresentationConnectionCloseReason; -enum class WebPresentationConnectionState; // The coordinator between the various page exposed properties and the content // layer represented via |WebPresentationClient|. @@ -48,15 +45,15 @@ DECLARE_VIRTUAL_TRACE(); // Implementation of WebPresentationController. - void didStartDefaultSession(WebPresentationConnectionClient*) override; - void didChangeSessionState(WebPresentationConnectionClient*, + void didStartDefaultSession(const WebPresentationSessionInfo&) override; + void didChangeSessionState(const WebPresentationSessionInfo&, WebPresentationConnectionState) override; - void didCloseConnection(WebPresentationConnectionClient*, + void didCloseConnection(const WebPresentationSessionInfo&, WebPresentationConnectionCloseReason, const WebString& message) override; - void didReceiveSessionTextMessage(WebPresentationConnectionClient*, + void didReceiveSessionTextMessage(const WebPresentationSessionInfo&, const WebString&) override; - void didReceiveSessionBinaryMessage(WebPresentationConnectionClient*, + void didReceiveSessionBinaryMessage(const WebPresentationSessionInfo&, const uint8_t* data, size_t length) override; @@ -81,7 +78,7 @@ // Return the connection associated with the given |connectionClient| or // null if it doesn't exist. - PresentationConnection* findConnection(WebPresentationConnectionClient*); + PresentationConnection* findConnection(const WebPresentationSessionInfo&); // The WebPresentationClient which allows communicating with the embedder. // It is not owned by the PresentationController but the controller will
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp index 9d22bcd..aa15f675 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.cpp
@@ -40,12 +40,10 @@ } void PresentationReceiver::onReceiverConnectionAvailable( - WebPresentationConnectionClient* connectionClient) { - DCHECK(connectionClient); + const WebPresentationSessionInfo& sessionInfo) { // take() will call PresentationReceiver::registerConnection() // and register the connection. - auto connection = - PresentationConnection::take(this, WTF::wrapUnique(connectionClient)); + auto connection = PresentationConnection::take(this, sessionInfo); // receiver.connectionList property not accessed if (!m_connectionListProperty)
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h index c4d3c2c..c59d67c 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h +++ b/third_party/WebKit/Source/modules/presentation/PresentationReceiver.h
@@ -20,7 +20,6 @@ class PresentationConnection; class PresentationConnectionList; class WebPresentationClient; -class WebPresentationConnectionClient; // Implements the PresentationReceiver interface from the Presentation API from // which websites can implement the receiving side of a presentation session. @@ -44,7 +43,8 @@ ScriptPromise connectionList(ScriptState*); // Implementation of WebPresentationController. - void onReceiverConnectionAvailable(WebPresentationConnectionClient*) override; + void onReceiverConnectionAvailable( + const WebPresentationSessionInfo&) override; void registerConnection(PresentationConnection*); DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp b/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp index 8ec4b95..9b6c601 100644 --- a/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp +++ b/third_party/WebKit/Source/modules/presentation/PresentationReceiverTest.cpp
@@ -11,7 +11,6 @@ #include "modules/presentation/PresentationConnectionList.h" #include "platform/testing/URLTestHelpers.h" #include "public/platform/modules/presentation/WebPresentationClient.h" -#include "public/platform/modules/presentation/WebPresentationConnectionClient.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include <memory> @@ -31,15 +30,15 @@ }; class MockWebPresentationClient : public WebPresentationClient { - void startSession(const WebVector<WebURL>& presentationUrls, - std::unique_ptr<WebPresentationConnectionClientCallbacks> - callbacks) override { + void startSession( + const WebVector<WebURL>& presentationUrls, + std::unique_ptr<WebPresentationConnectionCallback> callbacks) override { return startSession_(presentationUrls, callbacks); } - void joinSession(const WebVector<WebURL>& presentationUrls, - const WebString& presentationId, - std::unique_ptr<WebPresentationConnectionClientCallbacks> - callbacks) override { + void joinSession( + const WebVector<WebURL>& presentationUrls, + const WebString& presentationId, + std::unique_ptr<WebPresentationConnectionCallback> callbacks) override { return joinSession_(presentationUrls, presentationId, callbacks); } @@ -54,16 +53,14 @@ MOCK_METHOD1(setReceiver, void(WebPresentationReceiver*)); - MOCK_METHOD2( - startSession_, - void(const WebVector<WebURL>& presentationUrls, - std::unique_ptr<WebPresentationConnectionClientCallbacks>&)); + MOCK_METHOD2(startSession_, + void(const WebVector<WebURL>& presentationUrls, + std::unique_ptr<WebPresentationConnectionCallback>&)); - MOCK_METHOD3( - joinSession_, - void(const WebVector<WebURL>& presentationUrls, - const WebString& presentationId, - std::unique_ptr<WebPresentationConnectionClientCallbacks>&)); + MOCK_METHOD3(joinSession_, + void(const WebVector<WebURL>& presentationUrls, + const WebString& presentationId, + std::unique_ptr<WebPresentationConnectionCallback>&)); MOCK_METHOD3(sendString, void(const WebURL& presentationUrl, @@ -101,15 +98,6 @@ MOCK_METHOD1(setDefaultPresentationUrls, void(const WebVector<WebURL>&)); }; -class TestWebPresentationConnectionClient - : public WebPresentationConnectionClient { - public: - WebString getId() override { return WebString::fromUTF8("id"); } - WebURL getUrl() override { - return URLTestHelpers::toKURL("http://www.example.com"); - } -}; - class PresentationReceiverTest : public ::testing::Test { public: void addConnectionavailableEventListener(EventListener*, @@ -167,8 +155,8 @@ receiver->connectionList(scope.getScriptState()); // Receive first connection. - auto connectionClient = new TestWebPresentationConnectionClient(); - receiver->onReceiverConnectionAvailable(connectionClient); + receiver->onReceiverConnectionAvailable( + WebPresentationSessionInfo(KURL(KURL(), "http://example.com"), "id")); verifyConnectionListPropertyState(ScriptPromisePropertyBase::Resolved, receiver); @@ -185,13 +173,13 @@ EXPECT_CALL(*eventHandler, handleEvent(testing::_, testing::_)).Times(1); receiver->connectionList(scope.getScriptState()); - // Receive first connection. - auto connectionClient1 = new TestWebPresentationConnectionClient(); - receiver->onReceiverConnectionAvailable(connectionClient1); + WebPresentationSessionInfo sessionInfo(KURL(KURL(), "http://example.com"), + "id"); + // Receive first connection. + receiver->onReceiverConnectionAvailable(sessionInfo); // Receive second connection. - auto connectionClient2 = new TestWebPresentationConnectionClient(); - receiver->onReceiverConnectionAvailable(connectionClient2); + receiver->onReceiverConnectionAvailable(sessionInfo); verifyConnectionListSize(2, receiver); } @@ -205,13 +193,12 @@ addConnectionavailableEventListener(eventHandler, receiver); EXPECT_CALL(*eventHandler, handleEvent(testing::_, testing::_)).Times(0); + WebPresentationSessionInfo sessionInfo(KURL(KURL(), "http://example.com"), + "id"); // Receive first connection. - auto connectionClient1 = new TestWebPresentationConnectionClient(); - receiver->onReceiverConnectionAvailable(connectionClient1); - + receiver->onReceiverConnectionAvailable(sessionInfo); // Receive second connection. - auto connectionClient2 = new TestWebPresentationConnectionClient(); - receiver->onReceiverConnectionAvailable(connectionClient2); + receiver->onReceiverConnectionAvailable(sessionInfo); receiver->connectionList(scope.getScriptState()); verifyConnectionListPropertyState(ScriptPromisePropertyBase::Resolved,
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index 458e00b5..21de3101 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -363,9 +363,12 @@ "platform/modules/payments/WebPaymentItem.h", "platform/modules/payments/WebPaymentMethodData.h", "platform/modules/permissions/WebPermissionType.h", + "platform/modules/presentation/WebPresentationAvailabilityObserver.h", "platform/modules/presentation/WebPresentationClient.h", "platform/modules/presentation/WebPresentationController.h", "platform/modules/presentation/WebPresentationError.h", + "platform/modules/presentation/WebPresentationReceiver.h", + "platform/modules/presentation/WebPresentationSessionInfo.h", "platform/modules/push_messaging/WebPushClient.h", "platform/modules/push_messaging/WebPushError.h", "platform/modules/push_messaging/WebPushPermissionStatus.h",
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h index 41527229..1c9e7b3 100644 --- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationClient.h
@@ -14,19 +14,19 @@ class WebPresentationAvailabilityObserver; class WebPresentationController; -class WebPresentationConnectionClient; +struct WebPresentationError; class WebPresentationReceiver; +struct WebPresentationSessionInfo; class WebString; class WebURL; -struct WebPresentationError; template <typename T> class WebVector; // If session was created, callback's onSuccess() is invoked with the // information about the presentation session created by the embedder. // Otherwise, onError() is invoked with the error code and message. -using WebPresentationConnectionClientCallbacks = - WebCallbacks<std::unique_ptr<WebPresentationConnectionClient>, +using WebPresentationConnectionCallback = + WebCallbacks<const WebPresentationSessionInfo&, const WebPresentationError&>; // Callback for .getAvailability(). @@ -48,13 +48,13 @@ // Called when the frame requests to start a new session. virtual void startSession( const WebVector<WebURL>& presentationUrls, - std::unique_ptr<WebPresentationConnectionClientCallbacks>) = 0; + std::unique_ptr<WebPresentationConnectionCallback>) = 0; // Called when the frame requests to join an existing session. virtual void joinSession( const WebVector<WebURL>& presentationUrls, const WebString& presentationId, - std::unique_ptr<WebPresentationConnectionClientCallbacks>) = 0; + std::unique_ptr<WebPresentationConnectionCallback>) = 0; // Called when the frame requests to send String message to an existing // session.
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionClient.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionClient.h deleted file mode 100644 index 0ad0419d..0000000 --- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationConnectionClient.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2015 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. - -#ifndef WebPresentationConnectionClient_h -#define WebPresentationConnectionClient_h - -#include "public/platform/WebString.h" -#include "public/platform/WebURL.h" - -namespace blink { - -enum class WebPresentationConnectionState { - Connecting = 0, - Connected, - Closed, - Terminated, -}; - -enum class WebPresentationConnectionCloseReason { Error = 0, Closed, WentAway }; - -// The implementation the embedder has to provide for the Presentation API to -// work. -class WebPresentationConnectionClient { - public: - virtual ~WebPresentationConnectionClient() {} - - virtual WebString getId() = 0; - virtual WebURL getUrl() = 0; -}; - -} // namespace blink - -#endif // WebPresentationConnectionClient_h
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h index 2dcf0d3d..e59c632 100644 --- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationController.h
@@ -9,10 +9,17 @@ namespace blink { -class WebPresentationConnectionClient; +struct WebPresentationSessionInfo; class WebString; -enum class WebPresentationConnectionCloseReason; -enum class WebPresentationConnectionState; + +enum class WebPresentationConnectionCloseReason { Error = 0, Closed, WentAway }; + +enum class WebPresentationConnectionState { + Connecting = 0, + Connected, + Closed, + Terminated, +}; // The delegate Blink provides to WebPresentationClient in order to get updates. class BLINK_PLATFORM_EXPORT WebPresentationController { @@ -21,23 +28,23 @@ // Called when the presentation session is started by the embedder using // the default presentation URL and id. - virtual void didStartDefaultSession(WebPresentationConnectionClient*) = 0; + virtual void didStartDefaultSession(const WebPresentationSessionInfo&) = 0; // Called when the state of a session changes. - virtual void didChangeSessionState(WebPresentationConnectionClient*, + virtual void didChangeSessionState(const WebPresentationSessionInfo&, WebPresentationConnectionState) = 0; // Called when a connection closes. - virtual void didCloseConnection(WebPresentationConnectionClient*, + virtual void didCloseConnection(const WebPresentationSessionInfo&, WebPresentationConnectionCloseReason, const WebString& message) = 0; // Called when a text message of a session is received. - virtual void didReceiveSessionTextMessage(WebPresentationConnectionClient*, + virtual void didReceiveSessionTextMessage(const WebPresentationSessionInfo&, const WebString& message) = 0; // Called when a binary message of a session is received. - virtual void didReceiveSessionBinaryMessage(WebPresentationConnectionClient*, + virtual void didReceiveSessionBinaryMessage(const WebPresentationSessionInfo&, const uint8_t* data, size_t length) = 0; };
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h index 04ad7352e..15593441 100644 --- a/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationReceiver.h
@@ -9,7 +9,7 @@ namespace blink { -class WebPresentationConnectionClient; +struct WebPresentationSessionInfo; // The delegate Blink provides to WebPresentationReceiverClient in order to get // updates. @@ -19,7 +19,7 @@ // Called when receiver page gets an incoming connection. virtual void onReceiverConnectionAvailable( - WebPresentationConnectionClient*) = 0; + const WebPresentationSessionInfo&) = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/modules/presentation/WebPresentationSessionInfo.h b/third_party/WebKit/public/platform/modules/presentation/WebPresentationSessionInfo.h new file mode 100644 index 0000000..db04a50b --- /dev/null +++ b/third_party/WebKit/public/platform/modules/presentation/WebPresentationSessionInfo.h
@@ -0,0 +1,27 @@ +// Copyright 2015 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. + +#ifndef WebPresentationSessionInfo_h +#define WebPresentationSessionInfo_h + +#include "public/platform/WebString.h" +#include "public/platform/WebURL.h" + +namespace blink { + +// A simple wrapper around blink::mojom::PresentationSessionInfo. Since the +// presentation API has not been Onion Soup-ed, there are portions implemented +// in Blink and the embedder. Because it is not possible to use the STL and WTF +// mojo bindings alongside each other, going between Blink and the embedder +// requires this indirection. +struct WebPresentationSessionInfo { + WebPresentationSessionInfo(const WebURL& url, const WebString& id) + : url(url), id(id) {} + WebURL url; + WebString id; +}; + +} // namespace blink + +#endif // WebPresentationSessionInfo_h