diff --git a/DEPS b/DEPS index 90acccb7d..c97f40b 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'ea49cd0a053b89c31013b98a4763b9c9c75fe07a', + 'v8_revision': '165c183f7c47e7ff100baa5dd4d96948e239460b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'cddc8eddbd33e8e96540341eb9781403ae423b93', + 'pdfium_revision': '5e57faaa7fbcfe25a9b708b3972509b322f803db', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'a64c010c74cc810921c037fcf7ccee1d5c5b0c00', + 'catapult_revision': '06fd359d488b119665f6281e31b98514b0cf77a3', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.cc b/android_webview/browser/net/aw_cookie_store_wrapper.cc index 70f7b4c..17423fd 100644 --- a/android_webview/browser/net/aw_cookie_store_wrapper.cc +++ b/android_webview/browser/net/aw_cookie_store_wrapper.cc
@@ -16,8 +16,8 @@ namespace { // Posts |task| to the thread that the global CookieStore lives on. -void PostTaskToCookieStoreTaskRunner(const base::Closure& task) { - GetCookieStoreTaskRunner()->PostTask(FROM_HERE, task); +void PostTaskToCookieStoreTaskRunner(base::OnceClosure task) { + GetCookieStoreTaskRunner()->PostTask(FROM_HERE, std::move(task)); } // Wraps a subscription to cookie change notifications for the global @@ -128,6 +128,15 @@ last_access_time, secure, http_only, same_site, priority, callback); } +void SetCanonicalCookieAsyncOnCookieThread( + std::unique_ptr<net::CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const net::CookieStore::SetCookiesCallback& callback) { + GetCookieStore()->SetCanonicalCookieAsync(std::move(cookie), secure_source, + modify_http_only, callback); +} + void GetCookiesWithOptionsAsyncOnCookieThread( const GURL& url, const net::CookieOptions& options, @@ -230,6 +239,17 @@ CreateWrappedCallback<bool>(callback))); } +void AwCookieStoreWrapper::SetCanonicalCookieAsync( + std::unique_ptr<net::CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) { + DCHECK(client_task_runner_->RunsTasksOnCurrentThread()); + PostTaskToCookieStoreTaskRunner(base::BindOnce( + &SetCanonicalCookieAsyncOnCookieThread, std::move(cookie), secure_source, + modify_http_only, CreateWrappedCallback<bool>(callback))); +} + void AwCookieStoreWrapper::GetCookiesWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/android_webview/browser/net/aw_cookie_store_wrapper.h b/android_webview/browser/net/aw_cookie_store_wrapper.h index cf8bfbd..860f81a4a 100644 --- a/android_webview/browser/net/aw_cookie_store_wrapper.h +++ b/android_webview/browser/net/aw_cookie_store_wrapper.h
@@ -58,6 +58,10 @@ net::CookieSameSite same_site, net::CookiePriority priority, const SetCookiesCallback& callback) override; + void SetCanonicalCookieAsync(std::unique_ptr<net::CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) override; void GetCookiesWithOptionsAsync(const GURL& url, const net::CookieOptions& options, const GetCookiesCallback& callback) override;
diff --git a/base/logging.h b/base/logging.h index ccfb62a2..0660e7c 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -306,6 +306,9 @@ // to Clang which control what code paths are statically analyzed, // and is meant to be used in conjunction with assert & assert-like functions. // The expression is passed straight through if analysis isn't enabled. +// +// ANALYZER_SKIP_THIS_PATH() suppresses static analysis for the current +// codepath and any other branching codepaths that might follow. #if defined(__clang_analyzer__) inline constexpr bool AnalyzerNoReturn() __attribute__((analyzer_noreturn)) { @@ -318,11 +321,14 @@ return arg || AnalyzerNoReturn(); } -#define ANALYZER_ASSUME_TRUE(arg) ::logging::AnalyzerAssumeTrue(!!(arg)) +#define ANALYZER_ASSUME_TRUE(arg) logging::AnalyzerAssumeTrue(!!(arg)) +#define ANALYZER_SKIP_THIS_PATH() \ + static_cast<void>(::logging::AnalyzerNoReturn()) #else // !defined(__clang_analyzer__) #define ANALYZER_ASSUME_TRUE(arg) (arg) +#define ANALYZER_SKIP_THIS_PATH() #endif // defined(__clang_analyzer__)
diff --git a/base/memory/ref_counted.h b/base/memory/ref_counted.h index 3695f87b..56bd4025 100644 --- a/base/memory/ref_counted.h +++ b/base/memory/ref_counted.h
@@ -271,6 +271,11 @@ void Release() const { if (subtle::RefCountedBase::Release()) { + // Prune the code paths which the static analyzer may take to simulate + // object destruction. Use-after-free errors aren't possible given the + // lifetime guarantees of the refcounting system. + ANALYZER_SKIP_THIS_PATH(); + delete static_cast<const T*>(this); } } @@ -328,6 +333,7 @@ void Release() const { if (subtle::RefCountedThreadSafeBase::Release()) { + ANALYZER_SKIP_THIS_PATH(); Traits::Destruct(static_cast<const T*>(this)); } } @@ -527,13 +533,19 @@ } scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { - scoped_refptr<T>(std::move(r)).swap(*this); + scoped_refptr<T> tmp(std::move(r)); + tmp.swap(*this); return *this; } template <typename U> scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { - scoped_refptr<T>(std::move(r)).swap(*this); + // We swap with a temporary variable to guarantee that |ptr_| is released + // immediately. A naive implementation which swaps |this| and |r| would + // unintentionally extend the lifetime of |ptr_| to at least the lifetime of + // |r|. + scoped_refptr<T> tmp(std::move(r)); + tmp.swap(*this); return *this; }
diff --git a/base/memory/ref_counted_unittest.cc b/base/memory/ref_counted_unittest.cc index 62e3f54..f91fd420 100644 --- a/base/memory/ref_counted_unittest.cc +++ b/base/memory/ref_counted_unittest.cc
@@ -415,6 +415,27 @@ EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count()); } +TEST(RefCountedUnitTest, MoveAssignmentSelfMove) { + ScopedRefPtrCountBase::reset_count(); + + { + ScopedRefPtrCountBase* raw = new ScopedRefPtrCountBase; + scoped_refptr<ScopedRefPtrCountBase> p1(raw); + scoped_refptr<ScopedRefPtrCountBase>& p1_ref = p1; + + EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); + EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count()); + + p1 = std::move(p1_ref); + + // |p1| is "valid but unspecified", so don't bother inspecting its + // contents, just ensure that we don't crash. + } + + EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count()); + EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count()); +} + TEST(RefCountedUnitTest, MoveAssignmentDerived) { ScopedRefPtrCountBase::reset_count(); ScopedRefPtrCountDerived::reset_count();
diff --git a/base/process/launch_fuchsia.cc b/base/process/launch_fuchsia.cc index 21ab302..54591f9f 100644 --- a/base/process/launch_fuchsia.cc +++ b/base/process/launch_fuchsia.cc
@@ -93,17 +93,25 @@ launchpad_load_from_file(lp, argv_cstr[0]); launchpad_set_args(lp, argv.size(), argv_cstr.data()); - uint32_t to_clone = - LP_CLONE_MXIO_ROOT | LP_CLONE_MXIO_CWD | LP_CLONE_DEFAULT_JOB; + uint32_t to_clone = LP_CLONE_MXIO_ROOT | LP_CLONE_DEFAULT_JOB; std::unique_ptr<char* []> new_environ; char* const empty_environ = nullptr; char* const* old_environ = environ; if (options.clear_environ) old_environ = &empty_environ; - if (!options.environ.empty()) - new_environ = AlterEnvironment(old_environ, options.environ); - if (!options.environ.empty() || options.clear_environ) + + EnvironmentMap environ_modifications = options.environ; + if (!options.current_directory.empty()) { + environ_modifications["PWD"] = options.current_directory.value(); + } else { + to_clone |= LP_CLONE_MXIO_CWD; + } + + if (!environ_modifications.empty()) + new_environ = AlterEnvironment(old_environ, environ_modifications); + + if (!environ_modifications.empty() || options.clear_environ) launchpad_set_environ(lp, new_environ.get()); else to_clone |= LP_CLONE_ENVIRON;
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py index ea9055cf..22d0506 100755 --- a/build/android/gyp/lint.py +++ b/build/android/gyp/lint.py
@@ -23,7 +23,7 @@ def _OnStaleMd5(lint_path, config_path, processed_config_path, manifest_path, result_path, product_dir, sources, jar_path, - cache_dir, android_sdk_version, resource_sources, + cache_dir, android_sdk_version, srcjars, resource_sources, disable=None, classpath=None, can_fail_build=False, silent=False): def _RebasePath(path): @@ -150,6 +150,14 @@ cmd.extend(['--sources', _RebasePath(src_dir)]) os.symlink(os.path.abspath(src), PathInDir(src_dir, src)) + if srcjars: + srcjar_paths = build_utils.ParseGnList(srcjars) + if srcjar_paths: + srcjar_dir = _NewTempSubdir('SRC_ROOT') + cmd.extend(['--sources', _RebasePath(srcjar_dir)]) + for srcjar in srcjar_paths: + build_utils.ExtractAll(srcjar, path=srcjar_dir) + if disable: cmd.extend(['--disable', ','.join(disable)]) @@ -287,6 +295,8 @@ help='Directories containing java files.') parser.add_argument('--stamp', help='Path to touch on success.') + parser.add_argument('--srcjars', + help='GN list of included srcjars.') args = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:])) @@ -358,6 +368,7 @@ args.jar_path, args.cache_dir, args.android_sdk_version, + args.srcjars, resource_sources, disable=disable, classpath=classpath,
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index 2da62f84..c085176 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -417,6 +417,8 @@ if options.bundled_srcjars: gradle['bundled_srcjars'] = ( build_utils.ParseGnList(options.bundled_srcjars)) + else: + gradle['bundled_srcjars'] = [] gradle['dependent_android_projects'] = [] gradle['dependent_java_projects'] = []
diff --git a/build/android/lint/suppressions.xml b/build/android/lint/suppressions.xml index b7a7dda..6eebc4a 100644 --- a/build/android/lint/suppressions.xml +++ b/build/android/lint/suppressions.xml
@@ -268,6 +268,8 @@ <ignore regexp="chrome/android/chrome_strings_grd.resources.zip/values-sv/android_chrome_strings.xml"/> <ignore regexp="chrome/android/chrome_strings_grd.resources.zip/values-tl/android_chrome_strings.xml"/> </issue> + <!-- We have many C++ enums that we don't care about in java --> + <issue id="SwitchIntDef" severity="ignore"/> <issue id="TextFields" severity="Error"> <ignore regexp="chromecast/internal"/> </issue> @@ -290,6 +292,8 @@ <ignore regexp="chrome/android/chrome_strings_grd.resources.zip/values-zh-rCN/android_chrome_strings.xml"/> <ignore regexp="chrome/android/chrome_strings_grd.resources.zip/values-zh-rTW/android_chrome_strings.xml"/> </issue> + <!-- Our generated enums are allowed to have the same values. --> + <issue id="UniqueConstants" severity="ignore"/> <!-- TODO(crbug.com/635567): Fix this properly. --> <issue id="UnusedResources" severity="ignore"/> <issue id="UnusedResources">
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 6407731..1d3b2f5 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -835,6 +835,7 @@ "--classpath=@FileArg($_rebased_build_config:javac:interface_classpath)", "--resource-sources=@FileArg($_rebased_build_config:deps_info:owned_resources_dirs)", "--resource-sources=@FileArg($_rebased_build_config:deps_info:owned_resources_zips)", + "--srcjars=@FileArg($_rebased_build_config:gradle:bundled_srcjars)", "--can-fail-build", ] }
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc index 8714fb5..a79d886c 100644 --- a/cc/paint/display_item_list.cc +++ b/cc/paint/display_item_list.cc
@@ -73,8 +73,7 @@ paint_op_buffer_.ShrinkToFit(); rtree_.Build(visual_rects_); - if (!retain_visual_rects_) - visual_rects_.clear(); + visual_rects_.clear(); visual_rects_.shrink_to_fit(); begin_paired_indices_.shrink_to_fit(); } @@ -110,15 +109,7 @@ state->BeginArray("items"); for (size_t i = 0; i < paint_op_buffer_.size(); ++i) { - gfx::Rect visual_rect = visual_rects_[i]; - state->BeginDictionary(); - state->BeginArray("visualRect"); - state->AppendInteger(visual_rect.x()); - state->AppendInteger(visual_rect.y()); - state->AppendInteger(visual_rect.width()); - state->AppendInteger(visual_rect.height()); - state->EndArray(); SkPictureRecorder recorder; SkCanvas* canvas = @@ -130,6 +121,7 @@ std::string b64_picture; PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); state->SetString("skp64", b64_picture); + state->EndDictionary(); }
diff --git a/cc/paint/display_item_list.h b/cc/paint/display_item_list.h index a115c90..e204d8f 100644 --- a/cc/paint/display_item_list.h +++ b/cc/paint/display_item_list.h
@@ -123,10 +123,6 @@ std::vector<DrawImage>* images); gfx::Rect GetRectForImage(PaintImage::Id image_id) const; - void SetRetainVisualRectsForTesting(bool retain) { - retain_visual_rects_ = retain; - } - gfx::Rect VisualRectForTesting(int index) { return visual_rects_[index]; } void GatherDiscardableImages(DiscardableImageStore* image_store) const; @@ -181,9 +177,6 @@ bool in_painting_ = false; size_t op_count_ = 0u; - // For testing purposes only. Whether to keep visual rects across calls to - // Finalize(). - bool retain_visual_rects_ = false; friend class base::RefCountedThreadSafe<DisplayItemList>; FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, BytesUsed);
diff --git a/cc/paint/display_item_list_unittest.cc b/cc/paint/display_item_list_unittest.cc index 6250247..d5ff486 100644 --- a/cc/paint/display_item_list_unittest.cc +++ b/cc/paint/display_item_list_unittest.cc
@@ -380,7 +380,6 @@ TEST(DisplayItemListTest, AsValueWithNoOps) { auto list = make_scoped_refptr(new DisplayItemList); - list->SetRetainVisualRectsForTesting(true); list->Finalize(); // Pass |true| to ask for PaintOps even though there are none. @@ -442,7 +441,6 @@ TEST(DisplayItemListTest, AsValueWithOps) { gfx::Rect layer_rect = gfx::Rect(1, 2, 8, 9); auto list = make_scoped_refptr(new DisplayItemList); - list->SetRetainVisualRectsForTesting(true); gfx::Transform transform; transform.Translate(6.f, 7.f); @@ -505,20 +503,12 @@ for (int i = 0; i < 6; ++i) { const base::DictionaryValue* item_dict; - const base::ListValue* visual_rect_list; ASSERT_TRUE(list->GetDictionary(i, &item_dict)); // The SkPicture for each item exists. EXPECT_TRUE( item_dict->GetString("skp64", static_cast<std::string*>(nullptr))); - // The range has a visual rect, it is the same for each item here. - EXPECT_TRUE(item_dict->GetList("visualRect", &visual_rect_list)); - ASSERT_EQ(4u, visual_rect_list->GetSize()); - EXPECT_TRUE(visual_rect_list->GetDouble(0, &d) && d == 2) << d; - EXPECT_TRUE(visual_rect_list->GetDouble(1, &d) && d == 3) << d; - EXPECT_TRUE(visual_rect_list->GetDouble(2, &d) && d == 8) << d; - EXPECT_TRUE(visual_rect_list->GetDouble(3, &d) && d == 9) << d; } } }
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc index 5b5e74d..a384a53 100644 --- a/cc/test/fake_content_layer_client.cc +++ b/cc/test/fake_content_layer_client.cc
@@ -45,7 +45,6 @@ FakeContentLayerClient::PaintContentsToDisplayList( PaintingControlSetting painting_control) { auto display_list = make_scoped_refptr(new DisplayItemList); - display_list->SetRetainVisualRectsForTesting(true); for (RectPaintVector::const_iterator it = draw_rects_.begin(); it != draw_rects_.end(); ++it) {
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index f1f0836..7c258ae6 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -160,6 +160,14 @@ ] } +android_aidl("photo_picker_aidl") { + import_include = [ "java/src/org/chromium/chrome/browser/photo_picker" ] + sources = [ + "java/src/org/chromium/chrome/browser/photo_picker/IDecoderService.aidl", + "java/src/org/chromium/chrome/browser/photo_picker/IDecoderServiceCallback.aidl", + ] +} + android_library("chrome_java") { deps = [ ":chrome_java_resources", @@ -247,6 +255,7 @@ ":chrome_android_java_enums_srcjar", ":chrome_android_java_google_api_keys_srcjar", ":chrome_version_srcjar", + ":photo_picker_aidl", ":resource_id_javagen", "//chrome:content_setting_javagen", "//chrome:content_settings_type_javagen",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WebApkChildProcessServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/WebApkChildProcessServiceImpl.java index 746e28f8b..5660351 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/WebApkChildProcessServiceImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/WebApkChildProcessServiceImpl.java
@@ -10,6 +10,7 @@ import org.chromium.base.annotations.UsedByReflection; import org.chromium.content.app.ChildProcessServiceImpl; +import org.chromium.content.app.ContentChildProcessServiceDelegate; /** * This class exposes ChildProcessServiceImpl so that WebApkSandboxedProcessService can access it @@ -20,7 +21,8 @@ private final ChildProcessServiceImpl mChildProcessServiceImpl; public WebApkChildProcessServiceImpl() { - mChildProcessServiceImpl = new ChildProcessServiceImpl(); + mChildProcessServiceImpl = + new ChildProcessServiceImpl(new ContentChildProcessServiceDelegate()); } @UsedByReflection("WebApkSandboxedProcessService")
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java index f37ecd6d..2e0681b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/AddressEditor.java
@@ -70,7 +70,7 @@ * @param phoneNumber The phone number to possibly add. */ public void addPhoneNumberIfValid(@Nullable CharSequence phoneNumber) { - if (TextUtils.isEmpty(phoneNumber)) mPhoneNumbers.add(phoneNumber.toString()); + if (!TextUtils.isEmpty(phoneNumber)) mPhoneNumbers.add(phoneNumber.toString()); } /** @@ -143,6 +143,12 @@ // that's being edited. This will not fire the dropdown callback. mCountryField.setValue(AutofillAddress.getCountryCode(mProfile)); + // Phone number validator and formatter are cached, so their contry code needs to be updated + // for the new profile that's being edited. + assert mCountryField.getValue() != null; + mPhoneValidator.setCountryCode(mCountryField.getValue().toString()); + mPhoneFormatter.setCountryCode(mCountryField.getValue().toString()); + // There's a finite number of fields for address editing. Changing the country will re-order // and relabel the fields. The meaning of each field remains the same. if (mAddressFields.isEmpty()) { @@ -170,9 +176,6 @@ // Phone number is present and required for all countries. if (mPhoneField == null) { - assert mCountryField.getValue() != null; - mPhoneValidator.setCountryCode(mCountryField.getValue().toString()); - mPhoneFormatter.setCountryCode(mCountryField.getValue().toString()); mPhoneField = EditorFieldModel.createTextInput(EditorFieldModel.INPUT_TYPE_HINT_PHONE, mContext.getString(R.string.autofill_profile_editor_phone_number), mPhoneNumbers, mPhoneFormatter, mPhoneValidator, null,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java index 9f307683..77c06c19 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderService.java
@@ -8,10 +8,7 @@ import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; -import android.os.Handler; import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.SystemClock; @@ -25,19 +22,10 @@ * A service to accept requests to take image file contents and decode them. */ public class DecoderService extends Service { - // Message ids for communicating with the client. - - // A message sent by the client to decode an image. - static final int MSG_DECODE_IMAGE = 1; - // A message sent by the server to notify the client of the results of the decoding. - static final int MSG_IMAGE_DECODED_REPLY = 2; - // The keys for the bundle when passing data to and from this service. static final String KEY_FILE_DESCRIPTOR = "file_descriptor"; static final String KEY_FILE_PATH = "file_path"; static final String KEY_IMAGE_BITMAP = "image_bitmap"; - static final String KEY_IMAGE_BYTE_COUNT = "image_byte_count"; - static final String KEY_IMAGE_DESCRIPTOR = "image_descriptor"; static final String KEY_SIZE = "size"; static final String KEY_SUCCESS = "success"; static final String KEY_DECODE_TIME = "decode_time"; @@ -45,98 +33,78 @@ // A tag for logging error messages. private static final String TAG = "ImageDecoder"; - /** - * Handler for incoming messages from clients. - */ - static class IncomingHandler extends Handler { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_DECODE_IMAGE: - Bundle bundle = null; - Messenger client = null; - String filePath = ""; - int size = 0; - try { - Bundle payload = msg.getData(); - client = msg.replyTo; + @Override + public void onCreate() { + super.onCreate(); + } - filePath = payload.getString(KEY_FILE_PATH); - ParcelFileDescriptor pfd = payload.getParcelable(KEY_FILE_DESCRIPTOR); - size = payload.getInt(KEY_SIZE); + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } - // Setup a minimum viable response to parent process. Will be fleshed out - // further below. - bundle = new Bundle(); - bundle.putString(KEY_FILE_PATH, filePath); - bundle.putBoolean(KEY_SUCCESS, false); + private final IDecoderService.Stub mBinder = new IDecoderService.Stub() { + public void decodeImage(Bundle payload, IDecoderServiceCallback callback) { + Bundle bundle = null; + String filePath = ""; + int size = 0; + try { + filePath = payload.getString(KEY_FILE_PATH); + ParcelFileDescriptor pfd = payload.getParcelable(KEY_FILE_DESCRIPTOR); + size = payload.getInt(KEY_SIZE); - FileDescriptor fd = pfd.getFileDescriptor(); + // Setup a minimum viable response to parent process. Will be fleshed out + // further below. + bundle = new Bundle(); + bundle.putString(KEY_FILE_PATH, filePath); + bundle.putBoolean(KEY_SUCCESS, false); - long begin = SystemClock.elapsedRealtime(); - Bitmap bitmap = BitmapUtils.decodeBitmapFromFileDescriptor(fd, size); - long decodeTime = SystemClock.elapsedRealtime() - begin; + FileDescriptor fd = pfd.getFileDescriptor(); - try { - pfd.close(); - } catch (IOException e) { - Log.e(TAG, "Closing failed " + filePath + " (size: " + size + ") " + e); - } + long begin = SystemClock.elapsedRealtime(); + Bitmap bitmap = BitmapUtils.decodeBitmapFromFileDescriptor(fd, size); + long decodeTime = SystemClock.elapsedRealtime() - begin; - if (bitmap == null) { - Log.e(TAG, "Decode failed " + filePath + " (size: " + size + ")"); - sendReply(client, bundle); // Sends SUCCESS == false; - return; - } + try { + pfd.close(); + } catch (IOException e) { + Log.e(TAG, "Closing failed " + filePath + " (size: " + size + ") " + e); + } - // The most widely supported, easiest, and reasonably efficient method is to - // decode to an immutable bitmap and just return the bitmap over binder. It - // will internally memcpy itself to ashmem and then just send over the file - // descriptor. In the receiving process it will just leave the bitmap on - // ashmem since it's immutable and carry on. - bundle.putParcelable(KEY_IMAGE_BITMAP, bitmap); - bundle.putBoolean(KEY_SUCCESS, true); - bundle.putLong(KEY_DECODE_TIME, decodeTime); - sendReply(client, bundle); - bitmap.recycle(); - } catch (Exception e) { - // This service has no UI and maintains no state so if it crashes on - // decoding a photo, it is better UX to eat the exception instead of showing - // a crash dialog and discarding other requests that have already been sent. - Log.e(TAG, - "Unexpected error during decoding " + filePath + " (size: " + size - + ") " + e); + if (bitmap == null) { + Log.e(TAG, "Decode failed " + filePath + " (size: " + size + ")"); + sendReply(callback, bundle); // Sends SUCCESS == false; + return; + } - if (bundle != null && client != null) sendReply(client, bundle); - } - break; - default: - super.handleMessage(msg); + // The most widely supported, easiest, and reasonably efficient method is to + // decode to an immutable bitmap and just return the bitmap over binder. It + // will internally memcpy itself to ashmem and then just send over the file + // descriptor. In the receiving process it will just leave the bitmap on + // ashmem since it's immutable and carry on. + bundle.putParcelable(KEY_IMAGE_BITMAP, bitmap); + bundle.putBoolean(KEY_SUCCESS, true); + bundle.putLong(KEY_DECODE_TIME, decodeTime); + sendReply(callback, bundle); + bitmap.recycle(); + } catch (Exception e) { + // This service has no UI and maintains no state so if it crashes on + // decoding a photo, it is better UX to eat the exception instead of showing + // a crash dialog and discarding other requests that have already been sent. + Log.e(TAG, + "Unexpected error during decoding " + filePath + " (size: " + size + ") " + + e); + + if (bundle != null) sendReply(callback, bundle); } } - private void sendReply(Messenger client, Bundle bundle) { - Message reply = Message.obtain(null, MSG_IMAGE_DECODED_REPLY); - reply.setData(bundle); + private void sendReply(IDecoderServiceCallback callback, Bundle bundle) { try { - client.send(reply); + callback.onDecodeImageDone(bundle); } catch (RemoteException remoteException) { Log.e(TAG, "Remote error while replying: " + remoteException); } } - } - - /** - * The target we publish for clients to send messages to IncomingHandler. - */ - final Messenger mMessenger = new Messenger(new IncomingHandler()); - - /** - * When binding to the service, we return an interface to our messenger - * for sending messages to the service. - */ - @Override - public IBinder onBind(Intent intent) { - return mMessenger.getBinder(); - } + }; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java index e5cf11c..b3b728c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHost.java
@@ -10,16 +10,15 @@ import android.content.ServiceConnection; import android.graphics.Bitmap; import android.os.Bundle; -import android.os.Handler; import android.os.IBinder; -import android.os.Message; -import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemClock; +import android.support.annotation.Nullable; import org.chromium.base.Log; +import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.util.ConversionUtils; @@ -27,17 +26,31 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; -import java.lang.ref.WeakReference; import java.util.LinkedHashMap; import java.util.concurrent.TimeUnit; /** * A class to communicate with the {@link DecoderService}. */ -public class DecoderServiceHost { +public class DecoderServiceHost extends IDecoderServiceCallback.Stub { // A tag for logging error messages. private static final String TAG = "ImageDecoderHost"; + IDecoderService mIRemoteService; + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + mIRemoteService = IDecoderService.Stub.asInterface(service); + mBound = true; + mCallback.serviceReady(); + } + + public void onServiceDisconnected(ComponentName className) { + Log.e(TAG, "Service has unexpectedly disconnected"); + mIRemoteService = null; + mBound = false; + } + }; + /** * Interface for notifying clients of the service being ready. */ @@ -61,30 +74,6 @@ } /** - * Class for interacting with the main interface of the service. - */ - private class DecoderServiceConnection implements ServiceConnection { - // The callback to use to notify the service being ready. - private ServiceReadyCallback mCallback; - - public DecoderServiceConnection(ServiceReadyCallback callback) { - mCallback = callback; - } - - // Called when a connection to the service has been established. - public void onServiceConnected(ComponentName name, IBinder service) { - mService = new Messenger(service); - mBound = true; - mCallback.serviceReady(); - } - - // Called when a connection to the service has been lost. - public void onServiceDisconnected(ComponentName name) { - mBound = false; - } - } - - /** * Class for keeping track of the data involved with each request. */ private static class DecoderServiceParams { @@ -116,24 +105,18 @@ // The callback used to notify the client when the service is ready. private ServiceReadyCallback mCallback; - // Messenger for communicating with the remote service. - Messenger mService = null; - - // Our service connection to the {@link DecoderService}. - private DecoderServiceConnection mConnection; - // Flag indicating whether we are bound to the service. - boolean mBound; + private boolean mBound; - // The inbound messenger used by the remote service to communicate with us. - final Messenger mMessenger = new Messenger(new IncomingHandler(this)); + private final Context mContext; /** * The DecoderServiceHost constructor. * @param callback The callback to use when communicating back to the client. */ - public DecoderServiceHost(ServiceReadyCallback callback) { + public DecoderServiceHost(ServiceReadyCallback callback, Context context) { mCallback = callback; + mContext = context; } /** @@ -141,9 +124,9 @@ * @param context The context to use. */ public void bind(Context context) { - mConnection = new DecoderServiceConnection(mCallback); - Intent intent = new Intent(context, DecoderService.class); - context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + Intent intent = new Intent(mContext, DecoderService.class); + intent.setAction(IDecoderService.class.getName()); + mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } /** @@ -181,15 +164,35 @@ } } + @Override + public void onDecodeImageDone(final Bundle payload) { + // As per the Android documentation, AIDL callbacks can (and will) happen on any thread, so + // make sure the code runs on the UI thread, since further down the callchain the code will + // end up creating UI objects. + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + // Read the reply back from the service. + String filePath = payload.getString(DecoderService.KEY_FILE_PATH); + Boolean success = payload.getBoolean(DecoderService.KEY_SUCCESS); + Bitmap bitmap = success + ? (Bitmap) payload.getParcelable(DecoderService.KEY_IMAGE_BITMAP) + : null; + long decodeTime = payload.getLong(DecoderService.KEY_DECODE_TIME); + closeRequest(filePath, bitmap, decodeTime); + } + }); + } + /** * Ties up all the loose ends from the decoding request (communicates the results of the * decoding process back to the client, and takes care of house-keeping chores regarding * the request queue). * @param filePath The path to the image that was just decoded. - * @param bitmap The resulting decoded bitmap. + * @param bitmap The resulting decoded bitmap, or null if decoding fails. * @param decodeTime The length of time it took to decode the bitmap. */ - public void closeRequest(String filePath, Bitmap bitmap, long decodeTime) { + public void closeRequest(String filePath, @Nullable Bitmap bitmap, long decodeTime) { DecoderServiceParams params = getRequests().get(filePath); if (params != null) { long endRpcCall = SystemClock.elapsedRealtime(); @@ -198,7 +201,7 @@ params.mCallback.imageDecodedCallback(filePath, bitmap); - if (decodeTime != -1) { + if (decodeTime != -1 && bitmap != null) { RecordHistogram.recordTimesHistogram( "Android.PhotoPicker.ImageDecodeTime", decodeTime, TimeUnit.MILLISECONDS); @@ -248,13 +251,10 @@ if (pfd == null) return; // Prepare and send the data over. - Message payload = Message.obtain(null, DecoderService.MSG_DECODE_IMAGE); - payload.replyTo = mMessenger; bundle.putString(DecoderService.KEY_FILE_PATH, filePath); bundle.putInt(DecoderService.KEY_SIZE, size); - payload.setData(bundle); try { - mService.send(payload); + mIRemoteService.decodeImage(bundle, this); pfd.close(); } catch (RemoteException e) { Log.e(TAG, "Communications failed (Remote): " + e); @@ -272,46 +272,4 @@ public void cancelDecodeImage(String filePath) { mRequests.remove(filePath); } - - /** - * A class for handling communications from the service to us. - */ - static class IncomingHandler extends Handler { - // The DecoderServiceHost object to communicate with. - private final WeakReference<DecoderServiceHost> mHost; - - /** - * Constructor for IncomingHandler. - * @param host The DecoderServiceHost object to communicate with. - */ - IncomingHandler(DecoderServiceHost host) { - mHost = new WeakReference<DecoderServiceHost>(host); - } - - @Override - public void handleMessage(Message msg) { - DecoderServiceHost host = mHost.get(); - if (host == null) { - super.handleMessage(msg); - return; - } - - switch (msg.what) { - case DecoderService.MSG_IMAGE_DECODED_REPLY: - Bundle payload = msg.getData(); - - // Read the reply back from the service. - String filePath = payload.getString(DecoderService.KEY_FILE_PATH); - Boolean success = payload.getBoolean(DecoderService.KEY_SUCCESS); - Bitmap bitmap = success - ? (Bitmap) payload.getParcelable(DecoderService.KEY_IMAGE_BITMAP) - : null; - long decodeTime = payload.getLong(DecoderService.KEY_DECODE_TIME); - host.closeRequest(filePath, bitmap, decodeTime); - break; - default: - super.handleMessage(msg); - } - } - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/IDecoderService.aidl b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/IDecoderService.aidl new file mode 100644 index 0000000..778c3aa --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/IDecoderService.aidl
@@ -0,0 +1,21 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.photo_picker; + +import android.os.Bundle; + +import IDecoderServiceCallback; + +/** + * This interface is called by the Photo Picker to start image decoding jobs in + * a separate process. + */ +interface IDecoderService { + /** + * Decode an image. + * @param payload The data containing the details for the decoding request. + */ + oneway void decodeImage(in Bundle payload, IDecoderServiceCallback listener); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/IDecoderServiceCallback.aidl b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/IDecoderServiceCallback.aidl new file mode 100644 index 0000000..31fefa5 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/IDecoderServiceCallback.aidl
@@ -0,0 +1,18 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.photo_picker; + +/** + * This interface is used to communicate the results of an image decoding + * request. + */ +interface IDecoderServiceCallback { + /** + * Called when decoding is done. + * @param payload The results of the image decoding request, including the + * decoded bitmap. + */ + oneway void onDecodeImageDone(in Bundle payload); +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/OWNERS index 2cf393627..71a7706 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/OWNERS
@@ -1,2 +1,5 @@ finnur@chromium.org twellington@chromium.org + +per-file *.aidl=set noparent +per-file *.aidl=file://ipc/SECURITY_OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerCategoryView.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerCategoryView.java index fa8e3aae..a53c5e3d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerCategoryView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerCategoryView.java
@@ -131,8 +131,8 @@ super(context); mActivity = (ChromeActivity) context; - mDecoderServiceHost = new DecoderServiceHost(this); - mDecoderServiceHost.bind(mActivity); + mDecoderServiceHost = new DecoderServiceHost(this, context); + mDecoderServiceHost.bind(context); mSelectionDelegate = new SelectionDelegate<PickerBitmap>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index c058303..322123d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -1050,11 +1050,9 @@ private void setSheetOffsetFromBottom(float offset) { if (MathUtils.areFloatsEqual(offset, getSheetOffsetFromBottom())) return; - if (MathUtils.areFloatsEqual(getSheetOffsetFromBottom(), getMinOffset()) - && offset > getMinOffset()) { + if (offset > getMinOffset()) { onSheetOpened(); - } else if (MathUtils.areFloatsEqual(offset, getMinOffset()) - && getSheetOffsetFromBottom() > getMinOffset()) { + } else if (getSheetOffsetFromBottom() > getMinOffset()) { onSheetClosed(); }
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 1b6ad13b..c382e53 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -966,9 +966,9 @@ int ChromeMainDelegate::RunProcess( const std::string& process_type, const content::MainFunctionParams& main_function_params) { -// ANDROID doesn't support "cloud-print-service", so no -// CloudPrintServiceProcessMain, and arraysize doesn't support empty array. So -// we comment out the block for Android. +// ANDROID doesn't support "service", so no CloudPrintServiceProcessMain, and +// arraysize doesn't support empty array. So we comment out the block for +// Android. #if !defined(OS_ANDROID) static const MainFunction kMainFunctions[] = { #if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(CHROME_MULTIPLE_DLL_CHILD)
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index a9651a34..8f55b28 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -21,6 +21,8 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/thread_restrictions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h" #include "chrome/browser/apps/app_window_registry_util.h" @@ -90,7 +92,6 @@ #include "components/prefs/pref_service.h" #include "components/sessions/core/tab_restore_service.h" #include "components/signin/core/browser/signin_manager.h" -#include "content/public/browser/browser_thread.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" @@ -106,7 +107,6 @@ using apps::ExtensionAppShimHandler; using base::UserMetricsAction; using content::BrowserContext; -using content::BrowserThread; using content::DownloadManager; namespace { @@ -170,7 +170,7 @@ // real, user-visible app bundle directory. (The alternatives give either the // framework's path or the initial app's path, which may be an app mode shim // or a unit test.) - DCHECK_CURRENTLY_ON(BrowserThread::FILE); + base::ThreadRestrictions::AssertIOAllowed(); base::FilePath app_bundle_path = chrome::GetVersionedDirectory().DirName().DirName().DirName(); @@ -728,11 +728,11 @@ [NSApp setHelpMenu:helpMenu_]; // Record the path to the (browser) app bundle; this is used by the app mode - // shim. It has to be done in FILE thread because getting the path requires - // I/O. - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&RecordLastRunAppBundlePath)); + // shim. + base::PostTaskWithTraits(FROM_HERE, + {base::MayBlock(), base::TaskPriority::BACKGROUND, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, + base::Bind(&RecordLastRunAppBundlePath)); // Makes "Services" menu items available. [self registerServicesMenuTypesTo:[notify object]];
diff --git a/chrome/browser/chromeos/customization/customization_document.cc b/chrome/browser/chromeos/customization/customization_document.cc index 3a14bfc..ada7398 100644 --- a/chrome/browser/chromeos/customization/customization_document.cc +++ b/chrome/browser/chromeos/customization/customization_document.cc
@@ -24,6 +24,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/task_scheduler/post_task.h" +#include "base/threading/thread_restrictions.h" #include "base/time/time.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/customization/customization_wallpaper_downloader.h" @@ -49,8 +50,6 @@ #include "net/http/http_status_code.h" #include "net/url_request/url_fetcher.h" -using content::BrowserThread; - namespace chromeos { namespace { @@ -151,6 +150,19 @@ *exists = base::PathExists(path); } +std::string ReadFileInBackground(const base::FilePath& file) { + base::ThreadRestrictions::AssertIOAllowed(); + + std::string manifest; + if (!base::ReadFileToString(file, &manifest)) { + manifest.clear(); + LOG(ERROR) << "Failed to load services customization manifest from: " + << file.value(); + } + + return manifest; +} + } // anonymous namespace // Template URL where to fetch OEM services customization manifest from. @@ -533,36 +545,18 @@ if (url_.is_valid()) { fetch_started_ = true; if (url_.SchemeIsFile()) { - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&ServicesCustomizationDocument::ReadFileInBackground, - weak_ptr_factory_.GetWeakPtr(), - base::FilePath(url_.path()))); + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()}, + base::BindOnce(&ReadFileInBackground, base::FilePath(url_.path())), + base::BindOnce(&ServicesCustomizationDocument::OnManifestRead, + weak_ptr_factory_.GetWeakPtr())); } else { StartFileFetch(); } } } -// static -void ServicesCustomizationDocument::ReadFileInBackground( - base::WeakPtr<ServicesCustomizationDocument> self, - const base::FilePath& file) { - DCHECK_CURRENTLY_ON(BrowserThread::FILE); - - std::string manifest; - if (!base::ReadFileToString(file, &manifest)) { - manifest.clear(); - LOG(ERROR) << "Failed to load services customization manifest from: " - << file.value(); - } - - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&ServicesCustomizationDocument::OnManifesteRead, - self, - manifest)); -} - -void ServicesCustomizationDocument::OnManifesteRead( +void ServicesCustomizationDocument::OnManifestRead( const std::string& manifest) { if (!manifest.empty()) LoadManifestFromString(manifest);
diff --git a/chrome/browser/chromeos/customization/customization_document.h b/chrome/browser/chromeos/customization/customization_document.h index a971206..3ffbb0e1 100644 --- a/chrome/browser/chromeos/customization/customization_document.h +++ b/chrome/browser/chromeos/customization/customization_document.h
@@ -236,13 +236,8 @@ // Initiate file fetching. Don't wait for online status. void DoStartFileFetch(); - // Executes on FILE thread and reads file to string. - static void ReadFileInBackground( - base::WeakPtr<ServicesCustomizationDocument> self, - const base::FilePath& file); - // Called on UI thread with results of ReadFileInBackground. - void OnManifesteRead(const std::string& manifest); + void OnManifestRead(const std::string& manifest); // Method called when manifest was successfully loaded. void OnManifestLoaded();
diff --git a/chrome/browser/chromeos/device/input_service_proxy.cc b/chrome/browser/chromeos/device/input_service_proxy.cc index 601bc61..20fbd6d 100644 --- a/chrome/browser/chromeos/device/input_service_proxy.cc +++ b/chrome/browser/chromeos/device/input_service_proxy.cc
@@ -6,39 +6,60 @@ #include "base/bind_helpers.h" #include "base/macros.h" +#include "base/sequence_checker.h" #include "base/task_runner_util.h" +#include "base/task_scheduler/lazy_task_runner.h" +#include "base/task_scheduler/post_task.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; using device::InputServiceLinux; -typedef device::InputServiceLinux::InputDeviceInfo InputDeviceInfo; - namespace chromeos { -// static -BrowserThread::ID InputServiceProxy::thread_identifier_ = BrowserThread::FILE; +namespace { + +using InputDeviceInfo = device::InputServiceLinux::InputDeviceInfo; + +bool use_ui_thread_for_test = false; + +// SequencedTaskRunner could be used after InputServiceLinux and friends +// are updated to check on sequence instead of thread. +base::LazySingleThreadTaskRunner default_input_service_task_runner = + LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER( + base::TaskTraits({base::TaskPriority::BACKGROUND, base::MayBlock()}), + base::SingleThreadTaskRunnerThreadMode::SHARED); + +} // namespace class InputServiceProxy::ServiceObserver : public InputServiceLinux::Observer { public: - ServiceObserver() { DCHECK_CURRENTLY_ON(BrowserThread::UI); } - ~ServiceObserver() override { DCHECK(CalledOnValidThread()); } + ServiceObserver() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // Detach since this object is constructed on UI thread and forever after + // used from another sequence. + DETACH_FROM_SEQUENCE(sequence_checker_); + } + ~ServiceObserver() override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + } void Initialize(const base::WeakPtr<InputServiceProxy>& proxy) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); InputServiceLinux::GetInstance()->AddObserver(this); proxy_ = proxy; } void Shutdown() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (InputServiceLinux::HasInstance()) InputServiceLinux::GetInstance()->RemoveObserver(this); delete this; } std::vector<InputDeviceInfo> GetDevices() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::vector<InputDeviceInfo> devices; if (InputServiceLinux::HasInstance()) InputServiceLinux::GetInstance()->GetDevices(&devices); @@ -47,81 +68,72 @@ void GetDeviceInfo(const std::string& id, const InputServiceProxy::GetDeviceInfoCallback& callback) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); bool success = false; InputDeviceInfo info; info.id = id; if (InputServiceLinux::HasInstance()) success = InputServiceLinux::GetInstance()->GetDeviceInfo(id, &info); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, base::Bind(callback, success, info)); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(callback, success, info)); } // InputServiceLinux::Observer implementation: void OnInputDeviceAdded( const InputServiceLinux::InputDeviceInfo& info) override { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&InputServiceProxy::OnDeviceAdded, proxy_, info)); + BrowserThread::UI, FROM_HERE, + base::BindOnce(&InputServiceProxy::OnDeviceAdded, proxy_, info)); } void OnInputDeviceRemoved(const std::string& id) override { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&InputServiceProxy::OnDeviceRemoved, proxy_, id)); + BrowserThread::UI, FROM_HERE, + base::BindOnce(&InputServiceProxy::OnDeviceRemoved, proxy_, id)); } private: - bool CalledOnValidThread() const { - return BrowserThread::CurrentlyOn(InputServiceProxy::thread_identifier_); - } - base::WeakPtr<InputServiceProxy> proxy_; + SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(ServiceObserver); }; InputServiceProxy::InputServiceProxy() : service_observer_(new ServiceObserver()), - task_runner_(BrowserThread::GetTaskRunnerForThread(thread_identifier_)), weak_factory_(this) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - task_runner_->PostTask( - FROM_HERE, - base::Bind(&InputServiceProxy::ServiceObserver::Initialize, - base::Unretained(service_observer_.get()), - weak_factory_.GetWeakPtr())); + GetInputServiceTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&InputServiceProxy::ServiceObserver::Initialize, + base::Unretained(service_observer_.get()), + weak_factory_.GetWeakPtr())); } InputServiceProxy::~InputServiceProxy() { - DCHECK(thread_checker_.CalledOnValidThread()); - task_runner_->PostTask( - FROM_HERE, - base::Bind(&InputServiceProxy::ServiceObserver::Shutdown, - base::Unretained(service_observer_.release()))); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + GetInputServiceTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&InputServiceProxy::ServiceObserver::Shutdown, + base::Unretained(service_observer_.release()))); } void InputServiceProxy::AddObserver(Observer* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (observer) observers_.AddObserver(observer); } void InputServiceProxy::RemoveObserver(Observer* observer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (observer) observers_.RemoveObserver(observer); } void InputServiceProxy::GetDevices(const GetDevicesCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); base::PostTaskAndReplyWithResult( - task_runner_.get(), - FROM_HERE, + GetInputServiceTaskRunner().get(), FROM_HERE, base::Bind(&InputServiceProxy::ServiceObserver::GetDevices, base::Unretained(service_observer_.get())), callback); @@ -129,29 +141,36 @@ void InputServiceProxy::GetDeviceInfo(const std::string& id, const GetDeviceInfoCallback& callback) { - DCHECK(thread_checker_.CalledOnValidThread()); - task_runner_->PostTask( + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + GetInputServiceTaskRunner()->PostTask( FROM_HERE, - base::Bind(&InputServiceProxy::ServiceObserver::GetDeviceInfo, - base::Unretained(service_observer_.release()), - id, - callback)); + base::BindOnce(&InputServiceProxy::ServiceObserver::GetDeviceInfo, + base::Unretained(service_observer_.get()), id, callback)); } // static -void InputServiceProxy::SetThreadIdForTesting(BrowserThread::ID thread_id) { - InputServiceProxy::thread_identifier_ = thread_id; +scoped_refptr<base::SequencedTaskRunner> +InputServiceProxy::GetInputServiceTaskRunner() { + if (use_ui_thread_for_test) + return BrowserThread::GetTaskRunnerForThread(BrowserThread::UI); + + return default_input_service_task_runner.Get(); +} + +// static +void InputServiceProxy::SetUseUIThreadForTesting(bool use_ui_thread) { + use_ui_thread_for_test = use_ui_thread; } void InputServiceProxy::OnDeviceAdded( const InputServiceLinux::InputDeviceInfo& info) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); for (auto& observer : observers_) observer.OnInputDeviceAdded(info); } void InputServiceProxy::OnDeviceRemoved(const std::string& id) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); for (auto& observer : observers_) observer.OnInputDeviceRemoved(id); }
diff --git a/chrome/browser/chromeos/device/input_service_proxy.h b/chrome/browser/chromeos/device/input_service_proxy.h index 3c00da6e3..ab76958 100644 --- a/chrome/browser/chromeos/device/input_service_proxy.h +++ b/chrome/browser/chromeos/device/input_service_proxy.h
@@ -10,11 +10,11 @@ #include "base/callback.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/task_runner.h" +#include "base/sequenced_task_runner.h" #include "base/threading/thread_checker.h" -#include "content/public/browser/browser_thread.h" #include "device/hid/input_service_linux.h" namespace chromeos { @@ -47,12 +47,15 @@ void GetDeviceInfo(const std::string& id, const GetDeviceInfoCallback& callback); + // Returns the SequencedTaskRunner for device::InputServiceLinux. Make it + // static so that all InputServiceProxy instances and code that needs access + // to device::InputServiceLinux uses the same sequence. + static scoped_refptr<base::SequencedTaskRunner> GetInputServiceTaskRunner(); + // Should be called once before any InputServiceProxy instance is created. - static void SetThreadIdForTesting(content::BrowserThread::ID thread_id); + static void SetUseUIThreadForTesting(bool use_ui_thread); private: - static content::BrowserThread::ID thread_identifier_; - class ServiceObserver; void OnDeviceAdded(const device::InputServiceLinux::InputDeviceInfo& info); @@ -61,9 +64,7 @@ base::ObserverList<Observer> observers_; std::unique_ptr<ServiceObserver> service_observer_; - base::ThreadChecker thread_checker_; - - scoped_refptr<base::TaskRunner> task_runner_; + THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<InputServiceProxy> weak_factory_;
diff --git a/chrome/browser/chromeos/device/input_service_test_helper.cc b/chrome/browser/chromeos/device/input_service_test_helper.cc index 7cc5e87b..42ac2e8 100644 --- a/chrome/browser/chromeos/device/input_service_test_helper.cc +++ b/chrome/browser/chromeos/device/input_service_test_helper.cc
@@ -8,11 +8,9 @@ #include "base/memory/ptr_util.h" #include "base/run_loop.h" #include "chrome/browser/chromeos/device/input_service_proxy.h" -#include "content/public/browser/browser_thread.h" #include "device/hid/fake_input_service_linux.h" #include "testing/gtest/include/gtest/gtest.h" -using content::BrowserThread; using device::InputServiceLinux; using device::FakeInputServiceLinux; @@ -20,17 +18,17 @@ namespace { -void InitInputServiceOnFileThread() { +void InitInputServiceOnInputServiceSequence() { InputServiceLinux::SetForTesting(base::MakeUnique<FakeInputServiceLinux>()); } -void AddDeviceOnFileThread(const InputDeviceInfo& device) { +void AddDeviceOnInputServiceSequence(const InputDeviceInfo& device) { FakeInputServiceLinux* service = static_cast<FakeInputServiceLinux*>(InputServiceLinux::GetInstance()); service->AddDeviceForTesting(device); } -void RemoveDeviceOnFileThread(const std::string& id) { +void RemoveDeviceOnInputServiceSequence(const std::string& id) { FakeInputServiceLinux* service = static_cast<FakeInputServiceLinux*>(InputServiceLinux::GetInstance()); service->RemoveDeviceForTesting(id); @@ -118,8 +116,8 @@ const char InputServiceTestHelper::kMouseId[] = "mouse"; InputServiceTestHelper::InputServiceTestHelper() : observer_(new TestObserver) { - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&InitInputServiceOnFileThread)); + InputServiceProxy::GetInputServiceTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&InitInputServiceOnInputServiceSequence)); } InputServiceTestHelper::~InputServiceTestHelper() {} @@ -142,15 +140,15 @@ device.type = type; device.is_mouse = is_mouse; device.is_keyboard = !is_mouse; - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&AddDeviceOnFileThread, device)); + InputServiceProxy::GetInputServiceTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&AddDeviceOnInputServiceSequence, device)); observer_->WaitForDeviceAddition(device); } void InputServiceTestHelper::RemoveDeviceFromService(bool is_mouse) { std::string id = is_mouse ? kMouseId : kKeyboardId; - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - base::Bind(&RemoveDeviceOnFileThread, id)); + InputServiceProxy::GetInputServiceTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&RemoveDeviceOnInputServiceSequence, id)); observer_->WaitForDeviceRemoval(id); }
diff --git a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc index f86c942..c662be2 100644 --- a/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc +++ b/chrome/browser/chromeos/login/bluetooth_host_pairing_browsertest.cc
@@ -67,7 +67,7 @@ using InputDeviceInfo = device::InputServiceLinux::InputDeviceInfo; BluetoothHostPairingNoInputTest() { - InputServiceProxy::SetThreadIdForTesting(content::BrowserThread::UI); + InputServiceProxy::SetUseUIThreadForTesting(true); device::InputServiceLinux::SetForTesting( base::MakeUnique<device::FakeInputServiceLinux>());
diff --git a/chrome/browser/chromeos/login/hid_detection_browsertest.cc b/chrome/browser/chromeos/login/hid_detection_browsertest.cc index 75ad707..facfcfd 100644 --- a/chrome/browser/chromeos/login/hid_detection_browsertest.cc +++ b/chrome/browser/chromeos/login/hid_detection_browsertest.cc
@@ -51,7 +51,7 @@ typedef device::InputServiceLinux::InputDeviceInfo InputDeviceInfo; HidDetectionTest() : weak_ptr_factory_(this) { - InputServiceProxy::SetThreadIdForTesting(content::BrowserThread::UI); + InputServiceProxy::SetUseUIThreadForTesting(true); HidDetectionTest::InitInputService(); }
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index da28bd5..84e70e6 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -33,6 +33,7 @@ #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h" #include "chrome/browser/chromeos/customization/customization_document.h" +#include "chrome/browser/chromeos/device/input_service_proxy.h" #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h" #include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h" #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h" @@ -422,7 +423,7 @@ if (!remora_controller_) { remora_controller_.reset( new pairing_chromeos::BluetoothHostPairingController( - BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE))); + InputServiceProxy::GetInputServiceTaskRunner())); remora_controller_->StartPairing(); } return new HostPairingScreen(this, this, @@ -1620,7 +1621,7 @@ if (!shark_connection_listener_) { shark_connection_listener_.reset( new pairing_chromeos::SharkConnectionListener( - BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE), + InputServiceProxy::GetInputServiceTaskRunner(), base::Bind(&WizardController::OnSharkConnected, weak_factory_.GetWeakPtr()))); }
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager.cc b/chrome/browser/chromeos/policy/active_directory_policy_manager.cc index 5b3ca71..23c19e9 100644 --- a/chrome/browser/chromeos/policy/active_directory_policy_manager.cc +++ b/chrome/browser/chromeos/policy/active_directory_policy_manager.cc
@@ -9,7 +9,6 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "base/threading/thread_task_runner_handle.h" #include "chromeos/dbus/auth_policy_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "components/policy/core/common/policy_bundle.h" @@ -22,9 +21,6 @@ // https://technet.microsoft.com/en-us/library/cc940895.aspx constexpr base::TimeDelta kRefreshInterval = base::TimeDelta::FromMinutes(90); -// Retry delay in case of |refresh_in_progress_|. -constexpr base::TimeDelta kBusyRetryInterval = base::TimeDelta::FromSeconds(1); - } // namespace namespace policy { @@ -59,7 +55,12 @@ // Does nothing if |store_| hasn't yet initialized. PublishPolicy(); - ScheduleAutomaticRefresh(); + scheduler_ = base::MakeUnique<PolicyScheduler>( + base::BindRepeating(&ActiveDirectoryPolicyManager::DoRefresh, + weak_ptr_factory_.GetWeakPtr()), + base::BindRepeating(&ActiveDirectoryPolicyManager::OnPolicyRefreshed, + weak_ptr_factory_.GetWeakPtr()), + kRefreshInterval); } void ActiveDirectoryPolicyManager::Shutdown() { @@ -76,7 +77,7 @@ } void ActiveDirectoryPolicyManager::RefreshPolicies() { - ScheduleRefresh(base::TimeDelta()); + scheduler_->ScheduleTaskNow(); } void ActiveDirectoryPolicyManager::OnStoreLoaded( @@ -97,9 +98,7 @@ ActiveDirectoryPolicyManager::ActiveDirectoryPolicyManager( const AccountId& account_id, std::unique_ptr<CloudPolicyStore> store) - : account_id_(account_id), - store_(std::move(store)), - weak_ptr_factory_(this) {} + : account_id_(account_id), store_(std::move(store)) {} void ActiveDirectoryPolicyManager::PublishPolicy() { if (!store_->is_initialized()) { @@ -118,61 +117,8 @@ UpdatePolicy(std::move(bundle)); } -void ActiveDirectoryPolicyManager::OnPolicyRefreshed(bool success) { - if (!success) { - LOG(ERROR) << "Active Directory policy refresh failed."; - } - // Load independently of success or failure to keep up to date with whatever - // has happened on the authpolicyd / session manager side. - store_->Load(); - - refresh_in_progress_ = false; - last_refresh_ = base::TimeTicks::Now(); - ScheduleAutomaticRefresh(); -} - -void ActiveDirectoryPolicyManager::ScheduleRefresh(base::TimeDelta delay) { - if (refresh_task_) { - refresh_task_->Cancel(); - } - refresh_task_ = base::MakeUnique<base::CancelableClosure>( - base::Bind(&ActiveDirectoryPolicyManager::RunScheduledRefresh, - weak_ptr_factory_.GetWeakPtr())); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, refresh_task_->callback(), delay); -} - -void ActiveDirectoryPolicyManager::ScheduleAutomaticRefresh() { - base::TimeTicks baseline; - base::TimeDelta interval; - if (retry_refresh_) { - baseline = last_refresh_; - interval = kBusyRetryInterval; - } else if (last_refresh_ == base::TimeTicks()) { - baseline = startup_; - interval = base::TimeDelta(); - } else { - baseline = last_refresh_; - interval = kRefreshInterval; - } - base::TimeDelta delay; - const base::TimeTicks now(base::TimeTicks::Now()); - if (now < baseline + interval) { - delay = baseline + interval - now; - } - ScheduleRefresh(delay); -} - -void ActiveDirectoryPolicyManager::RunScheduledRefresh() { - // Abort if a refresh is currently in progress (to avoid D-Bus jobs piling up - // behind each other). - if (refresh_in_progress_) { - retry_refresh_ = true; - return; - } - - retry_refresh_ = false; - refresh_in_progress_ = true; +void ActiveDirectoryPolicyManager::DoRefresh( + base::OnceCallback<void(bool success)> callback) { chromeos::DBusThreadManager* thread_manager = chromeos::DBusThreadManager::Get(); DCHECK(thread_manager); @@ -180,15 +126,19 @@ thread_manager->GetAuthPolicyClient(); DCHECK(auth_policy_client); if (account_id_ == EmptyAccountId()) { - auth_policy_client->RefreshDevicePolicy( - base::Bind(&ActiveDirectoryPolicyManager::OnPolicyRefreshed, - weak_ptr_factory_.GetWeakPtr())); + auth_policy_client->RefreshDevicePolicy(std::move(callback)); } else { - auth_policy_client->RefreshUserPolicy( - account_id_, - base::Bind(&ActiveDirectoryPolicyManager::OnPolicyRefreshed, - weak_ptr_factory_.GetWeakPtr())); + auth_policy_client->RefreshUserPolicy(account_id_, std::move(callback)); } } +void ActiveDirectoryPolicyManager::OnPolicyRefreshed(bool success) { + if (!success) { + LOG(ERROR) << "Active Directory policy refresh failed."; + } + // Load independently of success or failure to keep up to date with whatever + // has happened on the authpolicyd / session manager side. + store_->Load(); +} + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager.h b/chrome/browser/chromeos/policy/active_directory_policy_manager.h index 9bf7935..598c545 100644 --- a/chrome/browser/chromeos/policy/active_directory_policy_manager.h +++ b/chrome/browser/chromeos/policy/active_directory_policy_manager.h
@@ -7,12 +7,11 @@ #include <memory> -#include "base/cancelable_callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/time/time.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/configuration_policy_provider.h" +#include "components/policy/core/common/policy_scheduler.h" #include "components/signin/core/account_id/account_id.h" namespace policy { @@ -57,35 +56,20 @@ // Publish the policy that's currently cached in the store. void PublishPolicy(); - // Callback from authpolicyd. + // Calls into authpolicyd to fetch policy. Reports success or failure via + // |callback|. + void DoRefresh(PolicyScheduler::TaskCallback callback); + + // Called by scheduler with result of policy fetch. void OnPolicyRefreshed(bool success); - // Schedule next policy refresh to run after |delay|. (Deletes any previously - // scheduled refresh tasks.) - void ScheduleRefresh(base::TimeDelta delay); - - // Schedule next automatic policy refresh based on initial fetch delay or - // refresh interval. (Deletes any previously scheduled refresh tasks.) - void ScheduleAutomaticRefresh(); - - // Actually execute the scheduled policy refresh. - void RunScheduledRefresh(); - const AccountId account_id_; std::unique_ptr<CloudPolicyStore> store_; - // Whether a policy refresh is in progress (and thus any further requests need - // to be blocked). - bool refresh_in_progress_ = false; - // Whether a refresh had been blocked and thus the next refresh needs to be - // scheduled at the shorter "retry" interval. - bool retry_refresh_ = false; - base::TimeTicks last_refresh_; - const base::TimeTicks startup_ = base::TimeTicks::Now(); - std::unique_ptr<base::CancelableClosure> refresh_task_; + std::unique_ptr<PolicyScheduler> scheduler_; // Must be last member. - base::WeakPtrFactory<ActiveDirectoryPolicyManager> weak_ptr_factory_; + base::WeakPtrFactory<ActiveDirectoryPolicyManager> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ActiveDirectoryPolicyManager); };
diff --git a/chrome/browser/chromeos/power/cpu_data_collector.cc b/chrome/browser/chromeos/power/cpu_data_collector.cc index f6109e00..189b192 100644 --- a/chrome/browser/chromeos/power/cpu_data_collector.cc +++ b/chrome/browser/chromeos/power/cpu_data_collector.cc
@@ -392,7 +392,10 @@ const std::string state_name = base::IntToString(freq_in_khz / 1000); size_t index = EnsureInVector(state_name, cpu_freq_state_names); for (int cpu = 0; cpu < cpu_count; ++cpu) { - if (!(*freq_samples)[cpu].cpu_online) { + // array.size() is previously checked to be equal to cpu_count+1. cpu + // ranges from [0,cpu_count), so cpu+1 never exceeds cpu_count and is + // safe. + if (!(*freq_samples)[cpu].cpu_online || array[cpu + 1] == "N/A") { continue; } if (index >= (*freq_samples)[cpu].time_in_state.size())
diff --git a/chrome/browser/chromeos/power/cpu_data_collector_unittest.cc b/chrome/browser/chromeos/power/cpu_data_collector_unittest.cc index de359ad1..bb8a3689 100644 --- a/chrome/browser/chromeos/power/cpu_data_collector_unittest.cc +++ b/chrome/browser/chromeos/power/cpu_data_collector_unittest.cc
@@ -44,6 +44,14 @@ "60000\t\t90000\t\t91000\t\t\n" "100000\t\t50000\t\t51000\t\t\n"; +// The string content of the fake cpu frequency file for all cpus except one +// that reports "N/A" as the cpu/freq combinations that are invalid. +constexpr char kAllTimeInStateContentNA[] = + "freq\t\tcpu0\t\tcpu1\t\tcpu2\t\t\n" + "20000\t\t30000000\t\t31000000\t\tN/A\t\t\n" + "60000\t\t90000\t\t91000\t\tN/A\t\t\n" + "100000\t\t50000\t\t51000\t\tN/A\t\t\n"; + } // namespace class CpuDataCollectorTest : public testing::Test { @@ -67,19 +75,6 @@ temp_dir_.GetPath().AppendASCII(kTimeInStateSuffixPathCpu1); all_time_in_state_path_ = temp_dir_.GetPath().AppendASCII(kAllTimeInStateSuffixPath); - - ASSERT_TRUE(base::CreateTemporaryFile(&time_in_state_path_cpu0_)); - ASSERT_TRUE(base::CreateTemporaryFile(&time_in_state_path_cpu1_)); - ASSERT_TRUE(base::CreateTemporaryFile(&all_time_in_state_path_)); - ASSERT_TRUE(base::WriteFile( - time_in_state_path_cpu0_, kTimeInStateContentCpu0, - static_cast<int>(strlen(kTimeInStateContentCpu0))) != -1); - ASSERT_TRUE(base::WriteFile( - time_in_state_path_cpu1_, kTimeInStateContentCpu1, - static_cast<int>(strlen(kTimeInStateContentCpu1))) != -1); - ASSERT_TRUE(base::WriteFile( - all_time_in_state_path_, kAllTimeInStateContent, - static_cast<int>(strlen(kAllTimeInStateContent))) != -1); } protected: @@ -103,6 +98,15 @@ }; TEST_F(CpuDataCollectorTest, ReadCpuFreqTimeInState) { + ASSERT_TRUE(base::CreateTemporaryFile(&time_in_state_path_cpu0_)); + ASSERT_TRUE(base::CreateTemporaryFile(&time_in_state_path_cpu1_)); + ASSERT_TRUE( + base::WriteFile(time_in_state_path_cpu0_, kTimeInStateContentCpu0, + static_cast<int>(strlen(kTimeInStateContentCpu0))) != -1); + ASSERT_TRUE( + base::WriteFile(time_in_state_path_cpu1_, kTimeInStateContentCpu1, + static_cast<int>(strlen(kTimeInStateContentCpu1))) != -1); + std::vector<std::string> cpu_freq_state_names; CpuDataCollector::StateOccupancySample freq_sample_cpu0; CpuDataCollector::StateOccupancySample freq_sample_cpu1; @@ -120,6 +124,11 @@ } TEST_F(CpuDataCollectorTest, ReadCpuFreqAllTimeInState) { + ASSERT_TRUE(base::CreateTemporaryFile(&all_time_in_state_path_)); + ASSERT_TRUE( + base::WriteFile(all_time_in_state_path_, kAllTimeInStateContent, + static_cast<int>(strlen(kAllTimeInStateContent))) != -1); + std::vector<std::string> cpu_freq_state_names; std::vector<CpuDataCollector::StateOccupancySample> freq_samples; CpuDataCollector::StateOccupancySample freq_sample_cpu0; @@ -137,4 +146,31 @@ EXPECT_EQ(kExpectedTimeInStateCpu1, freq_samples[1].time_in_state); } +TEST_F(CpuDataCollectorTest, ReadCpuFreqAllTimeInStateNA) { + ASSERT_TRUE(base::CreateTemporaryFile(&all_time_in_state_path_)); + ASSERT_TRUE(base::WriteFile( + all_time_in_state_path_, kAllTimeInStateContentNA, + static_cast<int>(strlen(kAllTimeInStateContentNA))) != -1); + + std::vector<std::string> cpu_freq_state_names; + std::vector<CpuDataCollector::StateOccupancySample> freq_samples; + CpuDataCollector::StateOccupancySample freq_sample_cpu0; + CpuDataCollector::StateOccupancySample freq_sample_cpu1; + CpuDataCollector::StateOccupancySample freq_sample_cpu2; + // |ReadCpuFreqAllTimeInState| only completes sample for cpu that is online. + freq_sample_cpu0.cpu_online = true; + freq_sample_cpu1.cpu_online = true; + freq_sample_cpu2.cpu_online = true; + freq_samples.push_back(freq_sample_cpu0); + freq_samples.push_back(freq_sample_cpu1); + freq_samples.push_back(freq_sample_cpu2); + + CpuDataCollector::ReadCpuFreqAllTimeInState( + 3, all_time_in_state_path_, &cpu_freq_state_names, &freq_samples); + EXPECT_EQ(kExpectedCpuFreqStateNames, cpu_freq_state_names); + EXPECT_EQ(kExpectedTimeInStateCpu0, freq_samples[0].time_in_state); + EXPECT_EQ(kExpectedTimeInStateCpu1, freq_samples[1].time_in_state); + EXPECT_TRUE(freq_samples[2].time_in_state.empty()); +} + } // namespace chromeos
diff --git a/chrome/browser/extensions/api/cookies/cookies_unittest.cc b/chrome/browser/extensions/api/cookies/cookies_unittest.cc index a236be2..6aeccbf 100644 --- a/chrome/browser/extensions/api/cookies/cookies_unittest.cc +++ b/chrome/browser/extensions/api/cookies/cookies_unittest.cc
@@ -188,7 +188,7 @@ std::unique_ptr<net::CanonicalCookie> canonical_cookie( net::CanonicalCookie::Create(GURL("http://test.com"), "=011Q255bNX_1!yd\203e+;path=/path\203", - base::Time(), net::CookieOptions())); + base::Time::Now(), net::CookieOptions())); ASSERT_NE(nullptr, canonical_cookie.get()); Cookie cookie = cookies_helpers::CreateCookie(*canonical_cookie, "some cookie store");
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index ae5450bd..96f2635 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -415,7 +415,20 @@ cursors.Range.fromNode(evt.target)); } - this.createTextEditHandlerIfNeeded_(evt.target); + // Re-target the node to the root of the editable. + var target = evt.target; + while (target.parent && target.parent.state.editable) + target = target.parent; + var voxTarget = ChromeVoxState.instance.currentRange.start.node; + while (voxTarget && voxTarget.parent && voxTarget.parent.state.editable) + voxTarget = voxTarget.parent; + + // It is possible that ChromeVox has range over some other node + // when a text field is focused. + if (!target.state.focused || target != voxTarget) + return; + + this.createTextEditHandlerIfNeeded_(target); // Sync the ChromeVox range to the editable, if a selection exists. var anchorObject = evt.target.root.anchorObject;
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc index fdb9fa0..7841f9b4 100644 --- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc +++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
@@ -34,6 +34,7 @@ #include "components/autofill/core/common/autofill_constants.h" #include "components/payments/content/payment_request_spec.h" #include "components/payments/content/payment_request_state.h" +#include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/geometry/insets.h" @@ -136,29 +137,6 @@ DISALLOW_COPY_AND_ASSIGN(ExpirationDateValidationDelegate); }; -// Formats card number. For example, "4111111111111111" is formatted into -// "4111 1111 1111 1111". -base::string16 FormatCardNumber(const base::string16& text) { - // Do not format masked card numbers, which start with a letter. - base::string16 number = autofill::CreditCard::StripSeparators(text); - if (number.empty() || !base::IsAsciiDigit(number[0])) - return text; - - std::vector<size_t> positions = {4U, 9U, 14U}; - if (autofill::CreditCard::GetCardNetwork(number) == - autofill::kAmericanExpressCard) { - positions = {4U, 11U}; - } - - static const base::char16 kSeparator = base::ASCIIToUTF16(" ")[0]; - for (size_t i : positions) { - if (number.size() > i) - number.insert(i, 1U, kSeparator); - } - - return number; -} - } // namespace CreditCardEditorViewController::CreditCardEditorViewController( @@ -368,7 +346,9 @@ base::string16 info = credit_card_to_edit_->GetInfo( autofill::AutofillType(type), state()->GetApplicationLocale()); - return type == autofill::CREDIT_CARD_NUMBER ? FormatCardNumber(info) : info; + return type == autofill::CREDIT_CARD_NUMBER + ? data_util::FormatCardNumberForDisplay(info) + : info; } bool CreditCardEditorViewController::ValidateModelAndSave() { @@ -627,7 +607,7 @@ base::string16 CreditCardEditorViewController::CreditCardValidationDelegate::Format( const base::string16& text) { - return FormatCardNumber(text); + return data_util::FormatCardNumberForDisplay(text); } bool CreditCardEditorViewController::CreditCardValidationDelegate::
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 7c39318..53cdd61 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -117,8 +117,12 @@ // print job. Defaults to null if unspecified. const char kCloudPrintPrintTicket[] = "cloud-print-print-ticket"; -// Causes the process to run as a cloud print service process. -const char kCloudPrintServiceProcess[] = "cloud-print-service"; +// The process type value which causes a process to run as a cloud print service +// process. +// +// DO NOT CHANGE THIS VALUE. Cloud printing relies on an external binary +// launching Chrome with this process type. +const char kCloudPrintServiceProcess[] = "service"; // Setup cloud print proxy for provided printers. This does not start // service or register proxy for autostart. @@ -315,8 +319,8 @@ const char kEnableClearBrowsingDataCounters[] = "enable-clear-browsing-data-counters"; -// This applies only when the process type is "cloud-print-service". Enables the -// Cloud Print Proxy component within the service process. +// This applies only when the process type is "service". Enables the Cloud Print +// Proxy component within the service process. const char kEnableCloudPrintProxy[] = "enable-cloud-print-proxy"; // Enable device discovery notifications.
diff --git a/chrome/common/extensions/manifest_handlers/app_launch_info.cc b/chrome/common/extensions/manifest_handlers/app_launch_info.cc index 6506824..74711b0 100644 --- a/chrome/common/extensions/manifest_handlers/app_launch_info.cc +++ b/chrome/common/extensions/manifest_handlers/app_launch_info.cc
@@ -213,8 +213,8 @@ OverrideLaunchURL(extension, gallery_url); } } else if (extension->id() == extension_misc::kCloudPrintAppId) { - // In order for the --cloud-print-service switch to work, we must update - // the launch URL and web extent. + // In order for the --type=service switch to work, we must update the launch + // URL and web extent. GURL url = cloud_devices::GetCloudPrintRelativeURL("enable_chrome_connector"); if (!url.is_empty()) {
diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc index b573e2d1..af1d580 100644 --- a/chrome/install_static/install_util.cc +++ b/chrome/install_static/install_util.cc
@@ -77,7 +77,7 @@ constexpr wchar_t kRegValueUsageStats[] = L"usagestats"; constexpr wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled"; -constexpr wchar_t kCloudPrintServiceProcess[] = L"cloud-print-service"; +constexpr wchar_t kCloudPrintServiceProcess[] = L"service"; constexpr wchar_t kCrashpadHandlerProcess[] = L"crashpad-handler"; #if !defined(DISABLE_NACL) constexpr wchar_t kNaClBrokerProcess[] = L"nacl-broker";
diff --git a/chrome/renderer/safe_browsing/phishing_classifier.cc b/chrome/renderer/safe_browsing/phishing_classifier.cc index 87915f4..d42f506 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier.cc
@@ -42,8 +42,9 @@ // Used for UMA, do not reorder. enum SkipClassificationReason { CLASSIFICATION_PROCEED = 0, - SKIP_HTTPS = 1, + DEPRECATED_SKIP_HTTPS = 1, SKIP_NONE_GET = 2, + SKIP_SCHEME_NOT_SUPPORTED = 3, SKIP_REASON_MAX }; @@ -126,10 +127,10 @@ blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); // Check whether the URL is one that we should classify. - // Currently, we only classify http: URLs that are GET requests. + // Currently, we only classify http/https URLs that are GET requests. GURL url(frame->GetDocument().Url()); - if (!url.SchemeIs(url::kHttpScheme)) { - RecordReasonForSkippingClassificationToUMA(SKIP_HTTPS); + if (!url.SchemeIsHTTPOrHTTPS()) { + RecordReasonForSkippingClassificationToUMA(SKIP_SCHEME_NOT_SUPPORTED); RunFailureCallback(); return; }
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc index 4ee3b99..148fcec 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
@@ -9,30 +9,22 @@ #include <utility> #include "base/bind.h" -#include "base/command_line.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/safe_browsing/client_model.pb.h" +#include "chrome/renderer/chrome_content_renderer_client.h" #include "chrome/renderer/safe_browsing/features.h" #include "chrome/renderer/safe_browsing/mock_feature_extractor_clock.h" #include "chrome/renderer/safe_browsing/murmurhash3_util.h" #include "chrome/renderer/safe_browsing/scorer.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" +#include "chrome/test/base/chrome_render_view_test.h" #include "components/safe_browsing/csd.pb.h" -#include "content/public/browser/render_frame_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/common/content_switches.h" #include "content/public/renderer/render_frame.h" +#include "content/public/renderer/render_view.h" #include "crypto/sha2.h" #include "net/dns/mock_host_resolver.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/embedded_test_server/http_response.h" #include "testing/gmock/include/gmock/gmock.h" +#include "third_party/WebKit/public/platform/WebURLRequest.h" #include "url/gurl.h" using ::testing::AllOf; @@ -42,25 +34,35 @@ namespace safe_browsing { -class PhishingClassifierTest : public InProcessBrowserTest { +class TestChromeContentRendererClient : public ChromeContentRendererClient { + public: + TestChromeContentRendererClient() {} + ~TestChromeContentRendererClient() override {} + // Since visited_link_slave_ in ChromeContentRenderClient never get initiated, + // overrides VisitedLinkedHash() function to prevent crashing. + unsigned long long VisitedLinkHash(const char* canonical_url, + size_t length) override { + return 0LL; + } +}; + +class PhishingClassifierTest : public ChromeRenderViewTest { protected: PhishingClassifierTest() : url_tld_token_net_(features::kUrlTldToken + std::string("net")), page_link_domain_phishing_(features::kPageLinkDomain + std::string("phishing.com")), page_term_login_(features::kPageTerm + std::string("login")), - page_text_(base::ASCIIToUTF16("login")) { + page_text_(base::ASCIIToUTF16("login")), + phishy_score_(PhishingClassifier::kInvalidScore) {} + + void SetUp() override { + ChromeRenderViewTest::SetUp(); + PrepareModel(); + SetUpClassifier(); } - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(switches::kSingleProcess); -#if defined(OS_WIN) - // Don't want to try to create a GPU process. - command_line->AppendSwitch(switches::kDisableGpu); -#endif - } - - void SetUpOnMainThread() override { + void PrepareModel() { // Construct a model to test with. We include one feature from each of // the feature extractors, which allows us to verify that they all ran. ClientSideModel model; @@ -101,106 +103,50 @@ scorer_.reset(Scorer::Create(model.SerializeAsString())); ASSERT_TRUE(scorer_.get()); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - content::RenderFrame* render_frame = content::RenderFrame::FromRoutingID( - web_contents->GetMainFrame()->GetRoutingID()); - classifier_.reset(new PhishingClassifier(render_frame, clock_)); + // These tests don't exercise the extraction timing. + EXPECT_CALL(*clock_, Now()) + .WillRepeatedly(::testing::Return(base::TimeTicks::Now())); + } - embedded_test_server()->RegisterRequestHandler( - base::Bind(&PhishingClassifierTest::HandleRequest, - base::Unretained(this))); - ASSERT_TRUE(embedded_test_server()->Start()); - - host_resolver()->AddRule("*", "127.0.0.1"); - + void SetUpClassifier() { + classifier_.reset( + new PhishingClassifier(view_->GetMainRenderFrame(), clock_)); // No scorer yet, so the classifier is not ready. ASSERT_FALSE(classifier_->is_ready()); // Now set the scorer. classifier_->set_phishing_scorer(scorer_.get()); ASSERT_TRUE(classifier_->is_ready()); - - // These tests don't exercise the extraction timing. - EXPECT_CALL(*clock_, Now()) - .WillRepeatedly(::testing::Return(base::TimeTicks::Now())); } - void TearDownOnMainThread() override { - content::RunAllPendingInMessageLoop(); - } + // Helper method to start phishing classification. + void RunPhishingClassifier(const base::string16* page_text) { + feature_map_.Clear(); - // Helper method to start phishing classification and wait for it to - // complete. Returns the true if the page is classified as phishy and - // false otherwise. - bool RunPhishingClassifier(const base::string16* page_text, - float* phishy_score, - FeatureMap* features) { - ClientPhishingRequest verdict; - // The classifier accesses the RenderFrame and must run in the RenderThread. - PostTaskToInProcessRendererAndWait( - base::Bind(&PhishingClassifierTest::DoRunPhishingClassifier, - base::Unretained(this), - page_text, phishy_score, features, &verdict)); - return verdict.is_phishing(); - } - - void DoRunPhishingClassifier(const base::string16* page_text, - float* phishy_score, - FeatureMap* features, - ClientPhishingRequest* verdict) { - *phishy_score = PhishingClassifier::kInvalidScore; - features->Clear(); - - // Force synchronous behavior for ease of unittesting. - base::RunLoop run_loop; classifier_->BeginClassification( - page_text, - base::Bind(&PhishingClassifierTest::ClassificationFinished, - base::Unretained(this), &run_loop, verdict)); - content::RunThisRunLoop(&run_loop); - - *phishy_score = verdict->client_score(); - for (int i = 0; i < verdict->feature_map_size(); ++i) { - features->AddRealFeature(verdict->feature_map(i).name(), - verdict->feature_map(i).value()); - } + page_text, base::Bind(&PhishingClassifierTest::ClassificationFinished, + base::Unretained(this))); + base::RunLoop().RunUntilIdle(); } // Completion callback for classification. - void ClassificationFinished(base::RunLoop* run_loop, - ClientPhishingRequest* verdict_out, - const ClientPhishingRequest& verdict) { - *verdict_out = verdict; // Copy the verdict. - run_loop->Quit(); + void ClassificationFinished(const ClientPhishingRequest& verdict) { + phishy_score_ = verdict.client_score(); + for (int i = 0; i < verdict.feature_map_size(); ++i) { + feature_map_.AddRealFeature(verdict.feature_map(i).name(), + verdict.feature_map(i).value()); + } + is_phishing_ = verdict.is_phishing(); } - void LoadHtml(const std::string& host, const std::string& content) { - GURL::Replacements replace_host; - replace_host.SetHostStr(host); - response_content_ = content; - ui_test_utils::NavigateToURL( - browser(), - embedded_test_server()->base_url().ReplaceComponents(replace_host)); + void LoadHtml(const GURL& url, const std::string& content) { + LoadHTMLWithUrlOverride(content.c_str(), url.spec().c_str()); } - void LoadHtmlPost(const std::string& host, const std::string& content) { - GURL::Replacements replace_host; - replace_host.SetHostStr(host); - response_content_ = content; - ui_test_utils::NavigateToURLWithPost( - browser(), - embedded_test_server()->base_url().ReplaceComponents(replace_host)); - } - - std::unique_ptr<net::test_server::HttpResponse> HandleRequest( - const net::test_server::HttpRequest& request) { - std::unique_ptr<net::test_server::BasicHttpResponse> http_response( - new net::test_server::BasicHttpResponse()); - http_response->set_code(net::HTTP_OK); - http_response->set_content_type("text/html"); - http_response->set_content(response_content_); - return std::move(http_response); + content::ContentRendererClient* CreateContentRendererClient() override { + ChromeContentRendererClient* client = new TestChromeContentRendererClient(); + InitChromeContentRendererClient(client); + return client; } std::string response_content_; @@ -212,151 +158,110 @@ const std::string url_tld_token_net_; const std::string page_link_domain_phishing_; const std::string page_term_login_; - const base::string16 page_text_; + base::string16 page_text_; + + // Outputs of phishing classifier. + FeatureMap feature_map_; + float phishy_score_; + bool is_phishing_; }; -// This test flakes on Mac with force compositing mode. -// http://crbug.com/316709 -// Flaky on Chrome OS and Linux, running into a memory allocation error. -// http://crbug.com/544085 -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_LINUX) -#define MAYBE_TestClassificationOfPhishingDotCom \ - DISABLED_TestClassificationOfPhishingDotCom -#else -#define MAYBE_TestClassificationOfPhishingDotCom \ - TestClassificationOfPhishingDotCom -#endif -IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, - MAYBE_TestClassificationOfPhishingDotCom) { - float phishy_score; - FeatureMap features; - - LoadHtml("host.net", +TEST_F(PhishingClassifierTest, TestClassificationOfPhishingDotComHttp) { + LoadHtml( + GURL("http://host.net"), "<html><body><a href=\"http://phishing.com/\">login</a></body></html>"); - EXPECT_TRUE(RunPhishingClassifier(&page_text_, &phishy_score, &features)); + RunPhishingClassifier(&page_text_); + // Note: features.features() might contain other features that simply aren't // in the model. - EXPECT_THAT(features.features(), + EXPECT_THAT(feature_map_.features(), AllOf(Contains(Pair(url_tld_token_net_, 1.0)), Contains(Pair(page_link_domain_phishing_, 1.0)), Contains(Pair(page_term_login_, 1.0)))); - EXPECT_FLOAT_EQ(0.5, phishy_score); + EXPECT_FLOAT_EQ(0.5, phishy_score_); + EXPECT_TRUE(is_phishing_); } -// This test flakes on Mac with force compositing mode. -// http://crbug.com/316709 -// Flaky on Chrome OS and Linux, running into a memory allocation error. -// http://crbug.com/544085 -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_LINUX) -#define MAYBE_TestClassificationOfSafeDotCom \ - DISABLED_TestClassificationOfSafeDotCom -#else -#define MAYBE_TestClassificationOfSafeDotCom TestClassificationOfSafeDotCom -#endif -IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, - MAYBE_TestClassificationOfSafeDotCom) { - float phishy_score; - FeatureMap features; +TEST_F(PhishingClassifierTest, TestClassificationOfPhishingDotComHttps) { + // Host the target page on HTTPS. + LoadHtml( + GURL("https://host.net"), + "<html><body><a href=\"http://phishing.com/\">login</a></body></html>"); + RunPhishingClassifier(&page_text_); + // Note: features.features() might contain other features that simply aren't + // in the model. + EXPECT_THAT(feature_map_.features(), + AllOf(Contains(Pair(url_tld_token_net_, 1.0)), + Contains(Pair(page_link_domain_phishing_, 1.0)), + Contains(Pair(page_term_login_, 1.0)))); + EXPECT_FLOAT_EQ(0.5, phishy_score_); + EXPECT_TRUE(is_phishing_); +} + +TEST_F(PhishingClassifierTest, TestClassificationOfSafeDotComHttp) { // Change the link domain to something non-phishy. - LoadHtml("host.net", + LoadHtml(GURL("http://host.net"), "<html><body><a href=\"http://safe.com/\">login</a></body></html>"); - EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features)); - EXPECT_THAT(features.features(), + RunPhishingClassifier(&page_text_); + + EXPECT_THAT(feature_map_.features(), AllOf(Contains(Pair(url_tld_token_net_, 1.0)), Contains(Pair(page_term_login_, 1.0)))); - EXPECT_THAT(features.features(), + EXPECT_THAT(feature_map_.features(), Not(Contains(Pair(page_link_domain_phishing_, 1.0)))); - EXPECT_GE(phishy_score, 0.0); - EXPECT_LT(phishy_score, 0.5); + EXPECT_GE(phishy_score_, 0.0); + EXPECT_LT(phishy_score_, 0.5); + EXPECT_FALSE(is_phishing_); } -// This test flakes on Mac with force compositing mode. -// http://crbug.com/316709 -// Flaky on Chrome OS and Linux, running into a memory allocation error. -// http://crbug.com/544085 -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_LINUX) -#define MAYBE_TestClassificationWhenNoTld DISABLED_TestClassificationWhenNoTld -#else -#define MAYBE_TestClassificationWhenNoTld TestClassificationWhenNoTld -#endif -IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, - MAYBE_TestClassificationWhenNoTld) { - float phishy_score; - FeatureMap features; +TEST_F(PhishingClassifierTest, TestClassificationOfSafeDotComHttps) { + // Host target page in HTTPS and change the link domain to something + // non-phishy. + LoadHtml(GURL("https://host.net"), + "<html><body><a href=\"http://safe.com/\">login</a></body></html>"); + RunPhishingClassifier(&page_text_); + EXPECT_THAT(feature_map_.features(), + AllOf(Contains(Pair(url_tld_token_net_, 1.0)), + Contains(Pair(page_term_login_, 1.0)))); + EXPECT_THAT(feature_map_.features(), + Not(Contains(Pair(page_link_domain_phishing_, 1.0)))); + EXPECT_GE(phishy_score_, 0.0); + EXPECT_LT(phishy_score_, 0.5); + EXPECT_FALSE(is_phishing_); +} + +TEST_F(PhishingClassifierTest, TestClassificationWhenNoTld) { // Extraction should fail for this case since there is no TLD. - LoadHtml("localhost", "<html><body>content</body></html>"); - EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features)); - EXPECT_EQ(0U, features.features().size()); - EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score); + LoadHtml(GURL("http://localhost"), "<html><body>content</body></html>"); + RunPhishingClassifier(&page_text_); + + EXPECT_EQ(0U, feature_map_.features().size()); + EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score_); + EXPECT_FALSE(is_phishing_); } -// This test flakes on Mac with force compositing mode. -// http://crbug.com/316709 -// Flaky on Chrome OS and Linux, running into a memory allocation error. -// http://crbug.com/544085 -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_LINUX) -#define MAYBE_TestClassificationWhenNotHttp \ - DISABLED_TestClassificationWhenNotHttp -#else -#define MAYBE_TestClassificationWhenNotHttp TestClassificationWhenNotHttp -#endif -IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, - MAYBE_TestClassificationWhenNotHttp) { - float phishy_score; - FeatureMap features; +TEST_F(PhishingClassifierTest, TestClassificationWhenSchemeNotSupported) { + // Extraction should also fail for this case because the URL is not http or + // https. + LoadHtml(GURL("file://host.net"), "<html><body>content</body></html>"); + RunPhishingClassifier(&page_text_); - // Extraction should also fail for this case because the URL is not http. - net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS); - https_server.ServeFilesFromSourceDirectory("chrome/test/data"); - ASSERT_TRUE(https_server.Start()); - GURL::Replacements replace_host; - replace_host.SetHostStr("host.net"); - GURL test_url = https_server.GetURL("/title1.html"); - ui_test_utils::NavigateToURL(browser(), - test_url.ReplaceComponents(replace_host)); - EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features)); - EXPECT_EQ(0U, features.features().size()); - EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score); + EXPECT_EQ(0U, feature_map_.features().size()); + EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score_); + EXPECT_FALSE(is_phishing_); } -// This test flakes on Mac with force compositing mode. -// http://crbug.com/316709 -// Flaky on Chrome OS and Linux, running into a memory allocation error. -// http://crbug.com/544085 -#if defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_LINUX) -#define MAYBE_TestClassificationWhenPostRequest \ - DISABLED_TestClassificationWhenPostRequest -#else -#define MAYBE_TestClassificationWhenPostRequest \ - TestClassificationWhenPostRequest -#endif -IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, - MAYBE_TestClassificationWhenPostRequest) { - float phishy_score; - FeatureMap features; - - // Extraction should fail for this case because the URL is a POST request. - LoadHtmlPost("host.net", "<html><body>content</body></html>"); - EXPECT_FALSE(RunPhishingClassifier(&page_text_, &phishy_score, &features)); - EXPECT_EQ(0U, features.features().size()); - EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score); -} - -// Test flakes with LSAN enabled. See http://crbug.com/373155. -// Flaky on Linux. See http://crbug.com/638557. -#if defined(LEAK_SANITIZER) || defined(OS_LINUX) -#define MAYBE_DisableDetection DISABLED_DisableDetection -#else -#define MAYBE_DisableDetection DisableDetection -#endif -IN_PROC_BROWSER_TEST_F(PhishingClassifierTest, MAYBE_DisableDetection) { +TEST_F(PhishingClassifierTest, DisableDetection) { EXPECT_TRUE(classifier_->is_ready()); - // Set a NULL scorer, which turns detection back off. classifier_->set_phishing_scorer(NULL); EXPECT_FALSE(classifier_->is_ready()); } +// TODO(jialiul): Add test to verify that classification only starts on GET +// method. It seems there is no easy way to simulate a HTTP POST in +// ChromeRenderViewTest. + } // namespace safe_browsing
diff --git a/components/crash/content/app/breakpad_win.cc b/components/crash/content/app/breakpad_win.cc index 3324f1f..0604383e 100644 --- a/components/crash/content/app/breakpad_win.cc +++ b/components/crash/content/app/breakpad_win.cc
@@ -547,7 +547,7 @@ if (process_type == L"browser") { callback = &DumpDoneCallback; default_filter = &ChromeExceptionFilter; - } else if (process_type == L"cloud-print-service") { + } else if (process_type == L"service") { callback = &DumpDoneCallback; default_filter = &CloudPrintServiceExceptionFilter; }
diff --git a/components/download/internal/config.cc b/components/download/internal/config.cc index 4aa195b..a25aa634 100644 --- a/components/download/internal/config.cc +++ b/components/download/internal/config.cc
@@ -19,7 +19,7 @@ const uint32_t kDefaultMaxConcurrentDownloads = 4; // Default value for maximum running downloads of the download service. -const uint32_t kDefaultMaxRunningDownloads = 1; +const uint32_t kDefaultMaxRunningDownloads = 2; // Default value for maximum scheduled downloads. const uint32_t kDefaultMaxScheduledDownloads = 15;
diff --git a/components/download/internal/config.h b/components/download/internal/config.h index 8135020..9abd50e 100644 --- a/components/download/internal/config.h +++ b/components/download/internal/config.h
@@ -54,8 +54,8 @@ // only Active state. uint32_t max_running_downloads; - // The maximum number of downloads that are scheduled but not yet in Active - // state, for each client using the download service. + // The maximum number of downloads that are scheduled for each client using + // the download service. uint32_t max_scheduled_downloads; // The maximum number of retries before the download is aborted.
diff --git a/components/download/internal/controller_impl.cc b/components/download/internal/controller_impl.cc index 2858f71..43fa783 100644 --- a/components/download/internal/controller_impl.cc +++ b/components/download/internal/controller_impl.cc
@@ -786,7 +786,17 @@ if (initializing_internals_) return; - // TODO(xingliu): Check the configuration to throttle downloads. + // Check the configuration to throttle number of downloads. + std::map<Entry::State, uint32_t> entries_states; + for (const auto* const entry : model_->PeekEntries()) + entries_states[entry->state]++; + uint32_t paused_count = entries_states[Entry::State::PAUSED]; + uint32_t active_count = entries_states[Entry::State::ACTIVE]; + if (config_->max_concurrent_downloads <= paused_count + active_count || + config_->max_running_downloads <= active_count) { + return; + } + Entry* next = scheduler_->Next( model_->PeekEntries(), device_status_listener_->CurrentDeviceStatus());
diff --git a/components/download/internal/controller_impl_unittest.cc b/components/download/internal/controller_impl_unittest.cc index 3206db1..5da8cdad7 100644 --- a/components/download/internal/controller_impl_unittest.cc +++ b/components/download/internal/controller_impl_unittest.cc
@@ -122,6 +122,8 @@ config_ = base::MakeUnique<Configuration>(); config_->file_keep_alive_time = base::TimeDelta::FromMinutes(10); config_->file_cleanup_window = base::TimeDelta::FromMinutes(5); + config_->max_concurrent_downloads = 5; + config_->max_running_downloads = 5; client_ = client.get(); driver_ = driver.get(); @@ -571,7 +573,7 @@ } TEST_F(DownloadServiceControllerImplTest, Resume) { - // Setupd download service test data. + // Setup download service test data. Entry entry1 = test::BuildBasicEntry(); Entry entry2 = test::BuildBasicEntry(); entry1.state = Entry::State::PAUSED; @@ -1109,4 +1111,63 @@ EXPECT_EQ(1u, updated_entries.size()); } +// Ensures no more downloads are activated if the number of downloads exceeds +// the max running download configuration. +TEST_F(DownloadServiceControllerImplTest, ThrottlingConfigMaxRunning) { + Entry entry1 = test::BuildBasicEntry(Entry::State::AVAILABLE); + Entry entry2 = test::BuildBasicEntry(Entry::State::ACTIVE); + std::vector<Entry> entries = {entry1, entry2}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + + // Setup the Configuration. + config_->max_concurrent_downloads = 1u; + config_->max_running_downloads = 1u; + + // Setup the controller. + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + store_->AutomaticallyTriggerAllFutureCallbacks(true); + + // Hit the max running configuration threshold, nothing should be called. + EXPECT_CALL(*scheduler_, Next(_, _)).Times(0); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(0); + driver_->MakeReady(); + task_runner_->RunUntilIdle(); + + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entry1.guid)->state); +} + +// Ensures max concurrent download configuration considers both active and +// paused downloads. +TEST_F(DownloadServiceControllerImplTest, ThrottlingConfigMaxConcurrent) { + Entry entry1 = test::BuildBasicEntry(Entry::State::AVAILABLE); + Entry entry2 = test::BuildBasicEntry(Entry::State::PAUSED); + std::vector<Entry> entries = {entry1, entry2}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + + // Setup the Configuration. + config_->max_concurrent_downloads = 2u; + config_->max_running_downloads = 1u; + + // Setup the controller. + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + store_->AutomaticallyTriggerAllFutureCallbacks(true); + + // Can have one more download due to max concurrent configuration. + testing::InSequence seq; + EXPECT_CALL(*scheduler_, Next(_, _)) + .Times(1) + .WillOnce(Return(model_->Get(entry1.guid))) + .RetiresOnSaturation(); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1).RetiresOnSaturation(); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); + driver_->MakeReady(); + task_runner_->RunUntilIdle(); + + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry1.guid)->state); +} + } // namespace download
diff --git a/components/exo/wayland/clients/client_base.cc b/components/exo/wayland/clients/client_base.cc index e6043678..5ae9136 100644 --- a/components/exo/wayland/clients/client_base.cc +++ b/components/exo/wayland/clients/client_base.cc
@@ -112,25 +112,11 @@ } #if defined(OZONE_PLATFORM_GBM) -void LinuxBufferParamsCreated(void* data, - zwp_linux_buffer_params_v1* params, - wl_buffer* new_buffer) { - ClientBase::Buffer* buffer = static_cast<ClientBase::Buffer*>(data); - buffer->buffer.reset(new_buffer); -} - -void LinuxBufferParamsFailed(void* data, zwp_linux_buffer_params_v1* params) { - LOG(ERROR) << "Linux buffer params failed"; -} - const GrGLInterface* GrGLCreateNativeInterface() { return GrGLAssembleInterface(nullptr, [](void* ctx, const char name[]) { return eglGetProcAddress(name); }); } - -zwp_linux_buffer_params_v1_listener g_params_listener = { - LinuxBufferParamsCreated, LinuxBufferParamsFailed}; #endif wl_registry_listener g_registry_listener = {RegistryHandler, RegistryRemover}; @@ -313,10 +299,11 @@ buffers_.push_back(std::move(buffer)); } - wl_display_roundtrip(display_.get()); for (size_t i = 0; i < buffers_.size(); ++i) { + // If the buffer handle doesn't exist, we would either be killed by the + // server or die here. if (!buffers_[i]->buffer) { - LOG(ERROR) << "LinuxBufferParamsCreated was not called on the buffer."; + LOG(ERROR) << "buffer handle uninitialized."; return false; } @@ -388,8 +375,6 @@ buffer->params.reset( zwp_linux_dmabuf_v1_create_params(globals_.linux_dmabuf.get())); - zwp_linux_buffer_params_v1_add_listener(buffer->params.get(), - &g_params_listener, buffer.get()); for (size_t i = 0; i < gbm_bo_get_num_planes(buffer->bo.get()); ++i) { base::ScopedFD fd(gbm_bo_get_plane_fd(buffer->bo.get(), i)); uint32_t stride = gbm_bo_get_plane_stride(buffer->bo.get(), i); @@ -397,8 +382,8 @@ zwp_linux_buffer_params_v1_add(buffer->params.get(), fd.get(), i, offset, stride, 0, 0); } - zwp_linux_buffer_params_v1_create(buffer->params.get(), width_, height_, - drm_format, 0); + buffer->buffer.reset(zwp_linux_buffer_params_v1_create_immed( + buffer->params.get(), width_, height_, drm_format, 0)); if (gbm_bo_get_num_planes(buffer->bo.get()) != 1) return buffer;
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index b0ddd35..d7246bd 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -658,19 +658,55 @@ } } +bool ValidateLinuxBufferParams(wl_resource* resource, + int32_t width, + int32_t height, + gfx::BufferFormat format, + uint32_t flags) { + if (width <= 0 || height <= 0) { + wl_resource_post_error(resource, + ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, + "invalid width or height"); + return false; + } + + if (flags & (ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT | + ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED)) { + wl_resource_post_error(resource, + ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, + "flags not supported"); + return false; + } + + LinuxBufferParams* linux_buffer_params = + GetUserDataAs<LinuxBufferParams>(resource); + size_t num_planes = gfx::NumberOfPlanesForBufferFormat(format); + + for (uint32_t i = 0; i < num_planes; ++i) { + auto plane_it = linux_buffer_params->planes.find(i); + if (plane_it == linux_buffer_params->planes.end()) { + wl_resource_post_error(resource, + ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, + "missing a plane"); + return false; + } + } + + if (linux_buffer_params->planes.size() != num_planes) { + wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, + "plane idx out of bounds"); + return false; + } + + return true; +} + void linux_buffer_params_create(wl_client* client, wl_resource* resource, int32_t width, int32_t height, uint32_t format, uint32_t flags) { - if (width <= 0 || height <= 0) { - wl_resource_post_error(resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, - "invalid width or height"); - return; - } - const auto* supported_format = std::find_if( std::begin(dmabuf_supported_formats), std::end(dmabuf_supported_formats), [format](const dmabuf_supported_format& supported_format) { @@ -683,13 +719,9 @@ return; } - if (flags & (ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT | - ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED)) { - wl_resource_post_error(resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, - "flags not supported"); + if (!ValidateLinuxBufferParams(resource, width, height, + supported_format->buffer_format, flags)) return; - } LinuxBufferParams* linux_buffer_params = GetUserDataAs<LinuxBufferParams>(resource); @@ -697,23 +729,11 @@ size_t num_planes = gfx::NumberOfPlanesForBufferFormat(supported_format->buffer_format); - if (linux_buffer_params->planes.size() != num_planes) { - wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, - "plane idx out of bounds"); - return; - } - std::vector<gfx::NativePixmapPlane> planes; std::vector<base::ScopedFD> fds; for (uint32_t i = 0; i < num_planes; ++i) { auto plane_it = linux_buffer_params->planes.find(i); - if (plane_it == linux_buffer_params->planes.end()) { - wl_resource_post_error(resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, - "missing a plane"); - return; - } LinuxBufferParams::Plane& plane = plane_it->second; planes.emplace_back(plane.stride, plane.offset, 0, 0); fds.push_back(std::move(plane.fd)); @@ -739,10 +759,71 @@ zwp_linux_buffer_params_v1_send_created(resource, buffer_resource); } +void linux_buffer_params_create_immed(wl_client* client, + wl_resource* resource, + uint32_t buffer_id, + int32_t width, + int32_t height, + uint32_t format, + uint32_t flags) { + const auto* supported_format = std::find_if( + std::begin(dmabuf_supported_formats), std::end(dmabuf_supported_formats), + [format](const dmabuf_supported_format& supported_format) { + return supported_format.dmabuf_format == format; + }); + if (supported_format == std::end(dmabuf_supported_formats)) { + wl_resource_post_error(resource, + ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, + "format not supported"); + return; + } + + if (!ValidateLinuxBufferParams(resource, width, height, + supported_format->buffer_format, flags)) + return; + + LinuxBufferParams* linux_buffer_params = + GetUserDataAs<LinuxBufferParams>(resource); + + size_t num_planes = + gfx::NumberOfPlanesForBufferFormat(supported_format->buffer_format); + + std::vector<gfx::NativePixmapPlane> planes; + std::vector<base::ScopedFD> fds; + + for (uint32_t i = 0; i < num_planes; ++i) { + auto plane_it = linux_buffer_params->planes.find(i); + LinuxBufferParams::Plane& plane = plane_it->second; + planes.emplace_back(plane.stride, plane.offset, 0, 0); + fds.push_back(std::move(plane.fd)); + } + + std::unique_ptr<Buffer> buffer = + linux_buffer_params->display->CreateLinuxDMABufBuffer( + gfx::Size(width, height), supported_format->buffer_format, planes, + std::move(fds)); + if (!buffer) { + // On import failure in case of a create_immed request, the protocol + // allows us to raise a fatal error from zwp_linux_dmabuf_v1 version 2+. + wl_resource_post_error(resource, + ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, + "dmabuf import failed"); + return; + } + + wl_resource* buffer_resource = + wl_resource_create(client, &wl_buffer_interface, 1, buffer_id); + + buffer->set_release_callback(base::Bind(&HandleBufferReleaseCallback, + base::Unretained(buffer_resource))); + + SetImplementation(buffer_resource, &buffer_implementation, std::move(buffer)); +} + const struct zwp_linux_buffer_params_v1_interface - linux_buffer_params_implementation = {linux_buffer_params_destroy, - linux_buffer_params_add, - linux_buffer_params_create}; + linux_buffer_params_implementation = { + linux_buffer_params_destroy, linux_buffer_params_add, + linux_buffer_params_create, linux_buffer_params_create_immed}; //////////////////////////////////////////////////////////////////////////////// // linux_dmabuf_interface: @@ -758,7 +839,7 @@ base::MakeUnique<LinuxBufferParams>(GetUserDataAs<Display>(resource)); wl_resource* linux_buffer_params_resource = - wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, 1, id); + wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, 2, id); SetImplementation(linux_buffer_params_resource, &linux_buffer_params_implementation, @@ -773,7 +854,7 @@ uint32_t version, uint32_t id) { wl_resource* resource = - wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, 1, id); + wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, version, id); wl_resource_set_implementation(resource, &linux_dmabuf_implementation, data, nullptr); @@ -3996,7 +4077,7 @@ #if defined(USE_OZONE) wl_global_create(wl_display_.get(), &wl_drm_interface, drm_version, display_, bind_drm); - wl_global_create(wl_display_.get(), &zwp_linux_dmabuf_v1_interface, 1, + wl_global_create(wl_display_.get(), &zwp_linux_dmabuf_v1_interface, 2, display_, bind_linux_dmabuf); #endif wl_global_create(wl_display_.get(), &wl_subcompositor_interface, 1, display_,
diff --git a/components/favicon/core/favicon_service.h b/components/favicon/core/favicon_service.h index d361800..60552b1 100644 --- a/components/favicon/core/favicon_service.h +++ b/components/favicon/core/favicon_service.h
@@ -139,6 +139,15 @@ // Marks all types of favicon for the page as being out of date. virtual void SetFaviconOutOfDateForPage(const GURL& page_url) = 0; + // Mark that the on-demand favicon at |icon_url| was requested now. This + // postpones the automatic eviction of the favicon from the database. Not all + // calls end up in a write into the DB: + // - It is no-op if the bitmaps are not stored using SetOnDemandFavicons(). + // - The updates of the "last requested time" have limited frequency for each + // particular favicon (e.g. once per week). This limits the overhead of + // cache management for on-demand favicons. + virtual void TouchOnDemandFavicon(const GURL& icon_url) = 0; + // Allows the importer to set many favicons for many pages at once. The pages // must exist, any favicon sets for unknown pages will be discarded. Existing // favicons will not be overwritten. @@ -171,19 +180,29 @@ favicon_base::IconType icon_type, const gfx::Image& image) = 0; - // Same as SetFavicons() with three differences: + // Same as SetFavicons with three differences: // 1) It will be a no-op if there is an existing cached favicon for *any* type // for |page_url|. // 2) If |icon_url| is known to the database, |bitmaps| will be ignored (i.e. // the icon won't be overwritten) but the mappings from |page_url| to // |icon_url| will be stored (conditioned to point 1 above). - // 3) If |icon_url| is stored, it will be marked as expired. + // 3) If |icon_url| is stored, it will be marked as "on-demand". + // + // On-demand favicons are those that are fetched without visiting their page. + // For this reason, their life-time cannot be bound to the life-time of the + // corresponding visit in history. + // - These bitmaps are evicted from the database based on the last time they + // get requested. The last requested time is initially set to Now() and is + // further updated by calling TouchOnDemandFavicon(). + // - Furthermore, on-demand bitmaps are immediately marked as expired. Hence, + // they are always replaced by standard favicons whenever their page gets + // visited. // The callback will receive whether the write actually happened. - virtual void SetLastResortFavicons(const GURL& page_url, - const GURL& icon_url, - favicon_base::IconType icon_type, - const gfx::Image& image, - base::Callback<void(bool)> callback) = 0; + virtual void SetOnDemandFavicons(const GURL& page_url, + const GURL& icon_url, + favicon_base::IconType icon_type, + const gfx::Image& image, + base::Callback<void(bool)> callback) = 0; // Avoid repeated requests to download missing favicon. virtual void UnableToDownloadFavicon(const GURL& icon_url) = 0;
diff --git a/components/favicon/core/favicon_service_impl.cc b/components/favicon/core/favicon_service_impl.cc index 55ac6b22..4522aad 100644 --- a/components/favicon/core/favicon_service_impl.cc +++ b/components/favicon/core/favicon_service_impl.cc
@@ -209,6 +209,10 @@ history_service_->SetFaviconsOutOfDateForPage(page_url); } +void FaviconServiceImpl::TouchOnDemandFavicon(const GURL& icon_url) { + history_service_->TouchOnDemandFavicon(icon_url); +} + void FaviconServiceImpl::SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage) { history_service_->SetImportedFavicons(favicon_usage); @@ -232,13 +236,13 @@ ExtractSkBitmapsToStore(image)); } -void FaviconServiceImpl::SetLastResortFavicons( +void FaviconServiceImpl::SetOnDemandFavicons( const GURL& page_url, const GURL& icon_url, favicon_base::IconType icon_type, const gfx::Image& image, base::Callback<void(bool)> callback) { - history_service_->SetLastResortFavicons( + history_service_->SetOnDemandFavicons( page_url, icon_type, icon_url, ExtractSkBitmapsToStore(image), callback); }
diff --git a/components/favicon/core/favicon_service_impl.h b/components/favicon/core/favicon_service_impl.h index e1cb63c..7ad2d0a 100644 --- a/components/favicon/core/favicon_service_impl.h +++ b/components/favicon/core/favicon_service_impl.h
@@ -91,6 +91,7 @@ const favicon_base::FaviconRawBitmapCallback& callback, base::CancelableTaskTracker* tracker) override; void SetFaviconOutOfDateForPage(const GURL& page_url) override; + void TouchOnDemandFavicon(const GURL& icon_url) override; void SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage) override; void MergeFavicon(const GURL& page_url, @@ -102,11 +103,11 @@ const GURL& icon_url, favicon_base::IconType icon_type, const gfx::Image& image) override; - void SetLastResortFavicons(const GURL& page_url, - const GURL& icon_url, - favicon_base::IconType icon_type, - const gfx::Image& image, - base::Callback<void(bool)> callback) override; + void SetOnDemandFavicons(const GURL& page_url, + const GURL& icon_url, + favicon_base::IconType icon_type, + const gfx::Image& image, + base::Callback<void(bool)> callback) override; void UnableToDownloadFavicon(const GURL& icon_url) override; bool WasUnableToDownloadFavicon(const GURL& icon_url) const override; void ClearUnableToDownloadFavicons() override;
diff --git a/components/favicon/core/large_icon_service.cc b/components/favicon/core/large_icon_service.cc index 660b3a3..043678a 100644 --- a/components/favicon/core/large_icon_service.cc +++ b/components/favicon/core/large_icon_service.cc
@@ -297,9 +297,9 @@ // something else could've been written). By marking the icons initially // expired (out-of-date), they will be refetched when we visit the original // page any time in the future. - favicon_service->SetLastResortFavicons(page_url, GURL(original_icon_url), - favicon_base::IconType::TOUCH_ICON, - image, callback); + favicon_service->SetOnDemandFavicons(page_url, GURL(original_icon_url), + favicon_base::IconType::TOUCH_ICON, + image, callback); } } // namespace
diff --git a/components/favicon/core/large_icon_service_unittest.cc b/components/favicon/core/large_icon_service_unittest.cc index 7c65371..23a2a67 100644 --- a/components/favicon/core/large_icon_service_unittest.cc +++ b/components/favicon/core/large_icon_service_unittest.cc
@@ -157,8 +157,8 @@ .WillOnce(PostFetchReply(gfx::Image::CreateFrom1xBitmap( CreateTestSkBitmap(64, 64, kTestColor)))); EXPECT_CALL(mock_favicon_service_, - SetLastResortFavicons(GURL(kDummyUrl), kExpectedServerUrl, - favicon_base::IconType::TOUCH_ICON, _, _)) + SetOnDemandFavicons(GURL(kDummyUrl), kExpectedServerUrl, + favicon_base::IconType::TOUCH_ICON, _, _)) .WillOnce(PostBoolReply(true)); large_icon_service_ @@ -194,8 +194,8 @@ .WillOnce(PostFetchReply(gfx::Image::CreateFrom1xBitmap( CreateTestSkBitmap(64, 64, kTestColor)))); EXPECT_CALL(mock_favicon_service_, - SetLastResortFavicons(GURL(kDummyUrl), kExpectedServerUrl, - favicon_base::IconType::TOUCH_ICON, _, _)) + SetOnDemandFavicons(GURL(kDummyUrl), kExpectedServerUrl, + favicon_base::IconType::TOUCH_ICON, _, _)) .WillOnce(PostBoolReply(true)); large_icon_service_ @@ -224,8 +224,8 @@ CreateTestSkBitmap(64, 64, kTestColor)), expected_metadata)); EXPECT_CALL(mock_favicon_service_, - SetLastResortFavicons(GURL(kDummyUrl), kExpectedOriginalUrl, - favicon_base::IconType::TOUCH_ICON, _, _)) + SetOnDemandFavicons(GURL(kDummyUrl), kExpectedOriginalUrl, + favicon_base::IconType::TOUCH_ICON, _, _)) .WillOnce(PostBoolReply(true)); base::MockCallback<base::Callback<void(bool success)>> callback; @@ -252,7 +252,7 @@ CreateTestSkBitmap(64, 64, kTestColor)))); // Verify that the non-trimmed page URL is used when writing to the database. EXPECT_CALL(mock_favicon_service_, - SetLastResortFavicons(_, kExpectedServerUrl, _, _, _)); + SetOnDemandFavicons(_, kExpectedServerUrl, _, _, _)); large_icon_service_ .GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( @@ -311,7 +311,7 @@ "&check_seen=true&size=61&min_size=42&max_size=122" "&fallback_opts=TYPE,SIZE,URL&url=http://www.example.com/"); - EXPECT_CALL(mock_favicon_service_, SetLastResortFavicons(_, _, _, _, _)) + EXPECT_CALL(mock_favicon_service_, SetOnDemandFavicons(_, _, _, _, _)) .Times(0); base::MockCallback<base::Callback<void(bool success)>> callback; @@ -346,7 +346,7 @@ EXPECT_CALL(mock_favicon_service_, UnableToDownloadFavicon(_)).Times(0); EXPECT_CALL(*mock_image_fetcher_, StartOrQueueNetworkRequest(_, _, _, _)) .Times(0); - EXPECT_CALL(mock_favicon_service_, SetLastResortFavicons(_, _, _, _, _)) + EXPECT_CALL(mock_favicon_service_, SetOnDemandFavicons(_, _, _, _, _)) .Times(0); base::MockCallback<base::Callback<void(bool success)>> callback;
diff --git a/components/favicon/core/test/mock_favicon_service.h b/components/favicon/core/test/mock_favicon_service.h index a4cace7..c9da0a1 100644 --- a/components/favicon/core/test/mock_favicon_service.h +++ b/components/favicon/core/test/mock_favicon_service.h
@@ -89,6 +89,7 @@ const favicon_base::FaviconRawBitmapCallback& callback, base::CancelableTaskTracker* tracker)); MOCK_METHOD1(SetFaviconOutOfDateForPage, void(const GURL& page_url)); + MOCK_METHOD1(TouchOnDemandFavicon, void(const GURL& icon_url)); MOCK_METHOD1(SetImportedFavicons, void(const favicon_base::FaviconUsageDataList& favicon_usage)); MOCK_METHOD5(MergeFavicon, @@ -102,7 +103,7 @@ const GURL& icon_url, favicon_base::IconType icon_type, const gfx::Image& image)); - MOCK_METHOD5(SetLastResortFavicons, + MOCK_METHOD5(SetOnDemandFavicons, void(const GURL& page_url, const GURL& icon_url, favicon_base::IconType icon_type,
diff --git a/components/history/core/browser/android/favicon_sql_handler.cc b/components/history/core/browser/android/favicon_sql_handler.cc index dd7a094e..b630bae 100644 --- a/components/history/core/browser/android/favicon_sql_handler.cc +++ b/components/history/core/browser/android/favicon_sql_handler.cc
@@ -39,7 +39,8 @@ // icon is already in database, just create a new favicon. // TODO(pkotwicz): Pass in real pixel size. favicon_base::FaviconID favicon_id = thumbnail_db_->AddFavicon( - GURL(), favicon_base::FAVICON, row.favicon(), Time::Now(), gfx::Size()); + GURL(), favicon_base::FAVICON, row.favicon(), FaviconBitmapType::ON_VISIT, + Time::Now(), gfx::Size()); if (!favicon_id) return false; @@ -104,7 +105,8 @@ // Is it a problem to give a empty URL? // TODO(pkotwicz): Pass in real pixel size. favicon_base::FaviconID id = thumbnail_db_->AddFavicon( - GURL(), favicon_base::FAVICON, row->favicon(), Time::Now(), gfx::Size()); + GURL(), favicon_base::FAVICON, row->favicon(), + FaviconBitmapType::ON_VISIT, Time::Now(), gfx::Size()); if (!id) return false; return thumbnail_db_->AddIconMapping(row->url(), id);
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 1c4aa6a04..a05f7546 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -1636,8 +1636,9 @@ thumbnail_db_->DeleteFaviconBitmap(bitmap_id_sizes[0].bitmap_id); favicon_sizes.erase(favicon_sizes.begin()); } - thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, base::Time::Now(), - pixel_size); + thumbnail_db_->AddFaviconBitmap(favicon_id, bitmap_data, + FaviconBitmapType::ON_VISIT, + base::Time::Now(), pixel_size); favicon_sizes.push_back(pixel_size); } @@ -1698,9 +1699,10 @@ // Add the favicon bitmap as expired as it is not consistent with the // merged in data. - thumbnail_db_->AddFaviconBitmap( - favicon_id, bitmaps_to_copy[j].bitmap_data, base::Time(), - bitmaps_to_copy[j].pixel_size); + thumbnail_db_->AddFaviconBitmap(favicon_id, + bitmaps_to_copy[j].bitmap_data, + FaviconBitmapType::ON_VISIT, base::Time(), + bitmaps_to_copy[j].pixel_size); favicon_sizes.push_back(bitmaps_to_copy[j].pixel_size); favicon_bitmaps_copied = true; @@ -1733,14 +1735,13 @@ const GURL& icon_url, const std::vector<SkBitmap>& bitmaps) { SetFaviconsImpl(page_url, icon_type, icon_url, bitmaps, - /*bitmaps_are_expired=*/false); + FaviconBitmapType::ON_VISIT); } -bool HistoryBackend::SetLastResortFavicons( - const GURL& page_url, - favicon_base::IconType icon_type, - const GURL& icon_url, - const std::vector<SkBitmap>& bitmaps) { +bool HistoryBackend::SetOnDemandFavicons(const GURL& page_url, + favicon_base::IconType icon_type, + const GURL& icon_url, + const std::vector<SkBitmap>& bitmaps) { if (!thumbnail_db_ || !db_) return false; @@ -1751,7 +1752,7 @@ } return SetFaviconsImpl(page_url, icon_type, icon_url, bitmaps, - /*bitmaps_are_expired=*/true); + FaviconBitmapType::ON_DEMAND); } void HistoryBackend::SetFaviconsOutOfDateForPage(const GURL& page_url) { @@ -1768,6 +1769,14 @@ ScheduleCommit(); } +void HistoryBackend::TouchOnDemandFavicon(const GURL& icon_url) { + if (!thumbnail_db_) + return; + + thumbnail_db_->TouchOnDemandFavicon(icon_url, Time::Now()); + ScheduleCommit(); +} + void HistoryBackend::SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage) { if (!db_ || !thumbnail_db_) @@ -1787,8 +1796,8 @@ // TODO(pkotwicz): Pass in real pixel size. favicon_id = thumbnail_db_->AddFavicon( favicon_usage[i].favicon_url, favicon_base::FAVICON, - new base::RefCountedBytes(favicon_usage[i].png_data), now, - gfx::Size()); + new base::RefCountedBytes(favicon_usage[i].png_data), + FaviconBitmapType::ON_VISIT, now, gfx::Size()); } // Save the mapping from all the URLs to the favicon. @@ -1833,7 +1842,7 @@ favicon_base::IconType icon_type, const GURL& icon_url, const std::vector<SkBitmap>& bitmaps, - bool bitmaps_are_expired) { + FaviconBitmapType type) { if (!thumbnail_db_ || !db_) return false; @@ -1849,11 +1858,9 @@ } bool favicon_data_modified = false; - if (favicon_created || !bitmaps_are_expired) - favicon_data_modified = SetFaviconBitmaps(icon_id, bitmaps); - - if (favicon_created && bitmaps_are_expired) - thumbnail_db_->SetFaviconOutOfDate(icon_id); + if (favicon_created || type == FaviconBitmapType::ON_VISIT) { + favicon_data_modified = SetFaviconBitmaps(icon_id, bitmaps, type); + } std::vector<favicon_base::FaviconID> icon_ids(1u, icon_id); bool mapping_changed = @@ -1907,7 +1914,8 @@ } bool HistoryBackend::SetFaviconBitmaps(favicon_base::FaviconID icon_id, - const std::vector<SkBitmap>& bitmaps) { + const std::vector<SkBitmap>& bitmaps, + FaviconBitmapType type) { std::vector<FaviconBitmapIDSize> bitmap_id_sizes; thumbnail_db_->GetFaviconBitmapIDSizes(icon_id, &bitmap_id_sizes); @@ -1944,11 +1952,12 @@ } else { if (!favicon_bitmaps_changed && IsFaviconBitmapDataEqual(bitmap_id, match_it->first)) { - thumbnail_db_->SetFaviconBitmapLastUpdateTime(bitmap_id, - base::Time::Now()); + thumbnail_db_->SetFaviconBitmapLastUpdateTime( + bitmap_id, base::Time::Now() /* new last updated time */); } else { - thumbnail_db_->SetFaviconBitmap(bitmap_id, match_it->first, - base::Time::Now()); + thumbnail_db_->SetFaviconBitmap( + bitmap_id, match_it->first, + base::Time::Now() /* new last updated time */); favicon_bitmaps_changed = true; } to_add.erase(match_it); @@ -1956,8 +1965,10 @@ } for (size_t i = 0; i < to_add.size(); ++i) { - thumbnail_db_->AddFaviconBitmap(icon_id, to_add[i].first, base::Time::Now(), - to_add[i].second); + thumbnail_db_->AddFaviconBitmap( + icon_id, to_add[i].first, type, + base::Time::Now() /* new last updated / last requested time */, + to_add[i].second); favicon_bitmaps_changed = true; }
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index cae7870..85c5fb8 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -326,13 +326,15 @@ const GURL& icon_url, const std::vector<SkBitmap>& bitmaps); - bool SetLastResortFavicons(const GURL& page_url, - favicon_base::IconType icon_type, - const GURL& icon_url, - const std::vector<SkBitmap>& bitmaps); + bool SetOnDemandFavicons(const GURL& page_url, + favicon_base::IconType icon_type, + const GURL& icon_url, + const std::vector<SkBitmap>& bitmaps); void SetFaviconsOutOfDateForPage(const GURL& page_url); + void TouchOnDemandFavicon(const GURL& icon_url); + void SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage); @@ -528,11 +530,9 @@ FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconsReplaceBitmapData); FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetFaviconsSameFaviconURLForTwoPages); - FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetLastResortFaviconsForEmptyDB); - FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, - SetLastResortFaviconsForPageInDB); - FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, - SetLastResortFaviconsForIconInDB); + FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForEmptyDB); + FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForPageInDB); + FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, SetOnDemandFaviconsForIconInDB); FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, UpdateFaviconMappingsAndFetchNoChange); FRIEND_TEST_ALL_PREFIXES(HistoryBackendTest, MergeFaviconPageURLNotInDB); @@ -686,7 +686,7 @@ favicon_base::IconType icon_type, const GURL& icon_url, const std::vector<SkBitmap>& bitmaps, - bool bitmaps_are_expired); + FaviconBitmapType type); // Used by both UpdateFaviconMappingsAndFetch() and GetFavicon(). // If |page_url| is non-null and there is a favicon stored in the database @@ -699,16 +699,19 @@ const std::vector<int>& desired_sizes, std::vector<favicon_base::FaviconRawBitmapResult>* results); - // Set the favicon bitmaps for |icon_id|. + // Set the favicon bitmaps of |type| for |icon_id|. // For each entry in |bitmaps|, if a favicon bitmap already exists at the // entry's pixel size, replace the favicon bitmap's data with the entry's // bitmap data. Otherwise add a new favicon bitmap. // Any favicon bitmaps already mapped to |icon_id| whose pixel size does not // match the pixel size of one of |bitmaps| is deleted. + // For bitmap type FaviconBitmapType::ON_DEMAND, this is legal to call only + // for a newly created |icon_id| (that has no bitmaps yet). // Returns true if any of the bitmap data at |icon_id| is changed as a result // of calling this method. bool SetFaviconBitmaps(favicon_base::FaviconID icon_id, - const std::vector<SkBitmap>& bitmaps); + const std::vector<SkBitmap>& bitmaps, + FaviconBitmapType type); // Returns true if the bitmap data at |bitmap_id| equals |new_bitmap_data|. bool IsFaviconBitmapDataEqual(
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc index 63dfe4b..c92e97e 100644 --- a/components/history/core/browser/history_backend_unittest.cc +++ b/components/history/core/browser/history_backend_unittest.cc
@@ -593,18 +593,22 @@ std::vector<unsigned char> data; data.push_back('a'); - EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap(favicon1, - new base::RefCountedBytes(data), base::Time::Now(), kSmallSize)); + EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap( + favicon1, new base::RefCountedBytes(data), FaviconBitmapType::ON_VISIT, + base::Time::Now(), kSmallSize)); data[0] = 'b'; - EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap(favicon1, - new base::RefCountedBytes(data), base::Time::Now(), kLargeSize)); + EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap( + favicon1, new base::RefCountedBytes(data), FaviconBitmapType::ON_VISIT, + base::Time::Now(), kLargeSize)); data[0] = 'c'; - EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap(favicon2, - new base::RefCountedBytes(data), base::Time::Now(), kSmallSize)); + EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap( + favicon2, new base::RefCountedBytes(data), FaviconBitmapType::ON_VISIT, + base::Time::Now(), kSmallSize)); data[0] = 'd'; - EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap(favicon2, - new base::RefCountedBytes(data), base::Time::Now(), kLargeSize)); + EXPECT_TRUE(backend_->thumbnail_db_->AddFaviconBitmap( + favicon2, new base::RefCountedBytes(data), FaviconBitmapType::ON_VISIT, + base::Time::Now(), kLargeSize)); // First visit two URLs. URLRow row1(GURL("http://www.google.com/")); @@ -737,7 +741,7 @@ data.push_back('a'); favicon_base::FaviconID favicon = backend_->thumbnail_db_->AddFavicon( kFaviconURL, favicon_base::FAVICON, new base::RefCountedBytes(data), - base::Time::Now(), kSmallSize); + FaviconBitmapType::ON_VISIT, base::Time::Now(), kSmallSize); backend_->thumbnail_db_->AddIconMapping(row.url(), favicon); history_client_.AddBookmark(kPageURL); @@ -821,20 +825,14 @@ std::vector<unsigned char> data; data.push_back('1'); - favicon_base::FaviconID favicon1 = - backend_->thumbnail_db_->AddFavicon(favicon_url1, - favicon_base::FAVICON, - new base::RefCountedBytes(data), - base::Time::Now(), - gfx::Size()); + favicon_base::FaviconID favicon1 = backend_->thumbnail_db_->AddFavicon( + favicon_url1, favicon_base::FAVICON, new base::RefCountedBytes(data), + FaviconBitmapType::ON_VISIT, base::Time::Now(), gfx::Size()); data[0] = '2'; - favicon_base::FaviconID favicon2 = - backend_->thumbnail_db_->AddFavicon(favicon_url2, - favicon_base::FAVICON, - new base::RefCountedBytes(data), - base::Time::Now(), - gfx::Size()); + favicon_base::FaviconID favicon2 = backend_->thumbnail_db_->AddFavicon( + favicon_url2, favicon_base::FAVICON, new base::RefCountedBytes(data), + FaviconBitmapType::ON_VISIT, base::Time::Now(), gfx::Size()); // First visit two URLs. URLRow row1(GURL("http://www.google.com/")); @@ -1171,11 +1169,9 @@ std::vector<unsigned char> data; data.push_back('1'); favicon_base::FaviconID favicon1 = backend_->thumbnail_db_->AddFavicon( - favicon_url1, - favicon_base::FAVICON, - base::RefCountedBytes::TakeVector(&data), - base::Time::Now(), - gfx::Size()); + favicon_url1, favicon_base::FAVICON, + base::RefCountedBytes::TakeVector(&data), FaviconBitmapType::ON_VISIT, + base::Time::Now(), gfx::Size()); URLRow row1(GURL("http://www.google.com/")); row1.set_visit_count(1); row1.set_last_visit(base::Time::Now()); @@ -2076,18 +2072,18 @@ EXPECT_EQ(2u, favicon_bitmaps.size()); } -// Tests calling SetLastResortFavicons(). Neither |page_url| nor |icon_url| are +// Tests calling SetOnDemandFavicons(). Neither |page_url| nor |icon_url| are // known to the database. -TEST_F(HistoryBackendTest, SetLastResortFaviconsForEmptyDB) { +TEST_F(HistoryBackendTest, SetOnDemandFaviconsForEmptyDB) { GURL page_url("http://www.google.com"); GURL icon_url("http:/www.google.com/favicon.ico"); std::vector<SkBitmap> bitmaps; bitmaps.push_back(CreateBitmap(SK_ColorRED, kSmallEdgeSize)); - // Call SetLastResortFavicons() with a different icon URL and bitmap data. - EXPECT_TRUE(backend_->SetLastResortFavicons(page_url, favicon_base::FAVICON, - icon_url, bitmaps)); + // Call SetOnDemandFavicons() with a different icon URL and bitmap data. + EXPECT_TRUE(backend_->SetOnDemandFavicons(page_url, favicon_base::FAVICON, + icon_url, bitmaps)); favicon_base::FaviconID favicon_id = backend_->thumbnail_db_->GetFaviconIDForFaviconURL(icon_url, @@ -2102,9 +2098,9 @@ EXPECT_EQ(base::Time(), favicon_bitmap.last_updated); } -// Tests calling SetLastResortFavicons(). |page_url| is known to the database +// Tests calling SetOnDemandFavicons(). |page_url| is known to the database // but |icon_url| is not (the second should be irrelevant though). -TEST_F(HistoryBackendTest, SetLastResortFaviconsForPageInDB) { +TEST_F(HistoryBackendTest, SetOnDemandFaviconsForPageInDB) { GURL page_url("http://www.google.com"); GURL icon_url1("http:/www.google.com/favicon1.ico"); GURL icon_url2("http:/www.google.com/favicon2.ico"); @@ -2118,10 +2114,10 @@ favicon_base::FAVICON); ASSERT_NE(0, original_favicon_id); - // Call SetLastResortFavicons() with a different icon URL and bitmap data. + // Call SetOnDemandFavicons() with a different icon URL and bitmap data. bitmaps[0] = CreateBitmap(SK_ColorWHITE, kSmallEdgeSize); - EXPECT_FALSE(backend_->SetLastResortFavicons(page_url, favicon_base::FAVICON, - icon_url2, bitmaps)); + EXPECT_FALSE(backend_->SetOnDemandFavicons(page_url, favicon_base::FAVICON, + icon_url2, bitmaps)); EXPECT_EQ(0, backend_->thumbnail_db_->GetFaviconIDForFaviconURL( icon_url2, favicon_base::FAVICON)); @@ -2133,9 +2129,9 @@ EXPECT_NE(base::Time(), favicon_bitmap.last_updated); } -// Tests calling SetLastResortFavicons(). |page_url| is not known to the +// Tests calling SetOnDemandFavicons(). |page_url| is not known to the // database but |icon_url| is. -TEST_F(HistoryBackendTest, SetLastResortFaviconsForIconInDB) { +TEST_F(HistoryBackendTest, SetOnDemandFaviconsForIconInDB) { const GURL old_page_url("http://www.google.com/old"); const GURL page_url("http://www.google.com/"); const GURL icon_url("http://www.google.com/icon"); @@ -2149,10 +2145,10 @@ favicon_base::FAVICON); ASSERT_NE(0, original_favicon_id); - // Call SetLastResortFavicons() with a different bitmap. + // Call SetOnDemandFavicons() with a different bitmap. bitmaps[0] = CreateBitmap(SK_ColorWHITE, kSmallEdgeSize); - EXPECT_FALSE(backend_->SetLastResortFavicons(page_url, favicon_base::FAVICON, - icon_url, bitmaps)); + EXPECT_FALSE(backend_->SetOnDemandFavicons(page_url, favicon_base::FAVICON, + icon_url, bitmaps)); EXPECT_EQ(original_favicon_id, backend_->thumbnail_db_->GetFaviconIDForFaviconURL( @@ -3048,7 +3044,8 @@ base::RefCountedBytes::TakeVector(&data)); base::Time last_updated = base::Time::FromTimeT(0); favicon_base::FaviconID icon_id = backend_->thumbnail_db_->AddFavicon( - icon_url, favicon_base::FAVICON, bitmap_data, last_updated, kSmallSize); + icon_url, favicon_base::FAVICON, bitmap_data, FaviconBitmapType::ON_VISIT, + last_updated, kSmallSize); EXPECT_NE(0, icon_id); EXPECT_NE(0, backend_->thumbnail_db_->AddIconMapping(page_url, icon_id));
diff --git a/components/history/core/browser/history_service.cc b/components/history/core/browser/history_service.cc index a9a3326..60a142f 100644 --- a/components/history/core/browser/history_service.cc +++ b/components/history/core/browser/history_service.cc
@@ -625,12 +625,11 @@ page_url, icon_type, icon_url, bitmaps)); } -void HistoryService::SetLastResortFavicons( - const GURL& page_url, - favicon_base::IconType icon_type, - const GURL& icon_url, - const std::vector<SkBitmap>& bitmaps, - base::Callback<void(bool)> callback) { +void HistoryService::SetOnDemandFavicons(const GURL& page_url, + favicon_base::IconType icon_type, + const GURL& icon_url, + const std::vector<SkBitmap>& bitmaps, + base::Callback<void(bool)> callback) { DCHECK(backend_task_runner_) << "History service being called after cleanup"; DCHECK(thread_checker_.CalledOnValidThread()); if (history_client_ && !history_client_->CanAddURL(page_url)) @@ -638,7 +637,7 @@ PostTaskAndReplyWithResult( backend_task_runner_.get(), FROM_HERE, - base::Bind(&HistoryBackend::SetLastResortFavicons, history_backend_, + base::Bind(&HistoryBackend::SetOnDemandFavicons, history_backend_, page_url, icon_type, icon_url, bitmaps), callback); } @@ -651,6 +650,14 @@ history_backend_, page_url)); } +void HistoryService::TouchOnDemandFavicon(const GURL& icon_url) { + DCHECK(backend_task_runner_) << "History service being called after cleanup"; + DCHECK(thread_checker_.CalledOnValidThread()); + ScheduleTask(PRIORITY_NORMAL, + base::Bind(&HistoryBackend::TouchOnDemandFavicon, + history_backend_, icon_url)); +} + void HistoryService::SetImportedFavicons( const favicon_base::FaviconUsageDataList& favicon_usage) { DCHECK(backend_task_runner_) << "History service being called after cleanup";
diff --git a/components/history/core/browser/history_service.h b/components/history/core/browser/history_service.h index b1aedcd..425a043 100644 --- a/components/history/core/browser/history_service.h +++ b/components/history/core/browser/history_service.h
@@ -756,18 +756,37 @@ // 2) If |icon_url| is known to the database, |bitmaps| will be ignored (i.e. // the icon won't be overwritten) but the mappings from |page_url| to // |icon_url| will be stored (conditioned to point 1 above). - // 3) If |icon_url| is stored, it will be marked as expired. + // 3) If |icon_url| is stored, it will be marked as "on-demand". + // + // On-demand favicons are those that are fetched without visiting their page. + // For this reason, their life-time cannot be bound to the life-time of the + // corresponding visit in history. + // - These bitmaps are evicted from the database based on the last time they + // get requested. The last requested time is initially set to Now() and is + // further updated by calling TouchOnDemandFavicon(). + // - Furthermore, on-demand bitmaps are immediately marked as expired. Hence, + // they are always replaced by standard favicons whenever their page gets + // visited. // The callback will receive whether the write actually happened. - void SetLastResortFavicons(const GURL& page_url, - favicon_base::IconType icon_type, - const GURL& icon_url, - const std::vector<SkBitmap>& bitmaps, - base::Callback<void(bool)> callback); + void SetOnDemandFavicons(const GURL& page_url, + favicon_base::IconType icon_type, + const GURL& icon_url, + const std::vector<SkBitmap>& bitmaps, + base::Callback<void(bool)> callback); // Used by the FaviconService to mark the favicon for the page as being out // of date. void SetFaviconsOutOfDateForPage(const GURL& page_url); + // Mark that the on-demand favicon at |icon_url| was requested now. This + // postpones the automatic eviction of the favicon from the database. Not all + // calls end up in a write into the DB: + // - it is no-op if the bitmaps are not stored using SetOnDemandFavicons(); + // - the updates of the "last requested time" have limited frequency for each + // particular favicon (e.g. once per week). This limits the overhead of + // cache management for on-demand favicons. + void TouchOnDemandFavicon(const GURL& icon_url); + // Used by the FaviconService for importing many favicons for many pages at // once. The pages must exist, any favicon sets for unknown pages will be // discarded. Existing favicons will not be overwritten.
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index 4346823..17b97b4 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -506,6 +506,24 @@ gfx::Size pixel_size; }; +enum FaviconBitmapType { + // The bitmap gets downloaded while visiting its page. Their life-time is + // bound to the life-time of the corresponding visit in history. + // - These bitmaps are re-downloaded when visiting the page again and the + // last_updated timestamp is old enough. + ON_VISIT, + + // The bitmap gets downloaded because it is demanded by some Chrome UI (while + // not visiting its page). For this reason, their life-time cannot be bound to + // the life-time of the corresponding visit in history. + // - These bitmaps are evicted from the database based on the last time they + // were requested. + // - Furthermore, on-demand bitmaps are immediately marked as expired. Hence, + // they are always replaced by ON_VISIT favicons whenever their page gets + // visited. + ON_DEMAND +}; + // Defines a favicon bitmap stored in the history backend. struct FaviconBitmap { FaviconBitmap();
diff --git a/components/history/core/browser/thumbnail_database.cc b/components/history/core/browser/thumbnail_database.cc index 60445eb..c8b430f4 100644 --- a/components/history/core/browser/thumbnail_database.cc +++ b/components/history/core/browser/thumbnail_database.cc
@@ -64,13 +64,17 @@ // icon_id The ID of the favicon that the bitmap is associated to. // last_updated The time at which this favicon was inserted into the // table. This is used to determine if it needs to be -// redownloaded from the web. +// redownloaded from the web. Value 0 denotes that the bitmap +// has been explicitly expired. // image_data PNG encoded data of the favicon. // width Pixel width of |image_data|. // height Pixel height of |image_data|. -// last_requested The time at which this bitmap was last requested. This is -// used to determine the priority with which the bitmap -// should be retained on cleanup. +// last_requested The time at which this bitmap was last requested. This +// entry is non-zero iff the bitmap is of type ON_DEMAND. +// This info is used for clearing old ON_DEMAND bitmaps. +// (On-demand bitmaps cannot get cleared along with expired +// visits in history DB because there is no corresponding +// visit.) namespace { @@ -503,12 +507,16 @@ FaviconBitmapID ThumbnailDatabase::AddFaviconBitmap( favicon_base::FaviconID icon_id, const scoped_refptr<base::RefCountedMemory>& icon_data, + FaviconBitmapType type, base::Time time, const gfx::Size& pixel_size) { DCHECK(icon_id); - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "INSERT INTO favicon_bitmaps (icon_id, image_data, last_updated, width, " - "height) VALUES (?, ?, ?, ?, ?)")); + + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + "INSERT INTO favicon_bitmaps (icon_id, image_data, last_updated, " + "last_requested, width, height) VALUES (?, ?, ?, ?, ?, ?)")); + statement.BindInt64(0, icon_id); if (icon_data.get() && icon_data->size()) { statement.BindBlob(1, icon_data->front(), @@ -516,9 +524,19 @@ } else { statement.BindNull(1); } - statement.BindInt64(2, time.ToInternalValue()); - statement.BindInt(3, pixel_size.width()); - statement.BindInt(4, pixel_size.height()); + + // On-visit bitmaps: + // - keep track of last_updated: last write time is used for expiration; + // - always have last_requested==0: no need to keep track of last read time. + statement.BindInt64(2, type == ON_VISIT ? time.ToInternalValue() : 0); + // On-demand bitmaps: + // - always have last_updated==0: last write time is not stored as they are + // always expired and thus ready to be replaced by ON_VISIT icons; + // - keep track of last_requested: last read time is used for cache eviction. + statement.BindInt64(3, type == ON_DEMAND ? time.ToInternalValue() : 0); + + statement.BindInt(4, pixel_size.width()); + statement.BindInt(5, pixel_size.height()); if (!statement.Run()) return 0; @@ -530,8 +548,13 @@ scoped_refptr<base::RefCountedMemory> bitmap_data, base::Time time) { DCHECK(bitmap_id); - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "UPDATE favicon_bitmaps SET image_data=?, last_updated=? WHERE id=?")); + // By updating last_updated timestamp, we assume the icon is of type ON_VISIT. + // If it is ON_DEMAND, reset last_requested to 0 and thus silently change the + // type to ON_VISIT. + sql::Statement statement( + db_.GetCachedStatement(SQL_FROM_HERE, + "UPDATE favicon_bitmaps SET image_data=?, " + "last_updated=?, last_requested=? WHERE id=?")); if (bitmap_data.get() && bitmap_data->size()) { statement.BindBlob(0, bitmap_data->front(), static_cast<int>(bitmap_data->size())); @@ -539,7 +562,8 @@ statement.BindNull(0); } statement.BindInt64(1, time.ToInternalValue()); - statement.BindInt64(2, bitmap_id); + statement.BindInt64(2, 0); + statement.BindInt64(3, bitmap_id); return statement.Run(); } @@ -548,22 +572,47 @@ FaviconBitmapID bitmap_id, base::Time time) { DCHECK(bitmap_id); - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "UPDATE favicon_bitmaps SET last_updated=? WHERE id=?")); + // By updating last_updated timestamp, we assume the icon is of type ON_VISIT. + // If it is ON_DEMAND, reset last_requested to 0 and thus silently change the + // type to ON_VISIT. + sql::Statement statement( + db_.GetCachedStatement(SQL_FROM_HERE, + "UPDATE favicon_bitmaps SET last_updated=?, " + "last_requested=? WHERE id=?")); statement.BindInt64(0, time.ToInternalValue()); - statement.BindInt64(1, bitmap_id); + statement.BindInt64(1, 0); + statement.BindInt64(2, bitmap_id); return statement.Run(); } -bool ThumbnailDatabase::SetFaviconBitmapLastRequestedTime( - FaviconBitmapID bitmap_id, - base::Time time) { - DCHECK(bitmap_id); - sql::Statement statement(db_.GetCachedStatement(SQL_FROM_HERE, - "UPDATE favicon_bitmaps SET last_requested=? WHERE id=?")); - statement.BindInt64(0, time.ToInternalValue()); - statement.BindInt64(1, bitmap_id); - return statement.Run(); +bool ThumbnailDatabase::TouchOnDemandFavicon(const GURL& icon_url, + base::Time time) { + // Look up the icon ids for the url. + sql::Statement id_statement(db_.GetCachedStatement( + SQL_FROM_HERE, "SELECT id FROM favicons WHERE url=?")); + id_statement.BindString(0, URLDatabase::GURLToDatabaseURL(icon_url)); + + base::Time max_time = + time - base::TimeDelta::FromDays(kFaviconUpdateLastRequestedAfterDays); + + while (id_statement.Step()) { + favicon_base::FaviconID icon_id = id_statement.ColumnInt64(0); + + // Update the time only for ON_DEMAND bitmaps (i.e. with last_requested > + // 0). For performance reasons, update the time only if the currently stored + // time is old enough (UPDATEs where the WHERE condition does not match any + // entries are way faster than UPDATEs that really change some data). + sql::Statement statement(db_.GetCachedStatement( + SQL_FROM_HERE, + "UPDATE favicon_bitmaps SET last_requested=? WHERE icon_id=? AND " + "last_requested>0 AND last_requested<=?")); + statement.BindInt64(0, time.ToInternalValue()); + statement.BindInt64(1, icon_id); + statement.BindInt64(2, max_time.ToInternalValue()); + if (!statement.Run()) + return false; + } + return true; } bool ThumbnailDatabase::DeleteFaviconBitmap(FaviconBitmapID bitmap_id) { @@ -634,10 +683,11 @@ const GURL& icon_url, favicon_base::IconType icon_type, const scoped_refptr<base::RefCountedMemory>& icon_data, + FaviconBitmapType type, base::Time time, const gfx::Size& pixel_size) { favicon_base::FaviconID icon_id = AddFavicon(icon_url, icon_type); - if (!icon_id || !AddFaviconBitmap(icon_id, icon_data, time, pixel_size)) + if (!icon_id || !AddFaviconBitmap(icon_id, icon_data, type, time, pixel_size)) return 0; return icon_id;
diff --git a/components/history/core/browser/thumbnail_database.h b/components/history/core/browser/thumbnail_database.h index ec21369d..697faf3 100644 --- a/components/history/core/browser/thumbnail_database.h +++ b/components/history/core/browser/thumbnail_database.h
@@ -26,6 +26,10 @@ class HistoryBackendClient; +// The minimum number of days after which last_requested field gets updated. +// All earlier updates are ignored. +static const int kFaviconUpdateLastRequestedAfterDays = 14; + // This database interface is owned by the history backend and runs on the // history thread. It is a totally separate component from history partially // because we may want to move it to its own thread in the future. The @@ -87,37 +91,36 @@ scoped_refptr<base::RefCountedMemory>* png_icon_data, gfx::Size* pixel_size); - // Adds a bitmap component at |pixel_size| for the favicon with |icon_id|. - // Only favicons representing a .ico file should have multiple favicon bitmaps - // per favicon. + // Adds a bitmap component of |type| at |pixel_size| for the favicon with + // |icon_id|. Only favicons representing a .ico file should have multiple + // favicon bitmaps per favicon. // |icon_data| is the png encoded data. - // The |time| indicates the access time, and is used to detect when the - // favicon should be refreshed. + // The |type| indicates how the lifetime of this icon should be managed. + // The |time| is used for lifetime management of the bitmap (should be Now()). // |pixel_size| is the pixel dimensions of |icon_data|. // Returns the id of the added bitmap or 0 if unsuccessful. FaviconBitmapID AddFaviconBitmap( favicon_base::FaviconID icon_id, const scoped_refptr<base::RefCountedMemory>& icon_data, + FaviconBitmapType type, base::Time time, const gfx::Size& pixel_size); // Sets the bitmap data and the last updated time for the favicon bitmap at - // |bitmap_id|. + // |bitmap_id|. Should not be called for bitmaps of type ON_DEMAND as they + // should never get updated (the call silently changes the type to ON_VISIT). // Returns true if successful. bool SetFaviconBitmap(FaviconBitmapID bitmap_id, scoped_refptr<base::RefCountedMemory> bitmap_data, base::Time time); - // Sets the last updated time for the favicon bitmap at |bitmap_id|. - // Returns true if successful. + // Sets the last_updated time for the favicon bitmap at |bitmap_id|. Should + // not be called for bitmaps of type ON_DEMAND as last_updated time is only + // tracked for ON_VISIT bitmaps (the call silently changes the type to + // ON_VISIT). Returns true if successful. bool SetFaviconBitmapLastUpdateTime(FaviconBitmapID bitmap_id, base::Time time); - // Sets the last requested time for the favicon bitmap at |bitmap_id|. - // Returns true if successful. - bool SetFaviconBitmapLastRequestedTime(FaviconBitmapID bitmap_id, - base::Time time); - // Deletes the favicon bitmap with |bitmap_id|. // Returns true if successful. bool DeleteFaviconBitmap(FaviconBitmapID bitmap_id); @@ -128,6 +131,16 @@ // of the bitmaps for |icon_id| to be out of date. bool SetFaviconOutOfDate(favicon_base::FaviconID icon_id); + // Mark all bitmaps of type ON_DEMAND at |icon_url| as requested at |time|. + // This postpones their automatic eviction from the database. Not all calls + // end up in a write into the DB: + // - it is no-op if the bitmaps are not of type ON_DEMAND; + // - the updates of the "last requested time" have limited frequency for each + // particular bitmap (e.g. once per week). This limits the overhead of + // cache management for on-demand favicons. + // Returns true if successful. + bool TouchOnDemandFavicon(const GURL& icon_url, base::Time time); + // Returns the id of the entry in the favicon database with the specified url // and icon type. // Returns 0 if no entry exists for the specified url. @@ -146,11 +159,12 @@ favicon_base::IconType icon_type); // Adds a favicon with a single bitmap. This call is equivalent to calling - // AddFavicon and AddFaviconBitmap. + // AddFavicon and AddFaviconBitmap of type |type|. favicon_base::FaviconID AddFavicon( const GURL& icon_url, favicon_base::IconType icon_type, const scoped_refptr<base::RefCountedMemory>& icon_data, + FaviconBitmapType type, base::Time time, const gfx::Size& pixel_size);
diff --git a/components/history/core/browser/thumbnail_database_unittest.cc b/components/history/core/browser/thumbnail_database_unittest.cc index 0ece892..4dbd0c6 100644 --- a/components/history/core/browser/thumbnail_database_unittest.cc +++ b/components/history/core/browser/thumbnail_database_unittest.cc
@@ -85,7 +85,8 @@ scoped_refptr<base::RefCountedStaticMemory> data( new base::RefCountedStaticMemory(kBlob1, sizeof(kBlob1))); favicon_base::FaviconID favicon_id = - db->AddFavicon(icon_url, icon_type, data, base::Time::Now(), gfx::Size()); + db->AddFavicon(icon_url, icon_type, data, FaviconBitmapType::ON_VISIT, + base::Time::Now(), gfx::Size()); db->AddIconMapping(page_url, favicon_id); } @@ -213,7 +214,8 @@ GURL url("http://google.com"); base::Time time = base::Time::Now(); favicon_base::FaviconID id = - db.AddFavicon(url, favicon_base::TOUCH_ICON, favicon, time, gfx::Size()); + db.AddFavicon(url, favicon_base::TOUCH_ICON, favicon, + FaviconBitmapType::ON_VISIT, time, gfx::Size()); EXPECT_NE(0, id); EXPECT_NE(0, db.AddIconMapping(url, id)); @@ -224,37 +226,145 @@ EXPECT_EQ(id, icon_mappings.front().icon_id); } -TEST_F(ThumbnailDatabaseTest, LastRequestedTime) { - ThumbnailDatabase db(NULL); +TEST_F(ThumbnailDatabaseTest, + AddOnDemandFaviconBitmapCreatesCorrectTimestamps) { + ThumbnailDatabase db(nullptr); ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); db.BeginTransaction(); + base::Time add_time; + ASSERT_TRUE( + base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &add_time)); std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); GURL url("http://google.com"); - base::Time now = base::Time::Now(); - favicon_base::FaviconID id = - db.AddFavicon(url, favicon_base::TOUCH_ICON, favicon, now, gfx::Size()); - ASSERT_NE(0, id); + favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); + ASSERT_NE(0, icon); + FaviconBitmapID bitmap = db.AddFaviconBitmap( + icon, favicon, FaviconBitmapType::ON_DEMAND, add_time, gfx::Size()); + ASSERT_NE(0, bitmap); - // Fetching the last requested time of a non-existent bitmap should fail. - base::Time last_requested = base::Time::UnixEpoch(); - EXPECT_FALSE(db.GetFaviconBitmap(id + 1, NULL, &last_requested, NULL, NULL)); - EXPECT_EQ(last_requested, base::Time::UnixEpoch()); // Remains unchanged. + base::Time last_updated; + base::Time last_requested; + ASSERT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, + nullptr, nullptr)); + EXPECT_EQ(base::Time(), last_updated); + EXPECT_EQ(add_time, last_requested); +} - // Fetching the last requested time of a bitmap that has no last request - // should return a null timestamp. - last_requested = base::Time::UnixEpoch(); - EXPECT_TRUE(db.GetFaviconBitmap(id, NULL, &last_requested, NULL, NULL)); - EXPECT_TRUE(last_requested.is_null()); +TEST_F(ThumbnailDatabaseTest, AddFaviconBitmapCreatesCorrectTimestamps) { + ThumbnailDatabase db(nullptr); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); + db.BeginTransaction(); - // Setting the last requested time of an existing bitmap should succeed, and - // the set time should be returned by the corresponding "Get". - last_requested = base::Time::UnixEpoch(); - EXPECT_TRUE(db.SetFaviconBitmapLastRequestedTime(id, now)); - EXPECT_TRUE(db.GetFaviconBitmap(id, NULL, &last_requested, NULL, NULL)); - EXPECT_EQ(last_requested, now); + base::Time add_time; + ASSERT_TRUE( + base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &add_time)); + std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); + scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); + + GURL url("http://google.com"); + favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); + ASSERT_NE(0, icon); + FaviconBitmapID bitmap = db.AddFaviconBitmap( + icon, favicon, FaviconBitmapType::ON_VISIT, add_time, gfx::Size()); + ASSERT_NE(0, bitmap); + + base::Time last_updated; + base::Time last_requested; + ASSERT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, + nullptr, nullptr)); + EXPECT_EQ(add_time, last_updated); + EXPECT_EQ(base::Time(), last_requested); +} + +TEST_F(ThumbnailDatabaseTest, TouchUpdatesOnDemandFavicons) { + ThumbnailDatabase db(nullptr); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); + db.BeginTransaction(); + + base::Time start; + ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); + std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); + scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); + + // Create an on-demand favicon. + GURL url("http://google.com"); + favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); + ASSERT_NE(0, icon); + FaviconBitmapID bitmap = db.AddFaviconBitmap( + icon, favicon, FaviconBitmapType::ON_DEMAND, start, gfx::Size()); + ASSERT_NE(0, bitmap); + + base::Time end = + start + base::TimeDelta::FromDays(kFaviconUpdateLastRequestedAfterDays); + EXPECT_TRUE(db.TouchOnDemandFavicon(url, end)); + + base::Time last_updated; + base::Time last_requested; + EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, + nullptr, nullptr)); + // Does not mess with the last_updated field. + EXPECT_EQ(base::Time(), last_updated); + EXPECT_EQ(end, last_requested); // Updates the last_requested field. +} + +TEST_F(ThumbnailDatabaseTest, TouchUpdatesOnlyInfrequently) { + ThumbnailDatabase db(nullptr); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); + db.BeginTransaction(); + + base::Time start; + ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); + std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); + scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); + + // Create an on-demand favicon. + GURL url("http://google.com"); + favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); + ASSERT_NE(0, icon); + FaviconBitmapID bitmap = db.AddFaviconBitmap( + icon, favicon, FaviconBitmapType::ON_DEMAND, start, gfx::Size()); + ASSERT_NE(0, bitmap); + + base::Time end = start + base::TimeDelta::FromMinutes(1); + EXPECT_TRUE(db.TouchOnDemandFavicon(url, end)); + + base::Time last_requested; + EXPECT_TRUE( + db.GetFaviconBitmap(bitmap, nullptr, &last_requested, nullptr, nullptr)); + EXPECT_EQ(start, last_requested); // No update. +} + +TEST_F(ThumbnailDatabaseTest, TouchDoesNotUpdateStandardFavicons) { + ThumbnailDatabase db(nullptr); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); + db.BeginTransaction(); + + base::Time start; + ASSERT_TRUE(base::Time::FromUTCExploded({2017, 5, 0, 1, 0, 0, 0, 0}, &start)); + std::vector<unsigned char> data(kBlob1, kBlob1 + sizeof(kBlob1)); + scoped_refptr<base::RefCountedBytes> favicon(new base::RefCountedBytes(data)); + + // Create a standard favicon. + GURL url("http://google.com"); + favicon_base::FaviconID icon = db.AddFavicon(url, favicon_base::FAVICON); + EXPECT_NE(0, icon); + FaviconBitmapID bitmap = db.AddFaviconBitmap( + icon, favicon, FaviconBitmapType::ON_VISIT, start, gfx::Size()); + EXPECT_NE(0, bitmap); + + base::Time end = + start + base::TimeDelta::FromDays(kFaviconUpdateLastRequestedAfterDays); + db.TouchOnDemandFavicon(url, end); + + base::Time last_updated; + base::Time last_requested; + EXPECT_TRUE(db.GetFaviconBitmap(bitmap, &last_updated, &last_requested, + nullptr, nullptr)); + EXPECT_EQ(start, last_updated); // Does not mess with last_updated. + EXPECT_EQ(base::Time(), last_requested); // No update. } TEST_F(ThumbnailDatabaseTest, DeleteIconMappings) { @@ -268,7 +378,8 @@ GURL url("http://google.com"); favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::TOUCH_ICON); base::Time time = base::Time::Now(); - db.AddFaviconBitmap(id, favicon, time, gfx::Size()); + db.AddFaviconBitmap(id, favicon, FaviconBitmapType::ON_VISIT, time, + gfx::Size()); EXPECT_LT(0, db.AddIconMapping(url, id)); favicon_base::FaviconID id2 = db.AddFavicon(url, favicon_base::FAVICON); @@ -299,13 +410,16 @@ favicon_base::FaviconID id1 = db.AddFavicon(url, favicon_base::TOUCH_ICON); base::Time time = base::Time::Now(); - db.AddFaviconBitmap(id1, favicon, time, kSmallSize); - db.AddFaviconBitmap(id1, favicon, time, kLargeSize); + db.AddFaviconBitmap(id1, favicon, FaviconBitmapType::ON_VISIT, time, + kSmallSize); + db.AddFaviconBitmap(id1, favicon, FaviconBitmapType::ON_VISIT, time, + kLargeSize); EXPECT_LT(0, db.AddIconMapping(url, id1)); favicon_base::FaviconID id2 = db.AddFavicon(url, favicon_base::FAVICON); EXPECT_NE(id1, id2); - db.AddFaviconBitmap(id2, favicon, time, kSmallSize); + db.AddFaviconBitmap(id2, favicon, FaviconBitmapType::ON_VISIT, time, + kSmallSize); EXPECT_LT(0, db.AddIconMapping(url, id2)); std::vector<IconMapping> icon_mappings; @@ -341,19 +455,22 @@ favicon_base::FaviconID kept_id1 = db.AddFavicon(kIconUrl1, favicon_base::FAVICON); - db.AddFaviconBitmap(kept_id1, favicon1, base::Time::Now(), kLargeSize); + db.AddFaviconBitmap(kept_id1, favicon1, FaviconBitmapType::ON_VISIT, + base::Time::Now(), kLargeSize); db.AddIconMapping(kPageUrl1, kept_id1); db.AddIconMapping(kPageUrl3, kept_id1); db.AddIconMapping(kPageUrl4, kept_id1); favicon_base::FaviconID unkept_id = db.AddFavicon(kIconUrl2, favicon_base::FAVICON); - db.AddFaviconBitmap(unkept_id, favicon1, base::Time::Now(), kLargeSize); + db.AddFaviconBitmap(unkept_id, favicon1, FaviconBitmapType::ON_VISIT, + base::Time::Now(), kLargeSize); db.AddIconMapping(kPageUrl2, unkept_id); favicon_base::FaviconID kept_id2 = db.AddFavicon(kIconUrl5, favicon_base::FAVICON); - db.AddFaviconBitmap(kept_id2, favicon2, base::Time::Now(), kLargeSize); + db.AddFaviconBitmap(kept_id2, favicon2, FaviconBitmapType::ON_VISIT, + base::Time::Now(), kLargeSize); db.AddIconMapping(kPageUrl5, kept_id2); // RetainDataForPageUrls() uses schema manipulations for efficiency. @@ -406,8 +523,8 @@ scoped_refptr<base::RefCountedStaticMemory> favicon1( new base::RefCountedStaticMemory(kBlob1, sizeof(kBlob1))); favicon_base::FaviconID kept_id = db.AddFavicon( - kIconUrl1, favicon_base::FAVICON, favicon1, base::Time::Now(), - gfx::Size()); + kIconUrl1, favicon_base::FAVICON, favicon1, FaviconBitmapType::ON_VISIT, + base::Time::Now(), gfx::Size()); db.AddIconMapping(kPageUrl1, kept_id); EXPECT_TRUE(db.RetainDataForPageUrls(std::vector<GURL>(1u, kPageUrl1))); @@ -439,8 +556,10 @@ GURL url("http://google.com"); favicon_base::FaviconID id = db.AddFavicon(url, favicon_base::FAVICON); base::Time last_updated = base::Time::Now(); - db.AddFaviconBitmap(id, favicon1, last_updated, kSmallSize); - db.AddFaviconBitmap(id, favicon2, last_updated, kLargeSize); + db.AddFaviconBitmap(id, favicon1, FaviconBitmapType::ON_VISIT, last_updated, + kSmallSize); + db.AddFaviconBitmap(id, favicon2, FaviconBitmapType::ON_VISIT, last_updated, + kLargeSize); EXPECT_TRUE(db.GetFaviconBitmaps(id, NULL)); @@ -461,8 +580,9 @@ GURL icon_url("http://google.com/favicon.ico"); base::Time time = base::Time::Now(); - favicon_base::FaviconID id = db.AddFavicon( - icon_url, favicon_base::FAVICON, favicon, time, gfx::Size()); + favicon_base::FaviconID id = + db.AddFavicon(icon_url, favicon_base::FAVICON, favicon, + FaviconBitmapType::ON_VISIT, time, gfx::Size()); EXPECT_NE(0, db.AddIconMapping(page_url, id)); std::vector<IconMapping> icon_mappings; EXPECT_TRUE(db.GetIconMappingsForPageURL(page_url, &icon_mappings)); @@ -477,8 +597,9 @@ scoped_refptr<base::RefCountedBytes> favicon2 = new base::RefCountedBytes(data); - favicon_base::FaviconID id2 = db.AddFavicon( - icon_url, favicon_base::TOUCH_ICON, favicon2, time, gfx::Size()); + favicon_base::FaviconID id2 = + db.AddFavicon(icon_url, favicon_base::TOUCH_ICON, favicon2, + FaviconBitmapType::ON_VISIT, time, gfx::Size()); EXPECT_NE(0, db.AddIconMapping(page_url, id2)); icon_mappings.clear(); @@ -494,11 +615,8 @@ new base::RefCountedBytes(data2); favicon_base::FaviconID id3 = - db.AddFavicon(icon_url, - favicon_base::TOUCH_PRECOMPOSED_ICON, - favicon3, - time, - gfx::Size()); + db.AddFavicon(icon_url, favicon_base::TOUCH_PRECOMPOSED_ICON, favicon3, + FaviconBitmapType::ON_VISIT, time, gfx::Size()); EXPECT_NE(0, db.AddIconMapping(page_url, id3)); icon_mappings.clear(); @@ -548,31 +666,23 @@ // Add a favicon which will have icon_mappings base::Time time = base::Time::Now(); - favicon_base::FaviconID id1 = db.AddFavicon(GURL("http://google.com"), - favicon_base::FAVICON, - favicon, - time, - gfx::Size()); + favicon_base::FaviconID id1 = + db.AddFavicon(GURL("http://google.com"), favicon_base::FAVICON, favicon, + FaviconBitmapType::ON_VISIT, time, gfx::Size()); EXPECT_NE(id1, 0); // Add another type of favicon time = base::Time::Now(); - favicon_base::FaviconID id2 = - db.AddFavicon(GURL("http://www.google.com/icon"), - favicon_base::TOUCH_ICON, - favicon, - time, - gfx::Size()); + favicon_base::FaviconID id2 = db.AddFavicon( + GURL("http://www.google.com/icon"), favicon_base::TOUCH_ICON, favicon, + FaviconBitmapType::ON_VISIT, time, gfx::Size()); EXPECT_NE(id2, 0); // Add 3rd favicon time = base::Time::Now(); - favicon_base::FaviconID id3 = - db.AddFavicon(GURL("http://www.google.com/icon"), - favicon_base::TOUCH_ICON, - favicon, - time, - gfx::Size()); + favicon_base::FaviconID id3 = db.AddFavicon( + GURL("http://www.google.com/icon"), favicon_base::TOUCH_ICON, favicon, + FaviconBitmapType::ON_VISIT, time, gfx::Size()); EXPECT_NE(id3, 0); // Add 2 icon mapping
diff --git a/components/location/android/java/src/org/chromium/components/location/LocationUtils.java b/components/location/android/java/src/org/chromium/components/location/LocationUtils.java index c0de175..d9228d7 100644 --- a/components/location/android/java/src/org/chromium/components/location/LocationUtils.java +++ b/components/location/android/java/src/org/chromium/components/location/LocationUtils.java
@@ -103,10 +103,13 @@ * * <p>The callback is guaranteed to be called unless the user never replies to the prompt * dialog, which in practice happens very infrequently since the dialog is modal. + * + * TODO(crbug/730711): Add back @LocationSettingsDialogOutcome to the callback when type + * annotations are allowed in Java 8. */ public void promptToEnableSystemLocationSetting( @LocationSettingsDialogContext int promptContext, WindowAndroid window, - @LocationSettingsDialogOutcome Callback<Integer> callback) { + Callback<Integer> callback) { callback.onResult(LocationSettingsDialogOutcome.NO_PROMPT); }
diff --git a/components/nacl/browser/nacl_browser.cc b/components/nacl/browser/nacl_browser.cc index 7d25812..ccafb43 100644 --- a/components/nacl/browser/nacl_browser.cc +++ b/components/nacl/browser/nacl_browser.cc
@@ -280,11 +280,11 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (IsOk() && irt_state_ == NaClResourceUninitialized) { irt_state_ = NaClResourceRequested; - // TODO(ncbray) use blocking pool. + auto task_runner = base::CreateTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BACKGROUND, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); std::unique_ptr<base::FileProxy> file_proxy( - new base::FileProxy(content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::FILE) - .get())); + new base::FileProxy(task_runner.get())); base::FileProxy* proxy = file_proxy.get(); if (!proxy->CreateOrOpen( irt_filepath_, base::File::FLAG_OPEN | base::File::FLAG_READ,
diff --git a/components/omnibox/browser/autocomplete_classifier.cc b/components/omnibox/browser/autocomplete_classifier.cc index b086d83..2386539 100644 --- a/components/omnibox/browser/autocomplete_classifier.cc +++ b/components/omnibox/browser/autocomplete_classifier.cc
@@ -44,8 +44,7 @@ AutocompleteProvider::TYPE_KEYWORD | #endif #if !defined(OS_IOS) - // "Builtin", "Shortcuts" and "Zero Suggest" are not supported on iOS. - AutocompleteProvider::TYPE_BUILTIN | + // "Shortcuts" and "Zero Suggest" are not supported on iOS. AutocompleteProvider::TYPE_SHORTCUTS | AutocompleteProvider::TYPE_ZERO_SUGGEST | #endif @@ -53,6 +52,7 @@ ? AutocompleteProvider::TYPE_CLIPBOARD_URL : 0) | AutocompleteProvider::TYPE_BOOKMARK | + AutocompleteProvider::TYPE_BUILTIN | AutocompleteProvider::TYPE_HISTORY_QUICK | AutocompleteProvider::TYPE_HISTORY_URL | AutocompleteProvider::TYPE_SEARCH;
diff --git a/components/pairing/bluetooth_host_pairing_controller.cc b/components/pairing/bluetooth_host_pairing_controller.cc index 969efa5..6dfe60a 100644 --- a/components/pairing/bluetooth_host_pairing_controller.cc +++ b/components/pairing/bluetooth_host_pairing_controller.cc
@@ -4,12 +4,15 @@ #include "components/pairing/bluetooth_host_pairing_controller.h" +#include <utility> + #include "base/bind.h" #include "base/hash.h" #include "base/location.h" #include "base/logging.h" -#include "base/single_thread_task_runner.h" +#include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" +#include "base/task_runner.h" #include "base/task_runner_util.h" #include "chromeos/system/devicetype.h" #include "components/pairing/bluetooth_pairing_constants.h" @@ -86,14 +89,9 @@ } // namespace BluetoothHostPairingController::BluetoothHostPairingController( - const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) - : current_stage_(STAGE_NONE), - connectivity_status_(CONNECTIVITY_UNTESTED), - update_status_(UPDATE_STATUS_UNKNOWN), - enrollment_status_(ENROLLMENT_STATUS_UNKNOWN), - proto_decoder_(new ProtoDecoder(this)), - file_task_runner_(file_task_runner), - ptr_factory_(this) {} + scoped_refptr<base::TaskRunner> input_service_task_runner) + : proto_decoder_(base::MakeUnique<ProtoDecoder>(this)), + input_service_task_runner_(std::move(input_service_task_runner)) {} BluetoothHostPairingController::~BluetoothHostPairingController() { Reset(); @@ -190,7 +188,7 @@ void BluetoothHostPairingController::OnGetAdapter( scoped_refptr<device::BluetoothAdapter> adapter) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!adapter_.get()); adapter_ = adapter; @@ -203,7 +201,7 @@ } void BluetoothHostPairingController::SetPowered() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (adapter_->IsPowered()) { was_powered_ = true; OnSetPowered(); @@ -218,7 +216,7 @@ } void BluetoothHostPairingController::OnSetPowered() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); adapter_->AddPairingDelegate( this, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH); @@ -235,7 +233,7 @@ void BluetoothHostPairingController::OnCreateService( scoped_refptr<device::BluetoothSocket> socket) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); service_socket_ = socket; service_socket_->Accept( @@ -257,7 +255,7 @@ scoped_refptr<device::BluetoothSocket> socket) { controller_device_address_ = device->GetAddress(); - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); adapter_->SetDiscoverable( false, base::Bind(&BluetoothHostPairingController::OnSetDiscoverable, @@ -277,7 +275,7 @@ } void BluetoothHostPairingController::OnSetDiscoverable(bool change_stage) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (change_stage) { DCHECK_EQ(current_stage_, STAGE_NONE); ChangeStage(STAGE_WAITING_FOR_CONTROLLER); @@ -288,7 +286,7 @@ void BluetoothHostPairingController::OnReceiveComplete( int bytes, scoped_refptr<net::IOBuffer> io_buffer) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); proto_decoder_->DecodeIOBuffer(bytes, io_buffer); if (controller_socket_.get()) { @@ -372,7 +370,7 @@ } base::PostTaskAndReplyWithResult( - file_task_runner_.get(), FROM_HERE, base::Bind(&GetDevices), + input_service_task_runner_.get(), FROM_HERE, base::Bind(&GetDevices), base::Bind(&BluetoothHostPairingController::PowerOffAdapterIfApplicable, ptr_factory_.GetWeakPtr())); } @@ -409,7 +407,7 @@ void BluetoothHostPairingController::OnPairDevicesMessage( const pairing_api::PairDevices& message) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); enrollment_domain_ = message.parameters().enrolling_domain(); ChangeStage(STAGE_ENROLLING); for (Observer& observer : observers_) @@ -418,7 +416,7 @@ void BluetoothHostPairingController::OnCompleteSetupMessage( const pairing_api::CompleteSetup& message) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (current_stage_ != STAGE_ENROLLMENT_SUCCESS) { ChangeStage(STAGE_ENROLLMENT_ERROR); } else { @@ -435,14 +433,14 @@ void BluetoothHostPairingController::OnRebootMessage( const pairing_api::Reboot& message) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); for (Observer& observer : observers_) observer.RebootHostRequested(); } void BluetoothHostPairingController::OnAddNetworkMessage( const pairing_api::AddNetwork& message) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); for (Observer& observer : observers_) observer.AddNetworkRequested(message.parameters().onc_spec()); } @@ -518,7 +516,7 @@ void BluetoothHostPairingController::OnEnrollmentStatusChanged( EnrollmentStatus enrollment_status) { DCHECK_EQ(current_stage_, STAGE_ENROLLING); - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); enrollment_status_ = enrollment_status; if (enrollment_status == ENROLLMENT_STATUS_SUCCESS) {
diff --git a/components/pairing/bluetooth_host_pairing_controller.h b/components/pairing/bluetooth_host_pairing_controller.h index 8eabce0..5c01dcf 100644 --- a/components/pairing/bluetooth_host_pairing_controller.h +++ b/components/pairing/bluetooth_host_pairing_controller.h
@@ -22,7 +22,7 @@ #include "device/hid/input_service_linux.h" namespace base { -class SingleThreadTaskRunner; +class TaskRunner; } namespace device { @@ -62,7 +62,7 @@ }; explicit BluetoothHostPairingController( - const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner); + scoped_refptr<base::TaskRunner> input_service_task_runner); ~BluetoothHostPairingController() override; // These functions should be only used in tests. @@ -141,12 +141,12 @@ uint32_t passkey) override; void AuthorizePairing(device::BluetoothDevice* device) override; - Stage current_stage_; + Stage current_stage_ = STAGE_NONE; std::string confirmation_code_; std::string enrollment_domain_; - Connectivity connectivity_status_; - UpdateStatus update_status_; - EnrollmentStatus enrollment_status_; + Connectivity connectivity_status_ = CONNECTIVITY_UNTESTED; + UpdateStatus update_status_ = UPDATE_STATUS_UNKNOWN; + EnrollmentStatus enrollment_status_ = ENROLLMENT_STATUS_UNKNOWN; std::string permanent_id_; std::string controller_device_address_; bool was_powered_ = false; @@ -168,10 +168,10 @@ std::unique_ptr<ProtoDecoder> proto_decoder_; TestDelegate* delegate_ = nullptr; - scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; - base::ThreadChecker thread_checker_; + scoped_refptr<base::TaskRunner> input_service_task_runner_; + THREAD_CHECKER(thread_checker_); base::ObserverList<Observer> observers_; - base::WeakPtrFactory<BluetoothHostPairingController> ptr_factory_; + base::WeakPtrFactory<BluetoothHostPairingController> ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(BluetoothHostPairingController); };
diff --git a/components/pairing/shark_connection_listener.cc b/components/pairing/shark_connection_listener.cc index 85c5541..e5eb97d 100644 --- a/components/pairing/shark_connection_listener.cc +++ b/components/pairing/shark_connection_listener.cc
@@ -7,16 +7,18 @@ #include <utility> #include "base/logging.h" +#include "base/task_runner.h" #include "base/threading/thread_restrictions.h" #include "components/pairing/bluetooth_host_pairing_controller.h" namespace pairing_chromeos { SharkConnectionListener::SharkConnectionListener( - const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner, + scoped_refptr<base::TaskRunner> input_service_task_runner, OnConnectedCallback callback) : callback_(callback) { - controller_.reset(new BluetoothHostPairingController(file_task_runner)); + controller_.reset( + new BluetoothHostPairingController(std::move(input_service_task_runner))); controller_->AddObserver(this); controller_->StartPairing(); }
diff --git a/components/pairing/shark_connection_listener.h b/components/pairing/shark_connection_listener.h index e940fe0..9b0b49d 100644 --- a/components/pairing/shark_connection_listener.h +++ b/components/pairing/shark_connection_listener.h
@@ -13,7 +13,7 @@ #include "components/pairing/host_pairing_controller.h" namespace base { -class SingleThreadTaskRunner; +class TaskRunner; } namespace pairing_chromeos { @@ -29,7 +29,7 @@ base::Callback<void(std::unique_ptr<HostPairingController>)>; SharkConnectionListener( - const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner, + scoped_refptr<base::TaskRunner> input_service_task_runner, OnConnectedCallback callback); ~SharkConnectionListener() override;
diff --git a/components/password_manager/core/browser/hash_password_manager.cc b/components/password_manager/core/browser/hash_password_manager.cc index 26aee4b..62d4596d 100644 --- a/components/password_manager/core/browser/hash_password_manager.cc +++ b/components/password_manager/core/browser/hash_password_manager.cc
@@ -11,8 +11,6 @@ namespace password_manager { -HashPasswordManager::HashPasswordManager(PrefService* prefs) : prefs_(prefs) {} - void HashPasswordManager::SavePasswordHash(const base::string16& password) { if (prefs_) { // TODO(crbug.com/657041) Implement creating a salt, hash calculation,
diff --git a/components/password_manager/core/browser/hash_password_manager.h b/components/password_manager/core/browser/hash_password_manager.h index 6d535bec..dd30872 100644 --- a/components/password_manager/core/browser/hash_password_manager.h +++ b/components/password_manager/core/browser/hash_password_manager.h
@@ -23,7 +23,7 @@ // All methods should be called on UI thread. class HashPasswordManager { public: - explicit HashPasswordManager(PrefService* prefs); + HashPasswordManager() = default; ~HashPasswordManager() = default; void SavePasswordHash(const base::string16& password); @@ -32,8 +32,10 @@ // Returns empty if no hash is available. base::Optional<SyncPasswordData> RetrievePasswordHash(); + void set_prefs(PrefService* prefs) { prefs_ = prefs; } + private: - PrefService* const prefs_; + PrefService* prefs_ = nullptr; DISALLOW_COPY_AND_ASSIGN(HashPasswordManager); };
diff --git a/components/password_manager/core/browser/hash_password_manager_unittest.cc b/components/password_manager/core/browser/hash_password_manager_unittest.cc index 1e2b57e..b647090 100644 --- a/components/password_manager/core/browser/hash_password_manager_unittest.cc +++ b/components/password_manager/core/browser/hash_password_manager_unittest.cc
@@ -29,14 +29,16 @@ TEST_F(HashPasswordManagerTest, Saving) { ASSERT_FALSE(prefs_.HasPrefPath(prefs::kSyncPasswordHash)); - HashPasswordManager hash_password_manager(&prefs_); + HashPasswordManager hash_password_manager; + hash_password_manager.set_prefs(&prefs_); hash_password_manager.SavePasswordHash(base::ASCIIToUTF16("sync_password")); EXPECT_TRUE(prefs_.HasPrefPath(prefs::kSyncPasswordHash)); } TEST_F(HashPasswordManagerTest, Clearing) { ASSERT_FALSE(prefs_.HasPrefPath(prefs::kSyncPasswordHash)); - HashPasswordManager hash_password_manager(&prefs_); + HashPasswordManager hash_password_manager; + hash_password_manager.set_prefs(&prefs_); hash_password_manager.SavePasswordHash(base::ASCIIToUTF16("sync_password")); hash_password_manager.ClearSavedPasswordHash(); EXPECT_FALSE(prefs_.HasPrefPath(prefs::kSyncPasswordHash)); @@ -44,7 +46,8 @@ TEST_F(HashPasswordManagerTest, Retrieving) { ASSERT_FALSE(prefs_.HasPrefPath(prefs::kSyncPasswordHash)); - HashPasswordManager hash_password_manager(&prefs_); + HashPasswordManager hash_password_manager; + hash_password_manager.set_prefs(&prefs_); hash_password_manager.SavePasswordHash(base::ASCIIToUTF16("sync_password")); // TODO(crbug.com/657041) Fix this text when hash calculation is implemented. EXPECT_FALSE(hash_password_manager.RetrievePasswordHash());
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc index 33da0da..51eb81d 100644 --- a/components/password_manager/core/browser/password_reuse_detector.cc +++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -5,13 +5,12 @@ #include "components/password_manager/core/browser/password_reuse_detector.h" #include <algorithm> +#include <utility> #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/password_manager_util.h" #include "components/password_manager/core/browser/password_reuse_detector_consumer.h" #include "components/password_manager/core/browser/psl_matching_helper.h" -#include "components/password_manager/core/common/password_manager_pref_names.h" -#include "components/prefs/pref_service.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_urls.h" #include "url/origin.h" @@ -45,8 +44,7 @@ rhs.rend()); } -PasswordReuseDetector::PasswordReuseDetector(PrefService* prefs) - : prefs_(prefs) {} +PasswordReuseDetector::PasswordReuseDetector() {} PasswordReuseDetector::~PasswordReuseDetector() {} @@ -84,23 +82,15 @@ const base::string16& input, const std::string& domain, PasswordReuseDetectorConsumer* consumer) { - if (!sync_password_hash_.has_value()) + if (!sync_password_data_.has_value()) return false; const Origin gaia_origin(GaiaUrls::GetInstance()->gaia_url().GetOrigin()); if (Origin(GURL(domain)).IsSameOriginWith(gaia_origin)) return false; - // Check that some suffix of |input| has the same hash as the sync password. - for (size_t i = 0; i + kMinPasswordLengthToCheck <= input.size(); ++i) { - base::StringPiece16 input_suffix(input.c_str() + i, input.size() - i); - if (password_manager_util::Calculate37BitsOfSHA256Hash(input_suffix) == - sync_password_hash_.value()) { - consumer->OnReuseFound(input_suffix.as_string(), - std::string(kSyncPasswordDomain), 1, 0); - return true; - } - } + // TODO(crbug.com/657041): Implement checking a hash of |input| with + // |sync_password_data_|. return false; } @@ -128,21 +118,13 @@ return false; } -void PasswordReuseDetector::SaveSyncPasswordHash( - const base::string16& password) { - sync_password_hash_ = - password_manager_util::Calculate37BitsOfSHA256Hash(password); - if (prefs_) { - // TODO(crbug.com/657041) Implement encrypting and saving of - // |sync_password_hash_| into preference kSyncPasswordHash. - prefs_->SetString(prefs::kSyncPasswordHash, std::string()); - } +void PasswordReuseDetector::UseSyncPasswordHash( + base::Optional<SyncPasswordData> sync_password_data) { + sync_password_data_ = std::move(sync_password_data); } void PasswordReuseDetector::ClearSyncPasswordHash() { - sync_password_hash_.reset(); - if (prefs_) - prefs_->ClearPref(prefs::kSyncPasswordHash); + sync_password_data_.reset(); } void PasswordReuseDetector::AddPassword(const autofill::PasswordForm& form) {
diff --git a/components/password_manager/core/browser/password_reuse_detector.h b/components/password_manager/core/browser/password_reuse_detector.h index f6d2d49d..4453deb 100644 --- a/components/password_manager/core/browser/password_reuse_detector.h +++ b/components/password_manager/core/browser/password_reuse_detector.h
@@ -15,11 +15,10 @@ #include "base/macros.h" #include "base/optional.h" #include "base/strings/string16.h" +#include "components/password_manager/core/browser/hash_password_manager.h" #include "components/password_manager/core/browser/password_store_change.h" #include "components/password_manager/core/browser/password_store_consumer.h" -class PrefService; - namespace password_manager { class PasswordReuseDetectorConsumer; @@ -39,7 +38,7 @@ // a password reuse. class PasswordReuseDetector : public PasswordStoreConsumer { public: - explicit PasswordReuseDetector(PrefService* prefs); + PasswordReuseDetector(); ~PasswordReuseDetector() override; // PasswordStoreConsumer @@ -58,8 +57,8 @@ const std::string& domain, PasswordReuseDetectorConsumer* consumer); - // Saves a hash of |password| for password reuse checking. - void SaveSyncPasswordHash(const base::string16& password); + // Stores internal |sync_password_data| for password reuse checking. + void UseSyncPasswordHash(base::Optional<SyncPasswordData> sync_password_data); // Clears a sync password hash if it was saved. void ClearSyncPasswordHash(); @@ -99,8 +98,7 @@ // of times how many different sites it's saved on. int saved_passwords_ = 0; - base::Optional<uint64_t> sync_password_hash_; - PrefService* const prefs_; + base::Optional<SyncPasswordData> sync_password_data_; DISALLOW_COPY_AND_ASSIGN(PasswordReuseDetector); };
diff --git a/components/password_manager/core/browser/password_reuse_detector_unittest.cc b/components/password_manager/core/browser/password_reuse_detector_unittest.cc index 2f45d16d..6266693 100644 --- a/components/password_manager/core/browser/password_reuse_detector_unittest.cc +++ b/components/password_manager/core/browser/password_reuse_detector_unittest.cc
@@ -10,10 +10,8 @@ #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/hash_password_manager.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" -#include "components/password_manager/core/common/password_manager_pref_names.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -63,7 +61,7 @@ } TEST(PasswordReuseDetectorTest, TypingPasswordOnDifferentSite) { - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; @@ -94,7 +92,7 @@ } TEST(PasswordReuseDetectorTest, PSLMatchNoReuseEvent) { - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; @@ -104,7 +102,7 @@ } TEST(PasswordReuseDetectorTest, NoPSLMatchReuseEvent) { - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; @@ -117,7 +115,7 @@ } TEST(PasswordReuseDetectorTest, TooShortPasswordNoReuseEvent) { - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; @@ -126,7 +124,7 @@ } TEST(PasswordReuseDetectorTest, PasswordNotInputSuffixNoReuseEvent) { - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; @@ -141,7 +139,7 @@ for (PasswordStoreChange::Type type : {PasswordStoreChange::ADD, PasswordStoreChange::UPDATE, PasswordStoreChange::REMOVE}) { - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; PasswordStoreChangeList changes = GetChangeList(type, GetForms(GetTestDomainsPasswords())); reuse_detector.OnLoginsChanged(changes); @@ -165,7 +163,7 @@ {"https://example3.com", "1234567890"}, }; - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(domain_passwords)); MockPasswordReuseDetectorConsumer mockConsumer; @@ -187,12 +185,15 @@ &mockConsumer); } -TEST(PasswordReuseDetectorTest, SyncPasswordNoReuse) { - PasswordReuseDetector reuse_detector(nullptr); +// TODO(crbug.com/657041): Enable when hash calculation is implemented. +TEST(PasswordReuseDetectorTest, DISABLED_SyncPasswordNoReuse) { + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; - reuse_detector.SaveSyncPasswordHash(ASCIIToUTF16("sync_password")); + // TODO(crbug.com/657041): Pass a password hash when hash calculation is + // implemented. + reuse_detector.UseSyncPasswordHash(base::Optional<SyncPasswordData>()); EXPECT_CALL(mockConsumer, OnReuseFound(_, _, _, _)).Times(0); reuse_detector.CheckReuse(ASCIIToUTF16("sync_password"), @@ -202,12 +203,15 @@ "https://evil.com", &mockConsumer); } -TEST(PasswordReuseDetectorTest, SyncPasswordReuseFound) { - PasswordReuseDetector reuse_detector(nullptr); +// TODO(crbug.com/657041): Enable when hash calculation is implemented. +TEST(PasswordReuseDetectorTest, DISABLED_SyncPasswordReuseFound) { + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; - reuse_detector.SaveSyncPasswordHash(ASCIIToUTF16("sync_password")); + // TODO(crbug.com/657041): Pass a password hash when hash calculation is + // implemented. + reuse_detector.UseSyncPasswordHash(base::Optional<SyncPasswordData>()); EXPECT_CALL(mockConsumer, OnReuseFound(ASCIIToUTF16("sync_password"), @@ -216,14 +220,18 @@ &mockConsumer); } -TEST(PasswordReuseDetectorTest, SavedPasswordsReuseSyncPasswordAvailable) { +// TODO(crbug.com/657041): Enable when hash calculation is implemented. +TEST(PasswordReuseDetectorTest, + DISABLED_SavedPasswordsReuseSyncPasswordAvailable) { // Check that reuse of saved passwords is detected also if the sync password // hash is saved. - PasswordReuseDetector reuse_detector(nullptr); + PasswordReuseDetector reuse_detector; reuse_detector.OnGetPasswordStoreResults(GetForms(GetTestDomainsPasswords())); MockPasswordReuseDetectorConsumer mockConsumer; - reuse_detector.SaveSyncPasswordHash(ASCIIToUTF16("sync_password")); + // TODO(crbug.com/657041): Pass a password hash when hash calculation is + // implemented. + reuse_detector.UseSyncPasswordHash(base::Optional<SyncPasswordData>()); EXPECT_CALL(mockConsumer, OnReuseFound(ASCIIToUTF16("password"), "google.com", 5, 1)); @@ -231,16 +239,6 @@ &mockConsumer); } -TEST(PasswordReuseDetectorTest, CheckThatSyncPasswordIsStoredIntoPreferences) { - TestingPrefServiceSimple prefs; - prefs.registry()->RegisterStringPref(prefs::kSyncPasswordHash, std::string(), - PrefRegistry::NO_REGISTRATION_FLAGS); - ASSERT_FALSE(prefs.HasPrefPath(prefs::kSyncPasswordHash)); - PasswordReuseDetector reuse_detector(&prefs); - reuse_detector.SaveSyncPasswordHash(ASCIIToUTF16("sync_password")); - EXPECT_TRUE(prefs.HasPrefPath(prefs::kSyncPasswordHash)); -} - } // namespace } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 378e4a8..35fccbc 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -113,8 +113,13 @@ bool PasswordStore::Init(const syncer::SyncableService::StartSyncFlare& flare, PrefService* prefs) { + ScheduleTask(base::Bind(&PasswordStore::InitOnBackgroundThread, this, flare)); +#if !defined(OS_ANDROID) && !defined(OS_IOS) + hash_password_manager_.set_prefs(prefs); ScheduleTask( - base::Bind(&PasswordStore::InitOnBackgroundThread, this, flare, prefs)); + base::Bind(&PasswordStore::SaveSyncPasswordHashImpl, this, + base::Passed(hash_password_manager_.RetrievePasswordHash()))); +#endif return true; } @@ -329,11 +334,15 @@ } void PasswordStore::SaveSyncPasswordHash(const base::string16& password) { - ScheduleTask( - base::Bind(&PasswordStore::SaveSyncPasswordHashImpl, this, password)); + hash_password_manager_.SavePasswordHash(password); + base::Optional<SyncPasswordData> sync_password_data = + hash_password_manager_.RetrievePasswordHash(); + ScheduleTask(base::Bind(&PasswordStore::SaveSyncPasswordHashImpl, this, + std::move(sync_password_data))); } void PasswordStore::ClearSyncPasswordHash() { + hash_password_manager_.ClearSavedPasswordHash(); ScheduleTask(base::Bind(&PasswordStore::ClearSyncPasswordHashImpl, this)); } #endif @@ -419,9 +428,10 @@ reuse_detector_->CheckReuse(input, domain, request.get()); } -void PasswordStore::SaveSyncPasswordHashImpl(const base::string16& password) { +void PasswordStore::SaveSyncPasswordHashImpl( + base::Optional<SyncPasswordData> sync_password_data) { if (reuse_detector_) - reuse_detector_->SaveSyncPasswordHash(password); + reuse_detector_->UseSyncPasswordHash(std::move(sync_password_data)); } void PasswordStore::ClearSyncPasswordHashImpl() { @@ -744,15 +754,14 @@ } void PasswordStore::InitOnBackgroundThread( - const syncer::SyncableService::StartSyncFlare& flare, - PrefService* prefs) { + const syncer::SyncableService::StartSyncFlare& flare) { DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); DCHECK(!syncable_service_); syncable_service_.reset(new PasswordSyncableService(this)); syncable_service_->InjectStartSyncFlare(flare); // TODO(crbug.com/706392): Fix password reuse detection for Android. #if !defined(OS_ANDROID) && !defined(OS_IOS) - reuse_detector_ = base::MakeUnique<PasswordReuseDetector>(prefs); + reuse_detector_ = base::MakeUnique<PasswordReuseDetector>(); GetAutofillableLoginsImpl( base::MakeUnique<GetLoginsRequest>(reuse_detector_.get())); #endif
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 40ecd07..0518991 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -23,6 +23,7 @@ // TODO(crbug.com/706392): Fix password reuse detection for Android. #if !defined(OS_ANDROID) && !defined(OS_IOS) +#include "components/password_manager/core/browser/hash_password_manager.h" #include "components/password_manager/core/browser/password_reuse_detector.h" #include "components/password_manager/core/browser/password_reuse_detector_consumer.h" #endif @@ -432,7 +433,8 @@ const std::string& domain); // Synchronous implementation of SaveSyncPasswordHash(). - void SaveSyncPasswordHashImpl(const base::string16& password); + void SaveSyncPasswordHashImpl( + base::Optional<SyncPasswordData> sync_password_data); // Synchronous implementation of ClearSyncPasswordHash(). void ClearSyncPasswordHashImpl(); @@ -584,8 +586,7 @@ // Creates PasswordSyncableService and PasswordReuseDetector instances on the // background thread. void InitOnBackgroundThread( - const syncer::SyncableService::StartSyncFlare& flare, - PrefService* prefs); + const syncer::SyncableService::StartSyncFlare& flare); // Deletes objest that should be destroyed on the background thread. void DestroyOnBackgroundThread(); @@ -598,6 +599,7 @@ // TODO(crbug.com/706392): Fix password reuse detection for Android. #if !defined(OS_ANDROID) && !defined(OS_IOS) std::unique_ptr<PasswordReuseDetector> reuse_detector_; + HashPasswordManager hash_password_manager_; #endif bool is_propagating_password_changes_to_web_credentials_enabled_;
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index 29ba50f13..3329dba3 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -31,6 +31,9 @@ #include "components/password_manager/core/browser/password_reuse_detector.h" #include "components/password_manager/core/browser/password_store_consumer.h" #include "components/password_manager/core/browser/password_store_default.h" +#include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -981,28 +984,28 @@ scoped_refptr<PasswordStoreDefault> store(new PasswordStoreDefault( base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(), base::MakeUnique<LoginDatabase>(test_login_db_file_path()))); - store->Init(syncer::SyncableService::StartSyncFlare(), nullptr); + + TestingPrefServiceSimple prefs; + prefs.registry()->RegisterStringPref(prefs::kSyncPasswordHash, std::string(), + PrefRegistry::NO_REGISTRATION_FLAGS); + ASSERT_FALSE(prefs.HasPrefPath(prefs::kSyncPasswordHash)); + store->Init(syncer::SyncableService::StartSyncFlare(), &prefs); const base::string16 sync_password = base::ASCIIToUTF16("password"); const base::string16 input = base::ASCIIToUTF16("123password"); store->SaveSyncPasswordHash(sync_password); base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(prefs.HasPrefPath(prefs::kSyncPasswordHash)); - // Check that sync password reuse is found. - MockPasswordReuseDetectorConsumer mock_consumer; - EXPECT_CALL( - mock_consumer, - OnReuseFound(sync_password, std::string(kSyncPasswordDomain), 1, 0)); - store->CheckReuse(input, "https://facebook.com", &mock_consumer); - base::RunLoop().RunUntilIdle(); - testing::Mock::VerifyAndClearExpectations(&mock_consumer); + // TODO(crbug.com/657041): Check that password reuse works when sync hash + // calculation is implemented. // Check that no sync password reuse is found after clearing the saved sync // password hash. store->ClearSyncPasswordHash(); - EXPECT_CALL(mock_consumer, OnReuseFound(_, _, _, _)).Times(0); - store->CheckReuse(input, "https://facebook.com", &mock_consumer); - base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(prefs.HasPrefPath(prefs::kSyncPasswordHash)); + // TODO(crbug.com/657041): Check that no password reuse happens here when sync + // hash calculation is implemented. store->ShutdownOnUIThread(); base::RunLoop().RunUntilIdle();
diff --git a/components/payments/core/payment_request_data_util.cc b/components/payments/core/payment_request_data_util.cc index 7f68941..8a9585f7 100644 --- a/components/payments/core/payment_request_data_util.cc +++ b/components/payments/core/payment_request_data_util.cc
@@ -6,6 +6,7 @@ #include "base/strings/string16.h" #include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/autofill_data_util.h" @@ -191,6 +192,26 @@ PhoneNumberUtil::PhoneNumberFormat::E164); } +base::string16 FormatCardNumberForDisplay(const base::string16& card_number) { + base::string16 number = autofill::CreditCard::StripSeparators(card_number); + if (number.empty() || !base::IsAsciiDigit(number[0])) + return card_number; + + std::vector<size_t> positions = {4U, 9U, 14U}; + if (autofill::CreditCard::GetCardNetwork(number) == + autofill::kAmericanExpressCard) { + positions = {4U, 11U}; + } + + static const base::char16 kSeparator = base::ASCIIToUTF16(" ")[0]; + for (size_t i : positions) { + if (number.size() > i) + number.insert(i, 1U, kSeparator); + } + + return number; +} + std::string GetCountryCodeWithFallback(const autofill::AutofillProfile* profile, const std::string& app_locale) { std::string country_code =
diff --git a/components/payments/core/payment_request_data_util.h b/components/payments/core/payment_request_data_util.h index c301946d..c3c1adb 100644 --- a/components/payments/core/payment_request_data_util.h +++ b/components/payments/core/payment_request_data_util.h
@@ -71,6 +71,11 @@ std::string FormatPhoneForResponse(const std::string& phone_number, const std::string& country_code); +// Formats |card_number| for display. For example, "4111111111111111" is +// formatted into "4111 1111 1111 1111". This method does not format masked card +// numbers, which start with a letter. +base::string16 FormatCardNumberForDisplay(const base::string16& card_number); + // Returns a country code to be used when validating this profile. If the // profile has a valid country code set, it is returned. If not, a country code // associated with |app_locale| is used as a fallback.
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn index 17217b1..d509384 100644 --- a/components/policy/core/common/BUILD.gn +++ b/components/policy/core/common/BUILD.gn
@@ -157,6 +157,7 @@ "ntdsapi.lib", ] } + # Compile on Linux for fuzzer and since code is reused on Chrome OS. if (is_win || is_linux) { sources += [ @@ -188,6 +189,8 @@ } if (is_chromeos) { sources += [ + "policy_scheduler.cc", + "policy_scheduler.h", "proxy_policy_provider.cc", "proxy_policy_provider.h", ] @@ -305,7 +308,10 @@ ] } if (is_chromeos) { - sources += [ "proxy_policy_provider_unittest.cc" ] + sources += [ + "policy_scheduler_unittest.cc", + "proxy_policy_provider_unittest.cc", + ] } else { sources += [ "cloud/user_cloud_policy_manager_unittest.cc",
diff --git a/components/policy/core/common/policy_scheduler.cc b/components/policy/core/common/policy_scheduler.cc new file mode 100644 index 0000000..b4c4bd1 --- /dev/null +++ b/components/policy/core/common/policy_scheduler.cc
@@ -0,0 +1,74 @@ +// Copyright 2017 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 "components/policy/core/common/policy_scheduler.h" + +#include "base/memory/ptr_util.h" +#include "base/threading/thread_task_runner_handle.h" + +namespace policy { + +PolicyScheduler::PolicyScheduler(Task task, + SchedulerCallback callback, + base::TimeDelta interval) + : task_(task), callback_(callback), interval_(interval) { + ScheduleTaskNow(); +} + +PolicyScheduler::~PolicyScheduler() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void PolicyScheduler::ScheduleTaskNow() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + ScheduleDelayedTask(base::TimeDelta()); +} + +void PolicyScheduler::ScheduleDelayedTask(base::TimeDelta delay) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (job_) { + job_->Cancel(); + } + job_ = base::MakeUnique<base::CancelableClosure>(base::Bind( + &PolicyScheduler::RunScheduledTask, weak_ptr_factory_.GetWeakPtr())); + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, + job_->callback(), delay); +} + +void PolicyScheduler::ScheduleNextTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + base::TimeDelta interval = overlap_ ? base::TimeDelta() : interval_; + const base::TimeTicks now(base::TimeTicks::Now()); + // Time uses saturated arithmetics thus no under/overflow possible. + const base::TimeDelta delay = last_task_ + interval - now; + // Clamping delay to non-negative values just to be on the safe side. + ScheduleDelayedTask(std::max(base::TimeDelta(), delay)); +} + +void PolicyScheduler::RunScheduledTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (task_in_progress_) { + overlap_ = true; + return; + } + + overlap_ = false; + task_in_progress_ = true; + task_.Run(base::BindOnce(&PolicyScheduler::OnTaskDone, + weak_ptr_factory_.GetWeakPtr())); +} + +void PolicyScheduler::OnTaskDone(bool success) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + task_in_progress_ = false; + last_task_ = base::TimeTicks::Now(); + callback_.Run(success); + ScheduleNextTask(); +} + +} // namespace policy
diff --git a/components/policy/core/common/policy_scheduler.h b/components/policy/core/common/policy_scheduler.h new file mode 100644 index 0000000..a570143 --- /dev/null +++ b/components/policy/core/common/policy_scheduler.h
@@ -0,0 +1,95 @@ +// Copyright 2017 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 COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEDULER_H_ +#define COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEDULER_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/cancelable_callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/time/time.h" +#include "components/policy/policy_export.h" + +namespace policy { + +// Scheduler for driving repeated asynchronous tasks such as e.g. policy +// fetches. Subsequent tasks are guaranteed not to overlap. Tasks are posted to +// the current thread and therefore must not block (suitable e.g. for +// asynchronous D-Bus calls). +// Tasks scheduling begins immediately after instantiation of the class. Upon +// destruction, scheduled but not yet started tasks are cancelled. The result of +// started but not finished tasks is NOT reported. +class POLICY_EXPORT PolicyScheduler { + public: + // Callback for the task to report success or failure. + using TaskCallback = base::OnceCallback<void(bool success)>; + + // Task to be performed at regular intervals. The task takes a |callback| to + // return success or failure. + using Task = base::RepeatingCallback<void(TaskCallback callback)>; + + // Callback for PolicyScheduler to report success or failure of the tasks. + using SchedulerCallback = base::RepeatingCallback<void(bool success)>; + + // Defines the |task| to be run every |interval| and the |callback| for the + // scheduler to report the result. (Intervals are computed as the time + // difference between the end of the previous and the start of the subsequent + // task.) Calling the constructor starts the loop and schedules the first task + // to be run without delay. + PolicyScheduler(Task task, + SchedulerCallback callback, + base::TimeDelta interval); + ~PolicyScheduler(); + + // Schedules a task to run immediately. Deletes any previously scheduled but + // not yet started tasks. In case a task is running currently, the new task is + // scheduled to run immediately after the end of the currently running task. + void ScheduleTaskNow(); + + private: + // Schedules next task to run in |delay|. Deletes any previously scheduled + // tasks. + void ScheduleDelayedTask(base::TimeDelta delay); + + // Schedules next task to run in |interval_| or immediately in case of + // overlap. Deletes any previously scheduled tasks. + void ScheduleNextTask(); + + // Actually executes the scheduled task. + void RunScheduledTask(); + + // Reports back the |result| of the previous task and schedules the next one. + void OnTaskDone(bool result); + + Task task_; + SchedulerCallback callback_; + const base::TimeDelta interval_; + + // Whether a task is in progress. + bool task_in_progress_ = false; + + // Whether there had been an overlap of tasks and thus the next task needs to + // be scheduled without delay. + bool overlap_ = false; + + // End time of the previous task. Zero in case no task has ended yet. + base::TimeTicks last_task_; + + std::unique_ptr<base::CancelableClosure> job_; + + SEQUENCE_CHECKER(sequence_checker_); + + // Must be last member. + base::WeakPtrFactory<PolicyScheduler> weak_ptr_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(PolicyScheduler); +}; + +} // namespace policy + +#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEDULER_H_ \ No newline at end of file
diff --git a/components/policy/core/common/policy_scheduler_unittest.cc b/components/policy/core/common/policy_scheduler_unittest.cc new file mode 100644 index 0000000..cb5758c --- /dev/null +++ b/components/policy/core/common/policy_scheduler_unittest.cc
@@ -0,0 +1,134 @@ +// Copyright 2017 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 "components/policy/core/common/policy_scheduler.h" + +#include <memory> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "base/threading/thread_task_runner_handle.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +class PolicySchedulerTest : public testing::Test { + public: + void DoTask(PolicyScheduler::TaskCallback callback) { + do_counter_++; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), true)); + } + + void OnTaskDone(bool success) { + done_counter_++; + + // Terminate PolicyScheduler after 5 iterations. + if (done_counter_ >= 5) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&PolicySchedulerTest::Terminate, + base::Unretained(this))); + } + } + + // To simulate a slow task the callback is captured instead of running it. + void CaptureCallbackForSlowTask(PolicyScheduler::TaskCallback callback) { + do_counter_++; + slow_callback_ = std::move(callback); + } + + // Runs the captured callback to simulate the end of the slow task. + void PostSlowTaskCallback() { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(slow_callback_), true)); + } + + void Terminate() { scheduler_.reset(); } + + protected: + int do_counter_ = 0; + int done_counter_ = 0; + std::unique_ptr<PolicyScheduler> scheduler_; + + PolicyScheduler::TaskCallback slow_callback_; + + base::test::ScopedTaskEnvironment scoped_task_environment_; +}; + +TEST_F(PolicySchedulerTest, Run) { + scheduler_ = base::MakeUnique<PolicyScheduler>( + base::BindRepeating(&PolicySchedulerTest::DoTask, base::Unretained(this)), + base::BindRepeating(&PolicySchedulerTest::OnTaskDone, + base::Unretained(this)), + base::TimeDelta::Max()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, done_counter_); +} + +TEST_F(PolicySchedulerTest, Loop) { + scheduler_ = base::MakeUnique<PolicyScheduler>( + base::BindRepeating(&PolicySchedulerTest::DoTask, base::Unretained(this)), + base::BindRepeating(&PolicySchedulerTest::OnTaskDone, + base::Unretained(this)), + base::TimeDelta()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(5, done_counter_); +} + +TEST_F(PolicySchedulerTest, Reschedule) { + scheduler_ = base::MakeUnique<PolicyScheduler>( + base::BindRepeating(&PolicySchedulerTest::DoTask, base::Unretained(this)), + base::BindRepeating(&PolicySchedulerTest::OnTaskDone, + base::Unretained(this)), + base::TimeDelta::Max()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, done_counter_); + + // Delayed action is not run. + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, done_counter_); + + // Rescheduling with 0 delay causes it to run. + scheduler_->ScheduleTaskNow(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(2, done_counter_); +} + +TEST_F(PolicySchedulerTest, OverlappingTasks) { + scheduler_ = base::MakeUnique<PolicyScheduler>( + base::BindRepeating(&PolicySchedulerTest::CaptureCallbackForSlowTask, + base::Unretained(this)), + base::BindRepeating(&PolicySchedulerTest::OnTaskDone, + base::Unretained(this)), + base::TimeDelta::Max()); + + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, do_counter_); + EXPECT_EQ(0, done_counter_); + + // Second action doesn't start while first is still pending. + scheduler_->ScheduleTaskNow(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1, do_counter_); + EXPECT_EQ(0, done_counter_); + + // After first action has finished, the second is started. + PostSlowTaskCallback(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(2, do_counter_); + EXPECT_EQ(1, done_counter_); + + // Let the second action finish. + PostSlowTaskCallback(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(2, do_counter_); + EXPECT_EQ(2, done_counter_); +} + +} // namespace policy \ No newline at end of file
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index ecb8291d..f42cb4d 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -26,6 +26,8 @@ "display_compositor/gpu_display_provider.h", "display_compositor/host_shared_bitmap_manager.cc", "display_compositor/host_shared_bitmap_manager.h", + "display_compositor/in_process_gpu_memory_buffer_manager.cc", + "display_compositor/in_process_gpu_memory_buffer_manager.h", "frame_sinks/frame_eviction_manager.cc", "frame_sinks/frame_eviction_manager.h", "frame_sinks/frame_evictor.cc", @@ -44,6 +46,13 @@ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] + deps = [ + # Note that dependency on //gpu/ipc/client is for GpuMemoryBufferImpl. This + # dependency should not be in public_deps. + "//gpu/ipc/client", + "//gpu/ipc/service", + ] + public_deps = [ "//base", "//cc",
diff --git a/components/viz/service/display_compositor/gpu_display_provider.cc b/components/viz/service/display_compositor/gpu_display_provider.cc index 8526c010..49f1376 100644 --- a/components/viz/service/display_compositor/gpu_display_provider.cc +++ b/components/viz/service/display_compositor/gpu_display_provider.cc
@@ -17,23 +17,36 @@ #include "cc/surfaces/display_scheduler.h" #include "components/viz/service/display_compositor/display_output_surface.h" #include "components/viz/service/display_compositor/host_shared_bitmap_manager.h" +#include "components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/shared_memory_limits.h" #include "gpu/command_buffer/service/image_factory.h" +#include "gpu/ipc/service/gpu_channel_manager.h" +#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #if defined(USE_OZONE) #include "components/viz/service/display_compositor/display_output_surface_ozone.h" #include "gpu/command_buffer/client/gles2_interface.h" #endif +namespace { + +gpu::ImageFactory* GetImageFactory(gpu::GpuChannelManager* channel_manager) { + auto* buffer_factory = channel_manager->gpu_memory_buffer_factory(); + return buffer_factory ? buffer_factory->AsImageFactory() : nullptr; +} + +} // namespace + namespace viz { GpuDisplayProvider::GpuDisplayProvider( scoped_refptr<gpu::InProcessCommandBuffer::Service> gpu_service, - std::unique_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager, - gpu::ImageFactory* image_factory) + gpu::GpuChannelManager* gpu_channel_manager) : gpu_service_(std::move(gpu_service)), - gpu_memory_buffer_manager_(std::move(gpu_memory_buffer_manager)), - image_factory_(image_factory), + gpu_memory_buffer_manager_( + base::MakeUnique<InProcessGpuMemoryBufferManager>( + gpu_channel_manager)), + image_factory_(GetImageFactory(gpu_channel_manager)), task_runner_(base::ThreadTaskRunnerHandle::Get()) {} GpuDisplayProvider::~GpuDisplayProvider() = default;
diff --git a/components/viz/service/display_compositor/gpu_display_provider.h b/components/viz/service/display_compositor/gpu_display_provider.h index 1afb34a..ab936fe 100644 --- a/components/viz/service/display_compositor/gpu_display_provider.h +++ b/components/viz/service/display_compositor/gpu_display_provider.h
@@ -18,6 +18,7 @@ #include "gpu/ipc/in_process_command_buffer.h" namespace gpu { +class GpuChannelManager; class ImageFactory; } @@ -29,8 +30,7 @@ public: GpuDisplayProvider( scoped_refptr<gpu::InProcessCommandBuffer::Service> gpu_service, - std::unique_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager, - gpu::ImageFactory* image_factory); + gpu::GpuChannelManager* gpu_channel_manager); ~GpuDisplayProvider() override; // DisplayProvider:
diff --git a/components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.cc b/components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.cc new file mode 100644 index 0000000..26f0015f --- /dev/null +++ b/components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.cc
@@ -0,0 +1,51 @@ +// Copyright 2017 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 "components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.h" + +#include "gpu/ipc/client/gpu_memory_buffer_impl.h" +#include "gpu/ipc/service/gpu_channel_manager.h" +#include "gpu/ipc/service/gpu_memory_buffer_factory.h" + +namespace viz { + +InProcessGpuMemoryBufferManager::InProcessGpuMemoryBufferManager( + gpu::GpuChannelManager* channel_manager) + : client_id_(1), channel_manager_(channel_manager), weak_factory_(this) { + weak_ptr_ = weak_factory_.GetWeakPtr(); +} + +InProcessGpuMemoryBufferManager::~InProcessGpuMemoryBufferManager() {} + +std::unique_ptr<gfx::GpuMemoryBuffer> +InProcessGpuMemoryBufferManager::CreateGpuMemoryBuffer( + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferUsage usage, + gpu::SurfaceHandle surface_handle) { + gfx::GpuMemoryBufferId id(next_gpu_memory_id_++); + gfx::GpuMemoryBufferHandle buffer_handle = + channel_manager_->gpu_memory_buffer_factory()->CreateGpuMemoryBuffer( + id, size, format, usage, client_id_, surface_handle); + return gpu::GpuMemoryBufferImpl::CreateFromHandle( + buffer_handle, size, format, usage, + base::Bind(&InProcessGpuMemoryBufferManager::DestroyGpuMemoryBuffer, + weak_ptr_, id, client_id_)); +} + +void InProcessGpuMemoryBufferManager::SetDestructionSyncToken( + gfx::GpuMemoryBuffer* buffer, + const gpu::SyncToken& sync_token) { + static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token( + sync_token); +} + +void InProcessGpuMemoryBufferManager::DestroyGpuMemoryBuffer( + gfx::GpuMemoryBufferId id, + int client_id, + const gpu::SyncToken& sync_token) { + channel_manager_->DestroyGpuMemoryBuffer(id, client_id, sync_token); +} + +} // namespace viz
diff --git a/components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.h b/components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.h new file mode 100644 index 0000000..4be5c8c --- /dev/null +++ b/components/viz/service/display_compositor/in_process_gpu_memory_buffer_manager.h
@@ -0,0 +1,47 @@ +// Copyright 2017 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 COMPONENTS_VIZ_SERVICE_DISPLAY_COMPOSITOR_IN_PROCESS_GPU_MEMORY_BUFFER_MANAGER_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_COMPOSITOR_IN_PROCESS_GPU_MEMORY_BUFFER_MANAGER_H_ + +#include "base/memory/weak_ptr.h" +#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" + +namespace gpu { +class GpuChannelManager; +} + +namespace viz { + +class InProcessGpuMemoryBufferManager : public gpu::GpuMemoryBufferManager { + public: + explicit InProcessGpuMemoryBufferManager( + gpu::GpuChannelManager* channel_manager); + + ~InProcessGpuMemoryBufferManager() override; + + // gpu::GpuMemoryBufferManager: + std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer( + const gfx::Size& size, + gfx::BufferFormat format, + gfx::BufferUsage usage, + gpu::SurfaceHandle surface_handle) override; + void SetDestructionSyncToken(gfx::GpuMemoryBuffer* buffer, + const gpu::SyncToken& sync_token) override; + + private: + void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, + int client_id, + const gpu::SyncToken& sync_token); + const int client_id_; + int next_gpu_memory_id_ = 1; + gpu::GpuChannelManager* channel_manager_; + base::WeakPtr<InProcessGpuMemoryBufferManager> weak_ptr_; + base::WeakPtrFactory<InProcessGpuMemoryBufferManager> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(InProcessGpuMemoryBufferManager); +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_COMPOSITOR_IN_PROCESS_GPU_MEMORY_BUFFER_MANAGER_H_
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn index 675733f6..1b4bd035 100644 --- a/content/app/BUILD.gn +++ b/content/app/BUILD.gn
@@ -124,6 +124,8 @@ "android/app_jni_registrar.h", "android/child_process_service_impl.cc", "android/child_process_service_impl.h", + "android/content_child_process_service_delegate.cc", + "android/content_child_process_service_delegate.h", "android/content_jni_onload.cc", "android/content_main.cc", "android/content_main.h",
diff --git a/content/app/android/app_jni_registrar.cc b/content/app/android/app_jni_registrar.cc index f8557b1b..5d4c4470 100644 --- a/content/app/android/app_jni_registrar.cc +++ b/content/app/android/app_jni_registrar.cc
@@ -8,13 +8,16 @@ #include "base/android/jni_registrar.h" #include "base/macros.h" #include "content/app/android/child_process_service_impl.h" +#include "content/app/android/content_child_process_service_delegate.h" #include "content/app/android/content_main.h" namespace { base::android::RegistrationMethod kContentRegisteredMethods[] = { - { "ContentMain", content::RegisterContentMain }, - { "ChildProcessServiceImpl", content::RegisterChildProcessServiceImpl }, + {"ContentChildProcessServiceDelegate", + content::RegisterContentChildProcessServiceDelegate}, + {"ContentMain", content::RegisterContentMain}, + {"ChildProcessServiceImpl", content::RegisterChildProcessServiceImpl}, }; } // namespace
diff --git a/content/app/android/child_process_service_impl.cc b/content/app/android/child_process_service_impl.cc index 08be4443..69f0dec 100644 --- a/content/app/android/child_process_service_impl.cc +++ b/content/app/android/child_process_service_impl.cc
@@ -4,127 +4,23 @@ #include "content/app/android/child_process_service_impl.h" -#include <android/native_window_jni.h> -#include <cpu-features.h> - #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/android/library_loader/library_loader_hooks.h" -#include "base/android/memory_pressure_listener_android.h" -#include "base/android/unguessable_token_android.h" +#include "base/command_line.h" #include "base/file_descriptor_store.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/macros.h" #include "base/posix/global_descriptors.h" -#include "base/unguessable_token.h" -#include "content/child/child_thread_impl.h" -#include "content/public/common/content_descriptors.h" -#include "content/public/common/content_switches.h" -#include "gpu/ipc/common/android/scoped_surface_request_conduit.h" -#include "gpu/ipc/common/gpu_surface_lookup.h" #include "jni/ChildProcessServiceImpl_jni.h" #include "services/service_manager/embedder/shared_file_util.h" #include "services/service_manager/embedder/switches.h" -#include "ui/gl/android/scoped_java_surface.h" -#include "ui/gl/android/surface_texture.h" -using base::android::AttachCurrentThread; -using base::android::CheckException; using base::android::JavaIntArrayToIntVector; using base::android::JavaParamRef; namespace content { -namespace { - -// TODO(sievers): Use two different implementations of this depending on if -// we're in a renderer or gpu process. -class ChildProcessSurfaceManager : public gpu::ScopedSurfaceRequestConduit, - public gpu::GpuSurfaceLookup { - public: - ChildProcessSurfaceManager() {} - ~ChildProcessSurfaceManager() override {} - - // |service impl| is the instance of - // org.chromium.content.app.ChildProcessServiceImpl. - void SetServiceImpl(const base::android::JavaRef<jobject>& service_impl) { - service_impl_.Reset(service_impl); - } - - // Overriden from ScopedSurfaceRequestConduit: - void ForwardSurfaceTextureForSurfaceRequest( - const base::UnguessableToken& request_token, - const gl::SurfaceTexture* surface_texture) override { - JNIEnv* env = base::android::AttachCurrentThread(); - - content:: - Java_ChildProcessServiceImpl_forwardSurfaceTextureForSurfaceRequest( - env, service_impl_, - base::android::UnguessableTokenAndroid::Create(env, request_token), - surface_texture->j_surface_texture()); - } - - // Overridden from GpuSurfaceLookup: - gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override { - JNIEnv* env = base::android::AttachCurrentThread(); - gl::ScopedJavaSurface surface( - content::Java_ChildProcessServiceImpl_getViewSurface(env, service_impl_, - surface_id)); - - if (surface.j_surface().is_null()) - return NULL; - - // Note: This ensures that any local references used by - // ANativeWindow_fromSurface are released immediately. This is needed as a - // workaround for https://code.google.com/p/android/issues/detail?id=68174 - base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env); - ANativeWindow* native_window = - ANativeWindow_fromSurface(env, surface.j_surface().obj()); - - return native_window; - } - - // Overridden from GpuSurfaceLookup: - gl::ScopedJavaSurface AcquireJavaSurface(int surface_id) override { - JNIEnv* env = base::android::AttachCurrentThread(); - return gl::ScopedJavaSurface( - content::Java_ChildProcessServiceImpl_getViewSurface(env, service_impl_, - surface_id)); - } - - private: - friend struct base::LazyInstanceTraitsBase<ChildProcessSurfaceManager>; - // The instance of org.chromium.content.app.ChildProcessServiceImpl. - base::android::ScopedJavaGlobalRef<jobject> service_impl_; - - DISALLOW_COPY_AND_ASSIGN(ChildProcessSurfaceManager); -}; - -static base::LazyInstance<ChildProcessSurfaceManager>::Leaky - g_child_process_surface_manager = LAZY_INSTANCE_INITIALIZER; - -// Chrome actually uses the renderer code path for all of its child -// processes such as renderers, plugins, etc. -void InternalInitChildProcessImpl(JNIEnv* env, - const JavaParamRef<jobject>& service_impl, - jint cpu_count, - jlong cpu_features) { - // Set the CPU properties. - android_setCpu(cpu_count, cpu_features); - - g_child_process_surface_manager.Get().SetServiceImpl(service_impl); - - gpu::GpuSurfaceLookup::InitInstance( - g_child_process_surface_manager.Pointer()); - gpu::ScopedSurfaceRequestConduit::SetInstance( - g_child_process_surface_manager.Pointer()); - - base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(env); -} - -} // namespace <anonymous> - void RegisterFileDescriptors(JNIEnv* env, const JavaParamRef<jclass>& clazz, const JavaParamRef<jintArray>& j_ids, @@ -170,14 +66,6 @@ } } -void InitChildProcessImpl(JNIEnv* env, - const JavaParamRef<jclass>& clazz, - const JavaParamRef<jobject>& service_impl, - jint cpu_count, - jlong cpu_features) { - InternalInitChildProcessImpl(env, service_impl, cpu_count, cpu_features); -} - void ExitChildProcess(JNIEnv* env, const JavaParamRef<jclass>& clazz) { VLOG(0) << "ChildProcessServiceImpl: Exiting child process."; base::android::LibraryLoaderExitHook(); @@ -188,8 +76,4 @@ return RegisterNativesImpl(env); } -void ShutdownMainThread(JNIEnv* env, const JavaParamRef<jobject>& obj) { - ChildThreadImpl::ShutdownThread(); -} - } // namespace content
diff --git a/content/app/android/content_child_process_service_delegate.cc b/content/app/android/content_child_process_service_delegate.cc new file mode 100644 index 0000000..fc7757d --- /dev/null +++ b/content/app/android/content_child_process_service_delegate.cc
@@ -0,0 +1,137 @@ +// Copyright 2017 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/app/android/content_child_process_service_delegate.h" + +#include <android/native_window_jni.h> +#include <cpu-features.h> + +#include "base/android/library_loader/library_loader_hooks.h" +#include "base/android/memory_pressure_listener_android.h" +#include "base/android/unguessable_token_android.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/unguessable_token.h" +#include "content/child/child_thread_impl.h" +#include "content/public/common/content_descriptors.h" +#include "content/public/common/content_switches.h" +#include "gpu/ipc/common/android/scoped_surface_request_conduit.h" +#include "gpu/ipc/common/gpu_surface_lookup.h" +#include "jni/ContentChildProcessServiceDelegate_jni.h" +#include "services/service_manager/embedder/shared_file_util.h" +#include "services/service_manager/embedder/switches.h" +#include "ui/gl/android/scoped_java_surface.h" +#include "ui/gl/android/surface_texture.h" + +using base::android::AttachCurrentThread; +using base::android::JavaParamRef; + +namespace content { + +namespace { + +// TODO(sievers): Use two different implementations of this depending on if +// we're in a renderer or gpu process. +class ChildProcessSurfaceManager : public gpu::ScopedSurfaceRequestConduit, + public gpu::GpuSurfaceLookup { + public: + ChildProcessSurfaceManager() {} + ~ChildProcessSurfaceManager() override {} + + // |service impl| is the instance of + // org.chromium.content.app.ChildProcessServiceImpl. + void SetServiceImpl(const base::android::JavaRef<jobject>& service_impl) { + service_impl_.Reset(service_impl); + } + + // Overriden from ScopedSurfaceRequestConduit: + void ForwardSurfaceTextureForSurfaceRequest( + const base::UnguessableToken& request_token, + const gl::SurfaceTexture* surface_texture) override { + JNIEnv* env = base::android::AttachCurrentThread(); + + content:: + Java_ContentChildProcessServiceDelegate_forwardSurfaceTextureForSurfaceRequest( + env, service_impl_, + base::android::UnguessableTokenAndroid::Create(env, request_token), + surface_texture->j_surface_texture()); + } + + // Overridden from GpuSurfaceLookup: + gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override { + JNIEnv* env = base::android::AttachCurrentThread(); + gl::ScopedJavaSurface surface( + content::Java_ContentChildProcessServiceDelegate_getViewSurface( + env, service_impl_, surface_id)); + + if (surface.j_surface().is_null()) + return NULL; + + // Note: This ensures that any local references used by + // ANativeWindow_fromSurface are released immediately. This is needed as a + // workaround for https://code.google.com/p/android/issues/detail?id=68174 + base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env); + ANativeWindow* native_window = + ANativeWindow_fromSurface(env, surface.j_surface().obj()); + + return native_window; + } + + // Overridden from GpuSurfaceLookup: + gl::ScopedJavaSurface AcquireJavaSurface(int surface_id) override { + JNIEnv* env = base::android::AttachCurrentThread(); + return gl::ScopedJavaSurface( + content::Java_ContentChildProcessServiceDelegate_getViewSurface( + env, service_impl_, surface_id)); + } + + private: + friend struct base::LazyInstanceTraitsBase<ChildProcessSurfaceManager>; + // The instance of org.chromium.content.app.ChildProcessServiceImpl. + base::android::ScopedJavaGlobalRef<jobject> service_impl_; + + DISALLOW_COPY_AND_ASSIGN(ChildProcessSurfaceManager); +}; + +base::LazyInstance<ChildProcessSurfaceManager>::Leaky + g_child_process_surface_manager = LAZY_INSTANCE_INITIALIZER; + +// Chrome actually uses the renderer code path for all of its child +// processes such as renderers, plugins, etc. +void InternalInitChildProcess(JNIEnv* env, + const JavaParamRef<jobject>& service_impl, + jint cpu_count, + jlong cpu_features) { + // Set the CPU properties. + android_setCpu(cpu_count, cpu_features); + + g_child_process_surface_manager.Get().SetServiceImpl(service_impl); + + gpu::GpuSurfaceLookup::InitInstance( + g_child_process_surface_manager.Pointer()); + gpu::ScopedSurfaceRequestConduit::SetInstance( + g_child_process_surface_manager.Pointer()); + + base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(env); +} + +} // namespace + +void InitChildProcess(JNIEnv* env, + const JavaParamRef<jobject>& obj, + jint cpu_count, + jlong cpu_features) { + InternalInitChildProcess(env, obj, cpu_count, cpu_features); +} + +void ShutdownMainThread(JNIEnv* env, const JavaParamRef<jobject>& obj) { + ChildThreadImpl::ShutdownThread(); +} + +bool RegisterContentChildProcessServiceDelegate(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace content
diff --git a/content/app/android/content_child_process_service_delegate.h b/content/app/android/content_child_process_service_delegate.h new file mode 100644 index 0000000..f338fb5 --- /dev/null +++ b/content/app/android/content_child_process_service_delegate.h
@@ -0,0 +1,14 @@ +// Copyright 2017 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_APP_ANDROID_CONTENT_CHILD_PROCESS_SERVICE_DELEGATE_H_ +#define CONTENT_APP_ANDROID_CONTENT_CHILD_PROCESS_SERVICE_DELEGATE_H_ + +#include <jni.h> + +namespace content { +bool RegisterContentChildProcessServiceDelegate(JNIEnv* env); +} // namespace content + +#endif // CONTENT_APP_ANDROID_CONTENT_CHILD_PROCESS_SERVICE_DELEGATE_H_
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 3ba593b..bdb1b14 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -76,9 +76,12 @@ java_files = [ "java/src/org/chromium/content/app/ChildProcessService.java", + "java/src/org/chromium/content/app/ChildProcessServiceDelegate.java", "java/src/org/chromium/content/app/ChildProcessServiceImpl.java", "java/src/org/chromium/content/app/ChromiumLinkerParams.java", "java/src/org/chromium/content/app/ContentApplication.java", + "java/src/org/chromium/content/app/ContentChildProcessService.java", + "java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java", "java/src/org/chromium/content/app/ContentMain.java", "java/src/org/chromium/content/app/KillChildUncaughtExceptionHandler.java", "java/src/org/chromium/content/app/PrivilegedProcessService.java", @@ -322,6 +325,7 @@ generate_jni("content_jni_headers") { sources = [ "java/src/org/chromium/content/app/ChildProcessServiceImpl.java", + "java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java", "java/src/org/chromium/content/app/ContentMain.java", "java/src/org/chromium/content/browser/AppWebMessagePort.java", "java/src/org/chromium/content/browser/AudioFocusDelegate.java",
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java index 4bce955..5590871 100644 --- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java +++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
@@ -8,8 +8,6 @@ import android.content.Intent; import android.os.IBinder; -import org.chromium.base.annotations.JNINamespace; - /** * This is the base class for child services; the [Sandboxed|Privileged]ProcessService0, 1.. etc * subclasses provide the concrete service entry points, to enable the browser to connect @@ -23,16 +21,21 @@ * and then N entries of the form: * <service android:name="org.chromium.content.app.[Sandboxed|Privileged]ProcessServiceX" * android:process=":[sandboxed|privileged]_processX" /> + * + * Subclasses must also provide a delegate in this class constructor. That delegate is responsible + * for loading native libraries and running the main entry point of the service. */ -@JNINamespace("content") -public class ChildProcessService extends Service { - private final ChildProcessServiceImpl mChildProcessServiceImpl = new ChildProcessServiceImpl(); +public abstract class ChildProcessService extends Service { + private final ChildProcessServiceImpl mChildProcessServiceImpl; + + protected ChildProcessService(ChildProcessServiceDelegate delegate) { + mChildProcessServiceImpl = new ChildProcessServiceImpl(delegate); + } @Override public void onCreate() { super.onCreate(); - mChildProcessServiceImpl.create(getApplicationContext(), - getApplicationContext()); + mChildProcessServiceImpl.create(getApplicationContext(), getApplicationContext()); } @Override
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceDelegate.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceDelegate.java new file mode 100644 index 0000000..7b917f26 --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceDelegate.java
@@ -0,0 +1,51 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.app; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; + +/** + * The interface that embedders should implement to specialize child service creation. + */ +public interface ChildProcessServiceDelegate { + /** Invoked when the service was created. This is the first method invoked on the delegate. */ + void onServiceCreated(); + + /** + * Called when the service is bound. Invoked on a background thread. + * @param intent the intent that started the service. + */ + void onServiceBound(Intent intent); + + /** + * Called once the connection has been setup. Invoked on a background thread. + * @param connectionBundle the bundle pass to the setupConnection call + * @param callback the IBinder provided by the client + */ + void onConnectionSetup(Bundle connectionBundle, IBinder callback); + + /** Called when the service gets destroyed. */ + void onDestroy(); + + /** + * Called when the delegate should load the native library. + * @param hostContext The host context the library should be loaded with (i.e. Chrome). + * @return true if the library was loaded successfully, false otherwise in which case the + * service stops. + */ + boolean loadNativeLibrary(Context hostContext); + + /** Called before the main method is invoked. */ + void onBeforeMain(); + + /** + * The main entry point for the service. This method should block as long as the service should + * be running. + */ + void runMain(); +}
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java index 9d170093..33b72f07 100644 --- a/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java +++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessServiceImpl.java
@@ -6,7 +6,6 @@ import android.content.Context; import android.content.Intent; -import android.graphics.SurfaceTexture; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -14,30 +13,18 @@ import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; -import android.view.Surface; import org.chromium.base.BaseSwitches; import org.chromium.base.CommandLine; import org.chromium.base.ContextUtils; -import org.chromium.base.JNIUtils; import org.chromium.base.Log; -import org.chromium.base.UnguessableToken; -import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.MainDex; import org.chromium.base.annotations.SuppressFBWarnings; -import org.chromium.base.library_loader.LibraryLoader; -import org.chromium.base.library_loader.Linker; -import org.chromium.base.library_loader.ProcessInitException; -import org.chromium.base.process_launcher.ChildProcessCreationParams; import org.chromium.base.process_launcher.FileDescriptorInfo; import org.chromium.base.process_launcher.ICallbackInt; import org.chromium.base.process_launcher.IChildProcessService; import org.chromium.content.browser.ChildProcessConstants; -import org.chromium.content.common.ContentSwitches; -import org.chromium.content.common.IGpuProcessCallback; -import org.chromium.content.common.SurfaceWrapper; -import org.chromium.content_public.common.ContentProcessInfo; import java.util.concurrent.Semaphore; @@ -49,7 +36,6 @@ * It makes it possible for other consumer services (such as WebAPKs) to reuse that logic. */ @JNINamespace("content") -@SuppressWarnings("SynchronizeOnNonFinalField") @MainDex public class ChildProcessServiceImpl { private static final String MAIN_THREAD_NAME = "ChildProcessMain"; @@ -58,6 +44,8 @@ // Only for a check that create is only called once. private static boolean sCreateCalled; + private final ChildProcessServiceDelegate mDelegate; + private final Object mBinderLock = new Object(); private final Object mLibraryInitializedLock = new Object(); @@ -71,22 +59,13 @@ // This is the native "Main" thread for the renderer / utility process. private Thread mMainThread; + // Parameters received via IPC, only accessed while holding the mMainThread monitor. private String[] mCommandLineParams; - private IGpuProcessCallback mGpuCallback; - private int mCpuCount; - private long mCpuFeatures; + // File descriptors that should be registered natively. private FileDescriptorInfo[] mFdInfos; - // Linker-specific parameters for this child process service. - // Only set once in bind(), does not require synchronization. - private ChromiumLinkerParams mLinkerParams; - - // Child library process type. - // Only set once in bind(), does not require synchronization. - private int mLibraryProcessType; - @GuardedBy("mLibraryInitializedLock") private boolean mLibraryInitialized; @@ -104,21 +83,9 @@ private final Semaphore mActivitySemaphore = new Semaphore(1); - public ChildProcessServiceImpl() { + public ChildProcessServiceImpl(ChildProcessServiceDelegate delegate) { KillChildUncaughtExceptionHandler.maybeInstallHandler(); - } - - // Return a Linker instance. If testing, the Linker needs special setup. - private Linker getLinker() { - if (Linker.areTestsEnabled()) { - // For testing, set the Linker implementation and the test runner - // class name to match those used by the parent. - assert mLinkerParams != null; - Linker.setupForTesting( - mLinkerParams.mLinkerImplementationForTesting, - mLinkerParams.mTestRunnerClassNameForTesting); - } - return Linker.getInstance(); + mDelegate = delegate; } // Binder object used by clients for this service. @@ -142,7 +109,7 @@ } @Override - public void setupConnection(Bundle args, ICallbackInt pidCallback, IBinder gpuCallback) + public void setupConnection(Bundle args, ICallbackInt pidCallback, IBinder callback) throws RemoteException { assert mServiceBound; synchronized (mBinderLock) { @@ -154,9 +121,7 @@ } pidCallback.call(Process.myPid()); - mGpuCallback = - gpuCallback != null ? IGpuProcessCallback.Stub.asInterface(gpuCallback) : null; - processConnectionBundle(args); + processConnectionBundle(args, callback); } @Override @@ -196,7 +161,8 @@ throw new RuntimeException("Illegal child process reuse."); } sCreateCalled = true; - ContentProcessInfo.setInChildProcess(true); + + mDelegate.onServiceCreated(); // Initialize the context for the application that owns this ChildProcessServiceImpl object. ContextUtils.initApplicationContext(context); @@ -215,60 +181,21 @@ assert mServiceBound; CommandLine.init(mCommandLineParams); - if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals( - CommandLine.getInstance().getSwitchValue( - ContentSwitches.SWITCH_PROCESS_TYPE))) { - JNIUtils.enableSelectiveJniRegistration(); - } - - Linker linker = null; - boolean requestedSharedRelro = false; - if (Linker.isUsed()) { - assert mLinkerParams != null; - linker = getLinker(); - if (mLinkerParams.mWaitForSharedRelro) { - requestedSharedRelro = true; - linker.initServiceProcess(mLinkerParams.mBaseLoadAddress); - } else { - linker.disableSharedRelros(); - } - } if (CommandLine.getInstance().hasSwitch( BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) { android.os.Debug.waitForDebugger(); } - LibraryLoader libraryLoader = null; - boolean loadAtFixedAddressFailed = false; - boolean isLoaded = false; + boolean nativeLibraryLoaded = false; try { - libraryLoader = LibraryLoader.get(mLibraryProcessType); - libraryLoader.loadNowOverrideApplicationContext(hostContext); - isLoaded = true; - } catch (ProcessInitException e) { - if (requestedSharedRelro) { - Log.w(TAG, "Failed to load native library with shared RELRO, " - + "retrying without"); - loadAtFixedAddressFailed = true; - } else { - Log.e(TAG, "Failed to load native library", e); - } + nativeLibraryLoaded = mDelegate.loadNativeLibrary(hostContext); + } catch (Exception e) { + Log.e(TAG, "Failed to load native library.", e); } - if (!isLoaded && libraryLoader != null && requestedSharedRelro) { - linker.disableSharedRelros(); - try { - libraryLoader.loadNowOverrideApplicationContext(hostContext); - isLoaded = true; - } catch (ProcessInitException e) { - Log.e(TAG, "Failed to load native library on retry", e); - } - } - if (!isLoaded) { + if (!nativeLibraryLoaded) { System.exit(-1); } - libraryLoader.registerRendererProcessHistogram( - requestedSharedRelro, loadAtFixedAddressFailed); - libraryLoader.initialize(); + synchronized (mLibraryInitializedLock) { mLibraryInitialized = true; mLibraryInitializedLock.notifyAll(); @@ -292,16 +219,14 @@ regionSizes[i] = fdInfo.size; } nativeRegisterFileDescriptors(fileIds, fds, regionOffsets, regionSizes); - nativeInitChildProcessImpl(ChildProcessServiceImpl.this, mCpuCount, - mCpuFeatures); + + mDelegate.onBeforeMain(); if (mActivitySemaphore.tryAcquire()) { - ContentMain.start(); + mDelegate.runMain(); nativeExitChildProcess(); } } catch (InterruptedException e) { Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); - } catch (ProcessInitException e) { - Log.w(TAG, "%s startup failed: %s", MAIN_THREAD_NAME, e); } } }, MAIN_THREAD_NAME); @@ -330,9 +255,7 @@ // Ignore } } - // Try to shutdown the MainThread gracefully, but it might not - // have chance to exit normally. - nativeShutdownMainThread(); + mDelegate.onDestroy(); } /* @@ -349,17 +272,14 @@ public IBinder bind(Intent intent, int authorizedCallerUid) { assert !mServiceBound; mAuthorizedCallerUid = authorizedCallerUid; - // mLinkerParams is never used if Linker.isUsed() returns false. See create(). - mLinkerParams = (ChromiumLinkerParams) intent.getParcelableExtra( - ChildProcessConstants.EXTRA_LINKER_PARAMS); - mLibraryProcessType = ChildProcessCreationParams.getLibraryProcessType(intent); mBindToCallerCheck = intent.getBooleanExtra(ChildProcessConstants.EXTRA_BIND_TO_CALLER, false); mServiceBound = true; + mDelegate.onServiceBound(intent); return mBinder; } - private void processConnectionBundle(Bundle bundle) { + private void processConnectionBundle(Bundle bundle, IBinder callback) { // Required to unparcel FileDescriptorInfo. bundle.setClassLoader(mHostClassLoader); synchronized (mMainThread) { @@ -370,9 +290,6 @@ } // We must have received the command line by now assert mCommandLineParams != null; - mCpuCount = bundle.getInt(ChildProcessConstants.EXTRA_CPU_COUNT); - mCpuFeatures = bundle.getLong(ChildProcessConstants.EXTRA_CPU_FEATURES); - assert mCpuCount > 0; Parcelable[] fdInfosAsParcelable = bundle.getParcelableArray(ChildProcessConstants.EXTRA_FILES); if (fdInfosAsParcelable != null) { @@ -381,53 +298,11 @@ mFdInfos = new FileDescriptorInfo[fdInfosAsParcelable.length]; System.arraycopy(fdInfosAsParcelable, 0, mFdInfos, 0, fdInfosAsParcelable.length); } - Bundle sharedRelros = bundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS); - if (sharedRelros != null) { - getLinker().useSharedRelros(sharedRelros); - sharedRelros = null; - } + mDelegate.onConnectionSetup(bundle, callback); mMainThread.notifyAll(); } } - @SuppressWarnings("unused") - @CalledByNative - private void forwardSurfaceTextureForSurfaceRequest( - UnguessableToken requestToken, SurfaceTexture surfaceTexture) { - if (mGpuCallback == null) { - Log.e(TAG, "No callback interface has been provided."); - return; - } - - Surface surface = new Surface(surfaceTexture); - - try { - mGpuCallback.forwardSurfaceForSurfaceRequest(requestToken, surface); - } catch (RemoteException e) { - Log.e(TAG, "Unable to call forwardSurfaceForSurfaceRequest: %s", e); - return; - } finally { - surface.release(); - } - } - - @SuppressWarnings("unused") - @CalledByNative - private Surface getViewSurface(int surfaceId) { - if (mGpuCallback == null) { - Log.e(TAG, "No callback interface has been provided."); - return null; - } - - try { - SurfaceWrapper wrapper = mGpuCallback.getViewSurface(surfaceId); - return wrapper != null ? wrapper.getSurface() : null; - } catch (RemoteException e) { - Log.e(TAG, "Unable to call getViewSurface: %s", e); - return null; - } - } - /** * Helper for registering FileDescriptorInfo objects with GlobalFileDescriptors or * FileDescriptorStore. @@ -438,19 +313,7 @@ int[] id, int[] fd, long[] offset, long[] size); /** - * The main entry point for a child process. This should be called from a new thread since - * it will not return until the child process exits. See child_process_service.{h,cc} - * - * @param serviceImpl The current ChildProcessServiceImpl object. - * renderer. - */ - private static native void nativeInitChildProcessImpl( - ChildProcessServiceImpl serviceImpl, int cpuCount, long cpuFeatures); - - /** * Force the child process to exit. */ private static native void nativeExitChildProcess(); - - private native void nativeShutdownMainThread(); }
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessService.java new file mode 100644 index 0000000..5a0cb86e --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessService.java
@@ -0,0 +1,12 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.app; + +/** Implementation of ChildProcessService that uses the content specific delegate. */ +public class ContentChildProcessService extends ChildProcessService { + public ContentChildProcessService() { + super(new ContentChildProcessServiceDelegate()); + } +}
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java new file mode 100644 index 0000000..afbb488 --- /dev/null +++ b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
@@ -0,0 +1,216 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.content.app; + +import android.content.Context; +import android.content.Intent; +import android.graphics.SurfaceTexture; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.view.Surface; + +import org.chromium.base.CommandLine; +import org.chromium.base.JNIUtils; +import org.chromium.base.Log; +import org.chromium.base.UnguessableToken; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.MainDex; +import org.chromium.base.library_loader.LibraryLoader; +import org.chromium.base.library_loader.Linker; +import org.chromium.base.library_loader.ProcessInitException; +import org.chromium.base.process_launcher.ChildProcessCreationParams; +import org.chromium.content.browser.ChildProcessConstants; +import org.chromium.content.common.ContentSwitches; +import org.chromium.content.common.IGpuProcessCallback; +import org.chromium.content.common.SurfaceWrapper; +import org.chromium.content_public.common.ContentProcessInfo; + +/** + * This implementation of {@link ChildProcessServiceDelegate} loads the native library potentially + * using the custom linker, provides access to view surfaces. + */ +@JNINamespace("content") +@MainDex +public class ContentChildProcessServiceDelegate implements ChildProcessServiceDelegate { + private static final String TAG = "ContentCPSDelegate"; + + // Linker-specific parameters for this child process service. + private ChromiumLinkerParams mLinkerParams; + + // Child library process type. + private int mLibraryProcessType; + + private IGpuProcessCallback mGpuCallback; + + private int mCpuCount; + private long mCpuFeatures; + + @Override + public void onServiceCreated() { + ContentProcessInfo.setInChildProcess(true); + } + + @Override + public void onServiceBound(Intent intent) { + mLinkerParams = (ChromiumLinkerParams) intent.getParcelableExtra( + ChildProcessConstants.EXTRA_LINKER_PARAMS); + mLibraryProcessType = ChildProcessCreationParams.getLibraryProcessType(intent); + } + + @Override + public void onConnectionSetup(Bundle connectionBundle, IBinder callback) { + mGpuCallback = callback != null ? IGpuProcessCallback.Stub.asInterface(callback) : null; + + mCpuCount = connectionBundle.getInt(ChildProcessConstants.EXTRA_CPU_COUNT); + mCpuFeatures = connectionBundle.getLong(ChildProcessConstants.EXTRA_CPU_FEATURES); + assert mCpuCount > 0; + + Bundle sharedRelros = connectionBundle.getBundle(Linker.EXTRA_LINKER_SHARED_RELROS); + if (sharedRelros != null) { + getLinker().useSharedRelros(sharedRelros); + sharedRelros = null; + } + } + + @Override + public boolean loadNativeLibrary(Context hostContext) { + String processType = + CommandLine.getInstance().getSwitchValue(ContentSwitches.SWITCH_PROCESS_TYPE); + if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { + JNIUtils.enableSelectiveJniRegistration(); + } + + Linker linker = null; + boolean requestedSharedRelro = false; + if (Linker.isUsed()) { + assert mLinkerParams != null; + linker = getLinker(); + if (mLinkerParams.mWaitForSharedRelro) { + requestedSharedRelro = true; + linker.initServiceProcess(mLinkerParams.mBaseLoadAddress); + } else { + linker.disableSharedRelros(); + } + } + LibraryLoader libraryLoader = null; + boolean isLoaded = false; + boolean loadAtFixedAddressFailed = false; + try { + libraryLoader = LibraryLoader.get(mLibraryProcessType); + libraryLoader.loadNowOverrideApplicationContext(hostContext); + isLoaded = true; + } catch (ProcessInitException e) { + if (requestedSharedRelro) { + Log.w(TAG, + "Failed to load native library with shared RELRO, " + + "retrying without"); + loadAtFixedAddressFailed = true; + } else { + Log.e(TAG, "Failed to load native library", e); + } + } + if (!isLoaded && libraryLoader != null && requestedSharedRelro) { + linker.disableSharedRelros(); + try { + libraryLoader.loadNowOverrideApplicationContext(hostContext); + isLoaded = true; + } catch (ProcessInitException e) { + Log.e(TAG, "Failed to load native library on retry", e); + } + } + if (!isLoaded) { + return false; + } + libraryLoader.registerRendererProcessHistogram( + requestedSharedRelro, loadAtFixedAddressFailed); + try { + libraryLoader.initialize(); + } catch (ProcessInitException e) { + Log.w(TAG, "startup failed: %s", e); + return false; + } + return true; + } + + @Override + public void onBeforeMain() { + nativeInitChildProcess(mCpuCount, mCpuFeatures); + } + + @Override + public void onDestroy() { + // Try to shutdown the MainThread gracefully, but it might not have a + // chance to exit normally. + nativeShutdownMainThread(); + } + + @Override + public void runMain() { + ContentMain.start(); + } + + // Return a Linker instance. If testing, the Linker needs special setup. + private Linker getLinker() { + if (Linker.areTestsEnabled()) { + // For testing, set the Linker implementation and the test runner + // class name to match those used by the parent. + assert mLinkerParams != null; + Linker.setupForTesting(mLinkerParams.mLinkerImplementationForTesting, + mLinkerParams.mTestRunnerClassNameForTesting); + } + return Linker.getInstance(); + } + + @SuppressWarnings("unused") + @CalledByNative + private void forwardSurfaceTextureForSurfaceRequest( + UnguessableToken requestToken, SurfaceTexture surfaceTexture) { + if (mGpuCallback == null) { + Log.e(TAG, "No callback interface has been provided."); + return; + } + + Surface surface = new Surface(surfaceTexture); + + try { + mGpuCallback.forwardSurfaceForSurfaceRequest(requestToken, surface); + } catch (RemoteException e) { + Log.e(TAG, "Unable to call forwardSurfaceForSurfaceRequest: %s", e); + return; + } finally { + surface.release(); + } + } + + @SuppressWarnings("unused") + @CalledByNative + private Surface getViewSurface(int surfaceId) { + if (mGpuCallback == null) { + Log.e(TAG, "No callback interface has been provided."); + return null; + } + + try { + SurfaceWrapper wrapper = mGpuCallback.getViewSurface(surfaceId); + return wrapper != null ? wrapper.getSurface() : null; + } catch (RemoteException e) { + Log.e(TAG, "Unable to call getViewSurface: %s", e); + return null; + } + } + + /** + * Initializes the native parts of the service. + * + * @param serviceImpl This ChildProcessServiceImpl object. + * @param cpuCount The number of CPUs. + * @param cpuFeatures The CPU features. + */ + private native void nativeInitChildProcess(int cpuCount, long cpuFeatures); + + private native void nativeShutdownMainThread(); +}
diff --git a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService.java b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService.java index 5cff15b..a7c96d35 100644 --- a/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService.java +++ b/content/public/android/java/src/org/chromium/content/app/PrivilegedProcessService.java
@@ -8,6 +8,4 @@ * Privileged (unsandboxed) Services inherit from this class. We enforce the * privileged/sandboxed distinction by type-checking objects against this parent class. */ -public class PrivilegedProcessService extends ChildProcessService { - -} +public class PrivilegedProcessService extends ContentChildProcessService {}
diff --git a/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java b/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java index 3a9830f..b7ad8b36 100644 --- a/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java +++ b/content/public/android/java/src/org/chromium/content/app/SandboxedProcessService.java
@@ -8,6 +8,4 @@ * Sandboxed Services inherit from this class. We enforce the privileged/sandboxed * distinction by type-checking objects against this parent class. */ -public class SandboxedProcessService extends ChildProcessService { - -} +public class SandboxedProcessService extends ContentChildProcessService {}
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py index 97e626c..7250836 100644 --- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -71,6 +71,8 @@ self.Fail('conformance2/rendering/' + 'draw-with-integer-texture-base-level.html', ['win', 'nvidia', 'd3d11'], bug=679639) + self.Flaky('deqp/functional/gles3/textureshadow/*.html', + ['win', 'nvidia', 'd3d11'], bug=735464) # Win10 / NVIDIA Quadro P400 / D3D11 flaky failures self.Fail('deqp/functional/gles3/transformfeedback/' +
diff --git a/headless/public/util/testing/generic_url_request_mocks.cc b/headless/public/util/testing/generic_url_request_mocks.cc index 54f1ed9..a4053dc 100644 --- a/headless/public/util/testing/generic_url_request_mocks.cc +++ b/headless/public/util/testing/generic_url_request_mocks.cc
@@ -84,6 +84,14 @@ CHECK(false); } +void MockCookieStore::SetCanonicalCookieAsync( + std::unique_ptr<net::CanonicalCookie> cookie, + bool secure_source, + bool can_modify_httponly, + const SetCookiesCallback& callback) { + CHECK(false); +} + void MockCookieStore::GetCookiesWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/headless/public/util/testing/generic_url_request_mocks.h b/headless/public/util/testing/generic_url_request_mocks.h index 94e0e5c0..98f5e9d 100644 --- a/headless/public/util/testing/generic_url_request_mocks.h +++ b/headless/public/util/testing/generic_url_request_mocks.h
@@ -74,6 +74,11 @@ net::CookiePriority priority, const SetCookiesCallback& callback) override; + void SetCanonicalCookieAsync(std::unique_ptr<net::CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) override; + void GetCookiesWithOptionsAsync(const GURL& url, const net::CookieOptions& options, const GetCookiesCallback& callback) override;
diff --git a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc index 345b7a2..66c213b 100644 --- a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc +++ b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc
@@ -119,14 +119,21 @@ } std::vector<base::string16> AutocompleteProviderClientImpl::GetBuiltinURLs() { - // iOS does not supports BuiltinProvider. - return std::vector<base::string16>(); + std::vector<std::string> chrome_builtins( + kChromeHostURLs, kChromeHostURLs + kNumberOfChromeHostURLs); + std::sort(chrome_builtins.begin(), chrome_builtins.end()); + + std::vector<base::string16> builtins; + for (auto& url : chrome_builtins) { + builtins.push_back(base::ASCIIToUTF16(url)); + } + return builtins; } std::vector<base::string16> AutocompleteProviderClientImpl::GetBuiltinsToProvideAsUserTypes() { - // iOS does not supports BuiltinProvider. - return std::vector<base::string16>(); + return {base::ASCIIToUTF16(kChromeUIChromeURLsURL), + base::ASCIIToUTF16(kChromeUIVersionURL)}; } bool AutocompleteProviderClientImpl::IsOffTheRecord() const {
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter.h b/ios/chrome/browser/ui/dialogs/dialog_presenter.h index b3e7a424..33d38b8 100644 --- a/ios/chrome/browser/ui/dialogs/dialog_presenter.h +++ b/ios/chrome/browser/ui/dialogs/dialog_presenter.h
@@ -86,8 +86,8 @@ // The dialog currently being shown. @property(nonatomic, readonly) AlertCoordinator* presentedDialogCoordinator; -// Called when a button in |dialog| is tapped. -- (void)buttonWasTappedForCoordinator:(AlertCoordinator*)coordinator; +// Called when |coordinator| is stopped. +- (void)dialogCoordinatorWasStopped:(AlertCoordinator*)coordinator; @end
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter.mm index 1d7094f..05749db 100644 --- a/ios/chrome/browser/ui/dialogs/dialog_presenter.mm +++ b/ios/chrome/browser/ui/dialogs/dialog_presenter.mm
@@ -73,8 +73,8 @@ // Shows the dialog associated with the next context in |contextQueue|. - (void)showNextDialog; -// Called when a button in |coordinator| is tapped. -- (void)buttonWasTappedForCoordinator:(AlertCoordinator*)coordinator; +// Called when |coordinator| is stopped. +- (void)dialogCoordinatorWasStopped:(AlertCoordinator*)coordinator; // Adds buttons to |alertCoordinator|. A confirmation button with |label| as // the text will be added for |confirmAction|, and a cancel button will be added @@ -153,7 +153,7 @@ ProceduralBlock OKHandler = ^{ if (completionHandler) completionHandler(); - [weakSelf buttonWasTappedForCoordinator:weakCoordinator]; + [weakSelf dialogCoordinatorWasStopped:weakCoordinator]; }; // Add button. @@ -312,15 +312,24 @@ } - (void)cancelDialogForWebState:(web::WebState*)webState { - DCHECK_NE(webState, self.presentedDialogWebState); - AlertCoordinator* dialogToCancel = _dialogCoordinatorsForWebStates[webState]; - if (dialogToCancel) { + BOOL cancelingPresentedDialog = webState == self.presentedDialogWebState; + AlertCoordinator* dialogToCancel = + cancelingPresentedDialog ? self.presentedDialogCoordinator + : _dialogCoordinatorsForWebStates[webState]; + DCHECK(!cancelingPresentedDialog || dialogToCancel); + [dialogToCancel executeCancelHandler]; + [dialogToCancel stop]; + + if (cancelingPresentedDialog) { + DCHECK(_dialogCoordinatorsForWebStates[webState] == nil); + // Simulate a button tap to trigger showing the next dialog. + [self dialogCoordinatorWasStopped:dialogToCancel]; + } else if (dialogToCancel) { + // Clean up queued state. auto it = std::find(_queuedWebStates.begin(), _queuedWebStates.end(), webState); DCHECK(it != _queuedWebStates.end()); _queuedWebStates.erase(it); - [dialogToCancel executeCancelHandler]; - [dialogToCancel stop]; _dialogCoordinatorsForWebStates.erase(webState); } } @@ -386,7 +395,7 @@ [self.presentedDialogCoordinator start]; } -- (void)buttonWasTappedForCoordinator:(AlertCoordinator*)coordinator { +- (void)dialogCoordinatorWasStopped:(AlertCoordinator*)coordinator { if (coordinator != self.presentedDialogCoordinator) return; self.presentedDialogWebState = nil; @@ -407,13 +416,13 @@ ProceduralBlock confirmHandler = ^{ if (confirmAction) confirmAction(); - [weakSelf buttonWasTappedForCoordinator:weakCoordinator]; + [weakSelf dialogCoordinatorWasStopped:weakCoordinator]; }; ProceduralBlock cancelHandler = ^{ if (cancelAction) cancelAction(); - [weakSelf buttonWasTappedForCoordinator:weakCoordinator]; + [weakSelf dialogCoordinatorWasStopped:weakCoordinator]; }; // Add buttons. @@ -485,12 +494,12 @@ if (!strongSelf) return; DialogBlockingOptionSelected([strongSelf presentedDialogWebState]); - [strongSelf buttonWasTappedForCoordinator:weakCoordinator]; + [strongSelf dialogCoordinatorWasStopped:weakCoordinator]; }; ProceduralBlock cancelHandler = ^{ if (cancelAction) cancelAction(); - [weakSelf buttonWasTappedForCoordinator:weakCoordinator]; + [weakSelf dialogCoordinatorWasStopped:weakCoordinator]; }; NSString* blockingOptionTitle = l10n_util::GetNSString(IDS_IOS_JAVA_SCRIPT_DIALOG_BLOCKING_BUTTON_TEXT);
diff --git a/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm b/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm index 2a566bf9..2bd6df4 100644 --- a/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm +++ b/ios/chrome/browser/ui/dialogs/dialog_presenter_unittest.mm
@@ -120,7 +120,7 @@ // showing the dialog for |webState2|. [presenter().presentedDialogCoordinator stop]; [presenter() - buttonWasTappedForCoordinator:presenter().presentedDialogCoordinator]; + dialogCoordinatorWasStopped:presenter().presentedDialogCoordinator]; EXPECT_EQ(2U, delegate().presentedWebStates.size()); EXPECT_EQ(&webState1, delegate().presentedWebStates.front()); EXPECT_EQ(&webState2, delegate().presentedWebStates.back());
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm index c6708818..77865e8 100644 --- a/ios/chrome/browser/ui/payments/address_edit_coordinator.mm +++ b/ios/chrome/browser/ui/payments/address_edit_coordinator.mm
@@ -9,6 +9,7 @@ #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_constants.h" @@ -147,8 +148,10 @@ autofill::kSettingsOrigin); for (EditorField* field in fields) { - address.SetRawInfo(AutofillTypeFromAutofillUIType(field.autofillUIType), - base::SysNSStringToUTF16(field.value)); + address.SetInfo(autofill::AutofillType( + AutofillTypeFromAutofillUIType(field.autofillUIType)), + base::SysNSStringToUTF16(field.value), + GetApplicationContext()->GetApplicationLocale()); } if (!self.address) {
diff --git a/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm index f46eaf9..7d39c51c 100644 --- a/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/address_edit_coordinator_unittest.mm
@@ -11,6 +11,7 @@ #include "base/test/ios/wait_util.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/country_names.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/autofill/core/browser/test_region_data_loader.h" #include "components/payments/core/payments_profile_comparator.h" @@ -102,6 +103,7 @@ protected: PaymentRequestAddressEditCoordinatorTest() : pref_service_(autofill::test::PrefServiceForTesting()) { + autofill::CountryNames::SetLocaleString("en-US"); personal_data_manager_.SetTestingPrefService(pref_service_.get()); payment_request_ = base::MakeUnique<MockTestPaymentRequest>( payment_request_test_util::CreateTestWebPaymentRequest(), @@ -193,12 +195,12 @@ // Expect an autofill profile to be added to the PaymentRequest. EXPECT_CALL(*payment_request_, AddAutofillProfile(ProfileMatches("John Doe", "CA" /* Canada */, - "Quebec", "16502111111"))) + "Quebec", "1 650-211-1111"))) .Times(1); // Expect an autofill profile to be added to the PersonalDataManager. EXPECT_CALL(personal_data_manager_, AddProfile(ProfileMatches("John Doe", "CA" /* Canada */, "Quebec", - "16502111111"))) + "1 650-211-1111"))) .Times(1); // No autofill profile should get updated in the PersonalDataManager. EXPECT_CALL(personal_data_manager_, UpdateProfile(_)).Times(0); @@ -261,12 +263,12 @@ // Expect an autofill profile to be updated in the PersonalDataManager. EXPECT_CALL(personal_data_manager_, UpdateProfile(ProfileMatches("John Doe", "CA" /* Canada */, - "Quebec", "16502111111"))) + "Quebec", "1 650-211-1111"))) .Times(1); // Expect an autofill profile to be invalidated in PaymentsProfileComparator. EXPECT_CALL(*profile_comparator_, Invalidate(ProfileMatches("John Doe", "CA" /* Canada */, "Quebec", - "16502111111"))) + "1 650-211-1111"))) .Times(1); // Call the controller delegate method.
diff --git a/ios/chrome/browser/ui/payments/address_edit_mediator.mm b/ios/chrome/browser/ui/payments/address_edit_mediator.mm index 19a2834e..2dbc06b4 100644 --- a/ios/chrome/browser/ui/payments/address_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/address_edit_mediator.mm
@@ -21,6 +21,7 @@ #include "components/autofill/core/browser/country_combobox_model.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/personal_data_manager.h" +#include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" @@ -119,6 +120,15 @@ return NO; } +- (void)formatValueForEditorField:(EditorField*)field { + if (field.autofillUIType == AutofillUITypeProfileHomePhoneWholeNumber) { + field.value = + base::SysUTF8ToNSString(payments::data_util::FormatPhoneForDisplay( + base::SysNSStringToUTF8(field.value), + base::SysNSStringToUTF8(self.selectedCountryCode))); + } +} + - (UIImage*)iconIdentifyingEditorField:(EditorField*)field { return nil; } @@ -299,8 +309,12 @@ EditorField* field = self.fieldsMap[phoneNumberFieldKey]; if (!field) { NSString* value = - [self fieldValueFromProfile:self.address - fieldType:autofill::PHONE_HOME_WHOLE_NUMBER]; + self.address + ? base::SysUTF16ToNSString( + payments::data_util::GetFormattedPhoneNumberForDisplay( + *self.address, + GetApplicationContext()->GetApplicationLocale())) + : nil; field = [[EditorField alloc] initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber fieldType:EditorFieldTypeTextField
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm index fce47e0..aa06914 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator.mm
@@ -9,6 +9,7 @@ #include "base/strings/sys_string_conversions.h" #include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_constants.h" @@ -136,8 +137,10 @@ autofill::kSettingsOrigin); for (EditorField* field in fields) { - profile.SetRawInfo(AutofillTypeFromAutofillUIType(field.autofillUIType), - base::SysNSStringToUTF16(field.value)); + profile.SetInfo(autofill::AutofillType( + AutofillTypeFromAutofillUIType(field.autofillUIType)), + base::SysNSStringToUTF16(field.value), + GetApplicationContext()->GetApplicationLocale()); } if (!self.profile) {
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm index 2244182..791d0e1 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_coordinator_unittest.mm
@@ -184,12 +184,12 @@ // Expect an autofill profile to be added to the PaymentRequest. EXPECT_CALL(*payment_request_, AddAutofillProfile( - ProfileMatches("John Doe", "john@doe.com", "16502111111"))) + ProfileMatches("John Doe", "john@doe.com", "1 650-211-1111"))) .Times(1); // Expect an autofill profile to be added to the PersonalDataManager. EXPECT_CALL( personal_data_manager_, - AddProfile(ProfileMatches("John Doe", "john@doe.com", "16502111111"))) + AddProfile(ProfileMatches("John Doe", "john@doe.com", "1 650-211-1111"))) .Times(1); // No autofill profile should get updated in the PersonalDataManager. EXPECT_CALL(personal_data_manager_, UpdateProfile(_)).Times(0); @@ -250,14 +250,14 @@ // No autofill profile should get added to the PersonalDataManager. EXPECT_CALL(personal_data_manager_, AddProfile(_)).Times(0); // Expect an autofill profile to be updated in the PersonalDataManager. - EXPECT_CALL( - personal_data_manager_, - UpdateProfile(ProfileMatches("John Doe", "john@doe.com", "16502111111"))) + EXPECT_CALL(personal_data_manager_, + UpdateProfile( + ProfileMatches("John Doe", "john@doe.com", "1 650-211-1111"))) .Times(1); // Expect an autofill profile to be invalidated in PaymentsProfileComparator. EXPECT_CALL( *profile_comparator_, - Invalidate(ProfileMatches("John Doe", "john@doe.com", "16502111111"))) + Invalidate(ProfileMatches("John Doe", "john@doe.com", "1 650-211-1111"))) .Times(1); // Call the controller delegate method.
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm index 6444603..98e20b8 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator.mm
@@ -6,9 +6,11 @@ #include "base/logging.h" #include "base/strings/sys_string_conversions.h" +#include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/field_types.h" +#include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" @@ -74,6 +76,17 @@ return NO; } +- (void)formatValueForEditorField:(EditorField*)field { + if (field.autofillUIType == AutofillUITypeProfileHomePhoneWholeNumber) { + const std::string countryCode = + autofill::AutofillCountry::CountryCodeForLocale( + GetApplicationContext()->GetApplicationLocale()); + field.value = + base::SysUTF8ToNSString(payments::data_util::FormatPhoneForDisplay( + base::SysNSStringToUTF8(field.value), countryCode)); + } +} + - (UIImage*)iconIdentifyingEditorField:(EditorField*)field { return nil; } @@ -99,8 +112,12 @@ if (_paymentRequest->request_payer_phone()) { NSString* phone = - [self fieldValueFromProfile:self.profile - fieldType:autofill::PHONE_HOME_WHOLE_NUMBER]; + self.profile + ? base::SysUTF16ToNSString( + payments::data_util::GetFormattedPhoneNumberForDisplay( + *self.profile, + GetApplicationContext()->GetApplicationLocale())) + : nil; EditorField* phoneField = [[EditorField alloc] initWithAutofillUIType:AutofillUITypeProfileHomePhoneWholeNumber fieldType:EditorFieldTypeTextField
diff --git a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm index 639fbed..9b2d54d 100644 --- a/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm +++ b/ios/chrome/browser/ui/payments/contact_info_edit_mediator_unittest.mm
@@ -105,7 +105,7 @@ field = fields[1]; EXPECT_TRUE([field isKindOfClass:[EditorField class]]); editor_field = base::mac::ObjCCastStrict<EditorField>(field); - EXPECT_TRUE([editor_field.value isEqualToString:@"16502111111"]); + EXPECT_TRUE([editor_field.value isEqualToString:@"+1 650-211-1111"]); field = fields[2]; EXPECT_TRUE([field isKindOfClass:[EditorField class]]);
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm index 63f1c2e4..4fceb55 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_coordinator.mm
@@ -8,12 +8,14 @@ #include "base/logging.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_constants.h" #import "components/autofill/ios/browser/credit_card_util.h" #include "components/strings/grit/components_strings.h" +#include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" #import "ios/chrome/browser/ui/autofill/autofill_ui_type_util.h" #import "ios/chrome/browser/ui/payments/credit_card_edit_mediator.h" @@ -187,9 +189,10 @@ } else if (field.autofillUIType == AutofillUITypeCreditCardBillingAddress) { creditCard.set_billing_address_id(base::SysNSStringToUTF8(field.value)); } else { - creditCard.SetRawInfo( - AutofillTypeFromAutofillUIType(field.autofillUIType), - base::SysNSStringToUTF16(field.value)); + creditCard.SetInfo(autofill::AutofillType(AutofillTypeFromAutofillUIType( + field.autofillUIType)), + base::SysNSStringToUTF16(field.value), + GetApplicationContext()->GetApplicationLocale()); } }
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm index 3630dd38..2f82561 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
@@ -10,6 +10,7 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/personal_data_manager.h" #import "components/autofill/ios/browser/credit_card_util.h" +#include "components/payments/core/payment_request_data_util.h" #include "components/strings/grit/components_strings.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/payments/payment_request.h" @@ -153,6 +154,14 @@ return !_creditCard || autofill::IsCreditCardLocal(*_creditCard); } +- (void)formatValueForEditorField:(EditorField*)field { + if (field.autofillUIType == AutofillUITypeCreditCardNumber) { + field.value = base::SysUTF16ToNSString( + payments::data_util::FormatCardNumberForDisplay( + base::SysNSStringToUTF16(field.value))); + } +} + - (UIImage*)iconIdentifyingEditorField:(EditorField*)field { // Early return if the field is not the credit card number field. if (field.autofillUIType != AutofillUITypeCreditCardNumber) @@ -253,7 +262,10 @@ // Credit Card number field. NSString* creditCardNumber = - _creditCard ? base::SysUTF16ToNSString(_creditCard->number()) : nil; + _creditCard ? base::SysUTF16ToNSString( + payments::data_util::FormatCardNumberForDisplay( + _creditCard->number())) + : nil; fieldKey = [NSNumber numberWithInt:AutofillUITypeCreditCardNumber]; EditorField* creditCardNumberField = self.fieldsMap[fieldKey]; if (!creditCardNumberField) {
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm index bd63f8c..1a134d3 100644 --- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm +++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller.mm
@@ -384,7 +384,7 @@ } // This method is called as the text is being typed in, pasted, or deleted. Asks -// the delegate if the text should be changed. Should always return YES. During +// the delegate if the text should be changed. Should always return NO. During // typing/pasting text, |newText| contains one or more new characters. When user // deletes text, |newText| is empty. |range| is the range of characters to be // replaced. @@ -401,24 +401,29 @@ AutofillEditItem* item = base::mac::ObjCCastStrict<AutofillEditItem>( [model itemAtIndexPath:indexPath]); - // Find the respective editor field and update its value. + // Find the respective editor field and update its value to the proposed text. NSNumber* key = [NSNumber numberWithInt:sectionIdentifier]; EditorField* field = self.fieldsMap[key]; DCHECK(field); - // Obtain the text being typed. - NSString* updatedText = - [textField.text stringByReplacingCharactersInRange:range - withString:newText]; - field.value = updatedText; + field.value = [textField.text stringByReplacingCharactersInRange:range + withString:newText]; + + // Format the proposed text if necessary. + [_dataSource formatValueForEditorField:field]; + + // Since this method is returning NO, update the text field's value now. + textField.text = field.value; // Get the icon that identifies the field value and reload the cell if the // icon changes. UIImage* oldIcon = item.identifyingIcon; item.identifyingIcon = [_dataSource iconIdentifyingEditorField:field]; - if (item.identifyingIcon != oldIcon) + if (item.identifyingIcon != oldIcon) { + item.textFieldValue = field.value; [self reconfigureCellsForItems:@[ item ]]; + } - return YES; + return NO; } #pragma mark - AutofillEditAccessoryDelegate
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h index d3bc084..9393b6e 100644 --- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h +++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_data_source.h
@@ -30,6 +30,9 @@ // Returns whether the header item should hide its background. - (BOOL)shouldHideBackgroundForHeaderItem; +// Formats the editor field value, if necessary. +- (void)formatValueForEditorField:(EditorField*)field; + // Returns an icon that identifies |field| or its current value. May be nil. - (UIImage*)iconIdentifyingEditorField:(EditorField*)field;
diff --git a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm index 21524ff4..b2c19ac 100644 --- a/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/payments/payment_request_edit_view_controller_unittest.mm
@@ -42,6 +42,9 @@ return NO; } +- (void)formatValueForEditorField:(EditorField*)field { +} + - (UIImage*)iconIdentifyingEditorField:(EditorField*)field { return nil; }
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h index 85671c9..68ac20f 100644 --- a/ios/net/cookies/cookie_store_ios.h +++ b/ios/net/cookies/cookie_store_ios.h
@@ -89,6 +89,10 @@ CookieSameSite same_site, CookiePriority priority, const SetCookiesCallback& callback) override; + void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) override; void GetCookiesWithOptionsAsync(const GURL& url, const net::CookieOptions& options, const GetCookiesCallback& callback) override;
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm index 2ea0715..f24def3 100644 --- a/ios/net/cookies/cookie_store_ios.mm +++ b/ios/net/cookies/cookie_store_ios.mm
@@ -25,6 +25,7 @@ #include "base/task_runner_util.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "ios/net/cookies/cookie_creation_time_manager.h" #include "ios/net/cookies/cookie_store_ios_client.h" #include "ios/net/cookies/system_cookie_util.h" @@ -404,8 +405,6 @@ cookie_path = std::string(canon_path.data() + canon_path_component.begin, canon_path_component.len); - // First create a CanonicalCookie, to normalize the arguments, - // particularly domain and path, and perform validation. std::unique_ptr<net::CanonicalCookie> canonical_cookie = base::MakeUnique<net::CanonicalCookie>( name, value, cookie_domain, cookie_path, creation_time, @@ -428,6 +427,40 @@ callback.Run(success); } +void CookieStoreIOS::SetCanonicalCookieAsync( + std::unique_ptr<net::CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) { + DCHECK(cookie->IsCanonical()); + // The exclude_httponly() option would only be used by a javascript + // engine. + DCHECK(modify_http_only); + + if (cookie->IsSecure() && !secure_source) { + if (!callback.is_null()) + callback.Run(false); + return; + } + + NSHTTPCookie* ns_cookie = SystemCookieFromCanonicalCookie(*cookie.get()); + + if (ns_cookie != nil) { + [system_store_ setCookie:ns_cookie]; + creation_time_manager_->SetCreationTime( + ns_cookie, + creation_time_manager_->MakeUniqueCreationTime( + cookie->CreationDate().is_null() ? base::Time::Now() + : cookie->CreationDate())); + if (!callback.is_null()) + callback.Run(true); + return; + } + + if (!callback.is_null()) + callback.Run(false); +} + void CookieStoreIOS::GetCookiesWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/ios/net/cookies/cookie_store_ios_persistent.h b/ios/net/cookies/cookie_store_ios_persistent.h index ce3bd470..18dba8fb 100644 --- a/ios/net/cookies/cookie_store_ios_persistent.h +++ b/ios/net/cookies/cookie_store_ios_persistent.h
@@ -53,6 +53,10 @@ CookieSameSite same_site, CookiePriority priority, const SetCookiesCallback& callback) override; + void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) override; void GetCookiesWithOptionsAsync(const GURL& url, const net::CookieOptions& options, const GetCookiesCallback& callback) override;
diff --git a/ios/net/cookies/cookie_store_ios_persistent.mm b/ios/net/cookies/cookie_store_ios_persistent.mm index a0ed1ada..9a8527c 100644 --- a/ios/net/cookies/cookie_store_ios_persistent.mm +++ b/ios/net/cookies/cookie_store_ios_persistent.mm
@@ -57,6 +57,18 @@ WrapSetCallback(callback)); } +void CookieStoreIOSPersistent::SetCanonicalCookieAsync( + std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) { + DCHECK(thread_checker().CalledOnValidThread()); + + cookie_monster()->SetCanonicalCookieAsync(std::move(cookie), secure_source, + modify_http_only, + WrapSetCallback(callback)); +} + void CookieStoreIOSPersistent::GetCookiesWithOptionsAsync( const GURL& url, const net::CookieOptions& options,
diff --git a/ios/showcase/payments/sc_payments_editor_coordinator.mm b/ios/showcase/payments/sc_payments_editor_coordinator.mm index c1db284..2f451a10 100644 --- a/ios/showcase/payments/sc_payments_editor_coordinator.mm +++ b/ios/showcase/payments/sc_payments_editor_coordinator.mm
@@ -105,6 +105,9 @@ return NO; } +- (void)formatValueForEditorField:(EditorField*)field { +} + - (UIImage*)iconIdentifyingEditorField:(EditorField*)field { return nil; }
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index 7da17ca..c3996e8 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -57,6 +57,8 @@ "navigation/crw_session_controller+private_constructors.h", "navigation/crw_session_controller.h", "navigation/crw_session_controller.mm", + "navigation/legacy_navigation_manager_impl.h", + "navigation/legacy_navigation_manager_impl.mm", "navigation/navigation_item_impl.h", "navigation/navigation_item_impl.mm", "navigation/navigation_item_impl_list.h", @@ -65,7 +67,6 @@ "navigation/navigation_item_storage_builder.mm", "navigation/navigation_manager_delegate.h", "navigation/navigation_manager_impl.h", - "navigation/navigation_manager_impl.mm", "navigation/navigation_manager_util.h", "navigation/navigation_manager_util.mm", "navigation/nscoder_util.h",
diff --git a/ios/web/navigation/legacy_navigation_manager_impl.h b/ios/web/navigation/legacy_navigation_manager_impl.h new file mode 100644 index 0000000..04951cf --- /dev/null +++ b/ios/web/navigation/legacy_navigation_manager_impl.h
@@ -0,0 +1,125 @@ +// Copyright 2017 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 IOS_WEB_NAVIGATION_LEGACY_NAVIGATION_MANAGER_IMPL_H_ +#define IOS_WEB_NAVIGATION_LEGACY_NAVIGATION_MANAGER_IMPL_H_ + +#include <stddef.h> + +#include <memory> +#include <vector> + +#import "base/mac/scoped_nsobject.h" +#include "base/macros.h" +#import "ios/web/navigation/navigation_manager_impl.h" +#import "ios/web/public/navigation_item_list.h" +#include "ios/web/public/reload_type.h" +#include "ui/base/page_transition_types.h" +#include "url/gurl.h" + +@class CRWSessionController; + +namespace web { +class BrowserState; +class NavigationItem; +struct Referrer; +class NavigationManagerDelegate; +class SessionStorageBuilder; + +// Implementation of NavigationManagerImpl. +class LegacyNavigationManagerImpl : public NavigationManagerImpl { + public: + LegacyNavigationManagerImpl(); + ~LegacyNavigationManagerImpl() override; + + // NavigationManagerImpl: + void SetDelegate(NavigationManagerDelegate* delegate) override; + void SetBrowserState(BrowserState* browser_state) override; + void SetSessionController(CRWSessionController* session_controller) override; + void InitializeSession() override; + void ReplaceSessionHistory(std::vector<std::unique_ptr<NavigationItem>> items, + int current_index) override; + void OnNavigationItemsPruned(size_t pruned_item_count) override; + void OnNavigationItemChanged() override; + void OnNavigationItemCommitted() override; + CRWSessionController* GetSessionController() const override; + void AddTransientItem(const GURL& url) override; + void AddPendingItem( + const GURL& url, + const web::Referrer& referrer, + ui::PageTransition navigation_type, + NavigationInitiationType initiation_type, + UserAgentOverrideOption user_agent_override_option) override; + void CommitPendingItem() override; + std::unique_ptr<std::vector<BrowserURLRewriter::URLRewriter>> + GetTransientURLRewriters() override; + void RemoveTransientURLRewriters() override; + int GetIndexForOffset(int offset) const override; + + // NavigationManager: + BrowserState* GetBrowserState() const override; + WebState* GetWebState() const override; + NavigationItem* GetVisibleItem() const override; + NavigationItem* GetLastCommittedItem() const override; + NavigationItem* GetPendingItem() const override; + NavigationItem* GetTransientItem() const override; + void DiscardNonCommittedItems() override; + void LoadURLWithParams(const NavigationManager::WebLoadParams&) override; + void AddTransientURLRewriter( + BrowserURLRewriter::URLRewriter rewriter) override; + int GetItemCount() const override; + NavigationItem* GetItemAtIndex(size_t index) const override; + int GetIndexOfItem(const NavigationItem* item) const override; + int GetPendingItemIndex() const override; + int GetLastCommittedItemIndex() const override; + bool RemoveItemAtIndex(int index) override; + bool CanGoBack() const override; + bool CanGoForward() const override; + bool CanGoToOffset(int offset) const override; + void GoBack() override; + void GoForward() override; + void GoToIndex(int index) override; + void Reload(ReloadType reload_type, bool check_for_reposts) override; + NavigationItemList GetBackwardItems() const override; + NavigationItemList GetForwardItems() const override; + void CopyStateFromAndPrune(const NavigationManager* source) override; + bool CanPruneAllButLastCommittedItem() const override; + + private: + // The SessionStorageBuilder functions require access to private variables of + // NavigationManagerImpl. + friend SessionStorageBuilder; + + // NavigationManagerImpl methods used by SessionStorageBuilder. + NavigationItemImpl* GetNavigationItemImplAtIndex(size_t index) const override; + size_t GetPreviousItemIndex() const override; + + // Returns true if the PageTransition for the underlying navigation item at + // |index| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK. + bool IsRedirectItemAtIndex(int index) const; + + // Returns the most recent NavigationItem that does not have an app-specific + // URL. + NavigationItem* GetLastCommittedNonAppSpecificItem() const; + + // The primary delegate for this manager. + NavigationManagerDelegate* delegate_; + + // The BrowserState that is associated with this instance. + BrowserState* browser_state_; + + // CRWSessionController that backs this instance. + // TODO(stuartmorgan): Fold CRWSessionController into this class. + base::scoped_nsobject<CRWSessionController> session_controller_; + + // List of transient url rewriters added by |AddTransientURLRewriter()|. + std::unique_ptr<std::vector<BrowserURLRewriter::URLRewriter>> + transient_url_rewriters_; + + DISALLOW_COPY_AND_ASSIGN(LegacyNavigationManagerImpl); +}; + +} // namespace web + +#endif // IOS_WEB_NAVIGATION_LEGACY_NAVIGATION_MANAGER_IMPL_H_
diff --git a/ios/web/navigation/navigation_manager_impl.mm b/ios/web/navigation/legacy_navigation_manager_impl.mm similarity index 77% rename from ios/web/navigation/navigation_manager_impl.mm rename to ios/web/navigation/legacy_navigation_manager_impl.mm index 46f7e40..8609620 100644 --- a/ios/web/navigation/navigation_manager_impl.mm +++ b/ios/web/navigation/legacy_navigation_manager_impl.mm
@@ -1,8 +1,8 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. +// Copyright 2017 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. -#import "ios/web/navigation/navigation_manager_impl.h" +#import "ios/web/navigation/legacy_navigation_manager_impl.h" #include <stddef.h> @@ -71,34 +71,35 @@ return *this; } -NavigationManagerImpl::NavigationManagerImpl() +LegacyNavigationManagerImpl::LegacyNavigationManagerImpl() : delegate_(nullptr), browser_state_(nullptr) {} -NavigationManagerImpl::~NavigationManagerImpl() { +LegacyNavigationManagerImpl::~LegacyNavigationManagerImpl() { [session_controller_ setNavigationManager:nullptr]; } -void NavigationManagerImpl::SetDelegate(NavigationManagerDelegate* delegate) { +void LegacyNavigationManagerImpl::SetDelegate( + NavigationManagerDelegate* delegate) { delegate_ = delegate; } -void NavigationManagerImpl::SetBrowserState(BrowserState* browser_state) { +void LegacyNavigationManagerImpl::SetBrowserState(BrowserState* browser_state) { browser_state_ = browser_state; [session_controller_ setBrowserState:browser_state]; } -void NavigationManagerImpl::SetSessionController( +void LegacyNavigationManagerImpl::SetSessionController( CRWSessionController* session_controller) { session_controller_.reset(session_controller); [session_controller_ setNavigationManager:this]; } -void NavigationManagerImpl::InitializeSession() { +void LegacyNavigationManagerImpl::InitializeSession() { SetSessionController( [[CRWSessionController alloc] initWithBrowserState:browser_state_]); } -void NavigationManagerImpl::ReplaceSessionHistory( +void LegacyNavigationManagerImpl::ReplaceSessionHistory( std::vector<std::unique_ptr<web::NavigationItem>> items, int lastCommittedItemIndex) { SetSessionController([[CRWSessionController alloc] @@ -107,15 +108,16 @@ lastCommittedItemIndex:lastCommittedItemIndex]); } -void NavigationManagerImpl::OnNavigationItemsPruned(size_t pruned_item_count) { +void LegacyNavigationManagerImpl::OnNavigationItemsPruned( + size_t pruned_item_count) { delegate_->OnNavigationItemsPruned(pruned_item_count); } -void NavigationManagerImpl::OnNavigationItemChanged() { +void LegacyNavigationManagerImpl::OnNavigationItemChanged() { delegate_->OnNavigationItemChanged(); } -void NavigationManagerImpl::OnNavigationItemCommitted() { +void LegacyNavigationManagerImpl::OnNavigationItemCommitted() { LoadCommittedDetails details; details.item = GetLastCommittedItem(); DCHECK(details.item); @@ -133,11 +135,12 @@ delegate_->OnNavigationItemCommitted(details); } -CRWSessionController* NavigationManagerImpl::GetSessionController() { +CRWSessionController* LegacyNavigationManagerImpl::GetSessionController() + const { return session_controller_; } -void NavigationManagerImpl::AddTransientItem(const GURL& url) { +void LegacyNavigationManagerImpl::AddTransientItem(const GURL& url) { [session_controller_ addTransientItemWithURL:url]; // TODO(crbug.com/676129): Transient item is only supposed to be added for @@ -150,7 +153,7 @@ GetTransientItem()->SetUserAgentType(item->GetUserAgentType()); } -void NavigationManagerImpl::AddPendingItem( +void LegacyNavigationManagerImpl::AddPendingItem( const GURL& url, const web::Referrer& referrer, ui::PageTransition navigation_type, @@ -204,44 +207,44 @@ } } -void NavigationManagerImpl::CommitPendingItem() { +void LegacyNavigationManagerImpl::CommitPendingItem() { [session_controller_ commitPendingItem]; } -BrowserState* NavigationManagerImpl::GetBrowserState() const { +BrowserState* LegacyNavigationManagerImpl::GetBrowserState() const { return browser_state_; } -WebState* NavigationManagerImpl::GetWebState() const { +WebState* LegacyNavigationManagerImpl::GetWebState() const { return delegate_->GetWebState(); } -NavigationItem* NavigationManagerImpl::GetVisibleItem() const { +NavigationItem* LegacyNavigationManagerImpl::GetVisibleItem() const { return [session_controller_ visibleItem]; } -NavigationItem* NavigationManagerImpl::GetLastCommittedItem() const { +NavigationItem* LegacyNavigationManagerImpl::GetLastCommittedItem() const { return [session_controller_ lastCommittedItem]; } -NavigationItem* NavigationManagerImpl::GetPendingItem() const { +NavigationItem* LegacyNavigationManagerImpl::GetPendingItem() const { return [session_controller_ pendingItem]; } -NavigationItem* NavigationManagerImpl::GetTransientItem() const { +NavigationItem* LegacyNavigationManagerImpl::GetTransientItem() const { return [session_controller_ transientItem]; } -void NavigationManagerImpl::DiscardNonCommittedItems() { +void LegacyNavigationManagerImpl::DiscardNonCommittedItems() { [session_controller_ discardNonCommittedItems]; } -void NavigationManagerImpl::LoadURLWithParams( +void LegacyNavigationManagerImpl::LoadURLWithParams( const NavigationManager::WebLoadParams& params) { delegate_->LoadURLWithParams(params); } -void NavigationManagerImpl::AddTransientURLRewriter( +void LegacyNavigationManagerImpl::AddTransientURLRewriter( BrowserURLRewriter::URLRewriter rewriter) { DCHECK(rewriter); if (!transient_url_rewriters_) { @@ -251,20 +254,26 @@ transient_url_rewriters_->push_back(rewriter); } -int NavigationManagerImpl::GetItemCount() const { +int LegacyNavigationManagerImpl::GetItemCount() const { return [session_controller_ items].size(); } -NavigationItem* NavigationManagerImpl::GetItemAtIndex(size_t index) const { +NavigationItem* LegacyNavigationManagerImpl::GetItemAtIndex( + size_t index) const { + return GetNavigationItemImplAtIndex(index); +} + +NavigationItemImpl* LegacyNavigationManagerImpl::GetNavigationItemImplAtIndex( + size_t index) const { return [session_controller_ itemAtIndex:index]; } -int NavigationManagerImpl::GetIndexOfItem( +int LegacyNavigationManagerImpl::GetIndexOfItem( const web::NavigationItem* item) const { return [session_controller_ indexOfItem:item]; } -int NavigationManagerImpl::GetPendingItemIndex() const { +int LegacyNavigationManagerImpl::GetPendingItemIndex() const { if (GetPendingItem()) { if ([session_controller_ pendingItemIndex] != -1) { return [session_controller_ pendingItemIndex]; @@ -276,13 +285,13 @@ return -1; } -int NavigationManagerImpl::GetLastCommittedItemIndex() const { +int LegacyNavigationManagerImpl::GetLastCommittedItemIndex() const { if (GetItemCount() == 0) return -1; return [session_controller_ lastCommittedItemIndex]; } -bool NavigationManagerImpl::RemoveItemAtIndex(int index) { +bool LegacyNavigationManagerImpl::RemoveItemAtIndex(int index) { if (index == GetLastCommittedItemIndex() || index == GetPendingItemIndex()) return false; @@ -293,41 +302,41 @@ return true; } -bool NavigationManagerImpl::CanGoBack() const { +bool LegacyNavigationManagerImpl::CanGoBack() const { return CanGoToOffset(-1); } -bool NavigationManagerImpl::CanGoForward() const { +bool LegacyNavigationManagerImpl::CanGoForward() const { return CanGoToOffset(1); } -bool NavigationManagerImpl::CanGoToOffset(int offset) const { +bool LegacyNavigationManagerImpl::CanGoToOffset(int offset) const { int index = GetIndexForOffset(offset); return 0 <= index && index < GetItemCount(); } -void NavigationManagerImpl::GoBack() { +void LegacyNavigationManagerImpl::GoBack() { delegate_->GoToIndex(GetIndexForOffset(-1)); } -void NavigationManagerImpl::GoForward() { +void LegacyNavigationManagerImpl::GoForward() { delegate_->GoToIndex(GetIndexForOffset(1)); } -void NavigationManagerImpl::GoToIndex(int index) { +void LegacyNavigationManagerImpl::GoToIndex(int index) { delegate_->GoToIndex(index); } -NavigationItemList NavigationManagerImpl::GetBackwardItems() const { +NavigationItemList LegacyNavigationManagerImpl::GetBackwardItems() const { return [session_controller_ backwardItems]; } -NavigationItemList NavigationManagerImpl::GetForwardItems() const { +NavigationItemList LegacyNavigationManagerImpl::GetForwardItems() const { return [session_controller_ forwardItems]; } -void NavigationManagerImpl::Reload(ReloadType reload_type, - bool check_for_reposts) { +void LegacyNavigationManagerImpl::Reload(ReloadType reload_type, + bool check_for_reposts) { if (!GetTransientItem() && !GetPendingItem() && !GetLastCommittedItem()) return; @@ -355,28 +364,29 @@ delegate_->Reload(); } -void NavigationManagerImpl::CopyStateFromAndPrune( +void LegacyNavigationManagerImpl::CopyStateFromAndPrune( const NavigationManager* manager) { DCHECK(manager); CRWSessionController* other_session = - static_cast<const NavigationManagerImpl*>(manager)->session_controller_; + static_cast<const NavigationManagerImpl*>(manager) + ->GetSessionController(); [session_controller_ copyStateFromSessionControllerAndPrune:other_session]; } -bool NavigationManagerImpl::CanPruneAllButLastCommittedItem() const { +bool LegacyNavigationManagerImpl::CanPruneAllButLastCommittedItem() const { return [session_controller_ canPruneAllButLastCommittedItem]; } std::unique_ptr<std::vector<BrowserURLRewriter::URLRewriter>> -NavigationManagerImpl::GetTransientURLRewriters() { +LegacyNavigationManagerImpl::GetTransientURLRewriters() { return std::move(transient_url_rewriters_); } -void NavigationManagerImpl::RemoveTransientURLRewriters() { +void LegacyNavigationManagerImpl::RemoveTransientURLRewriters() { transient_url_rewriters_.reset(); } -int NavigationManagerImpl::GetIndexForOffset(int offset) const { +int LegacyNavigationManagerImpl::GetIndexForOffset(int offset) const { int result = [session_controller_ pendingItemIndex] == -1 ? GetLastCommittedItemIndex() : static_cast<int>([session_controller_ pendingItemIndex]); @@ -424,15 +434,15 @@ return result; } -bool NavigationManagerImpl::IsRedirectItemAtIndex(int index) const { +bool LegacyNavigationManagerImpl::IsRedirectItemAtIndex(int index) const { DCHECK_GE(index, 0); DCHECK_LT(index, GetItemCount()); ui::PageTransition transition = GetItemAtIndex(index)->GetTransitionType(); return transition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK; } -NavigationItem* NavigationManagerImpl::GetLastCommittedNonAppSpecificItem() - const { +NavigationItem* +LegacyNavigationManagerImpl::GetLastCommittedNonAppSpecificItem() const { int index = GetLastCommittedItemIndex(); if (index == -1) return nullptr; @@ -446,4 +456,8 @@ return nullptr; } +size_t LegacyNavigationManagerImpl::GetPreviousItemIndex() const { + return [session_controller_ previousItemIndex]; +} + } // namespace web
diff --git a/ios/web/navigation/navigation_manager_impl.h b/ios/web/navigation/navigation_manager_impl.h index fb4fc7d..0e2a9e3 100644 --- a/ios/web/navigation/navigation_manager_impl.h +++ b/ios/web/navigation/navigation_manager_impl.h
@@ -12,6 +12,7 @@ #import "base/mac/scoped_nsobject.h" #include "base/macros.h" +#import "ios/web/navigation/navigation_item_impl.h" #import "ios/web/public/navigation_item_list.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/reload_type.h" @@ -23,7 +24,6 @@ namespace web { class BrowserState; class NavigationItem; -struct Referrer; class NavigationManagerDelegate; class SessionStorageBuilder; @@ -49,12 +49,11 @@ // Generally mirrors upstream's NavigationController. class NavigationManagerImpl : public NavigationManager { public: - NavigationManagerImpl(); - ~NavigationManagerImpl() override; + ~NavigationManagerImpl() override {} // Setters for NavigationManagerDelegate and BrowserState. - void SetDelegate(NavigationManagerDelegate* delegate); - void SetBrowserState(BrowserState* browser_state); + virtual void SetDelegate(NavigationManagerDelegate* delegate) = 0; + virtual void SetBrowserState(BrowserState* browser_state) = 0; // Sets the CRWSessionController that backs this object. // Keeps a strong reference to |session_controller|. @@ -64,121 +63,80 @@ // TODO(stuartmorgan): Also move deserialization of CRWSessionControllers // under the control of this class, and move the bulk of CRWSessionController // logic into it. - void SetSessionController(CRWSessionController* session_controller); + virtual void SetSessionController( + CRWSessionController* session_controller) = 0; // Initializes a new session history. - void InitializeSession(); + virtual void InitializeSession() = 0; // Replace the session history with a new one, where |items| is the // complete set of navigation items in the new history, and |current_index| // is the index of the currently active item. - void ReplaceSessionHistory(std::vector<std::unique_ptr<NavigationItem>> items, - int current_index); + virtual void ReplaceSessionHistory( + std::vector<std::unique_ptr<NavigationItem>> items, + int current_index) = 0; // Helper functions for notifying WebStateObservers of changes. // TODO(stuartmorgan): Make these private once the logic triggering them moves // into this layer. - void OnNavigationItemsPruned(size_t pruned_item_count); - void OnNavigationItemChanged(); - void OnNavigationItemCommitted(); + virtual void OnNavigationItemsPruned(size_t pruned_item_count) = 0; + virtual void OnNavigationItemChanged() = 0; + virtual void OnNavigationItemCommitted() = 0; // Temporary accessors and content/ class pass-throughs. // TODO(stuartmorgan): Re-evaluate this list once the refactorings have // settled down. - CRWSessionController* GetSessionController(); + virtual CRWSessionController* GetSessionController() const = 0; // Adds a transient item with the given URL. A transient item will be // discarded on any navigation. - void AddTransientItem(const GURL& url); + virtual void AddTransientItem(const GURL& url) = 0; // Adds a new item with the given url, referrer, navigation type, initiation // type and user agent override option, making it the pending item. If pending // item is the same as the current item, this does nothing. |referrer| may be // nil if there isn't one. The item starts out as pending, and will be lost // unless |-commitPendingItem| is called. - void AddPendingItem(const GURL& url, - const web::Referrer& referrer, - ui::PageTransition navigation_type, - NavigationInitiationType initiation_type, - UserAgentOverrideOption user_agent_override_option); + virtual void AddPendingItem( + const GURL& url, + const web::Referrer& referrer, + ui::PageTransition navigation_type, + NavigationInitiationType initiation_type, + UserAgentOverrideOption user_agent_override_option) = 0; // Commits the pending item, if any. - void CommitPendingItem(); - - // NavigationManager: - BrowserState* GetBrowserState() const override; - WebState* GetWebState() const override; - NavigationItem* GetVisibleItem() const override; - NavigationItem* GetLastCommittedItem() const override; - NavigationItem* GetPendingItem() const override; - NavigationItem* GetTransientItem() const override; - void DiscardNonCommittedItems() override; - void LoadURLWithParams(const NavigationManager::WebLoadParams&) override; - void AddTransientURLRewriter( - BrowserURLRewriter::URLRewriter rewriter) override; - int GetItemCount() const override; - NavigationItem* GetItemAtIndex(size_t index) const override; - int GetIndexOfItem(const NavigationItem* item) const override; - int GetPendingItemIndex() const override; - int GetLastCommittedItemIndex() const override; - bool RemoveItemAtIndex(int index) override; - bool CanGoBack() const override; - bool CanGoForward() const override; - bool CanGoToOffset(int offset) const override; - void GoBack() override; - void GoForward() override; - void GoToIndex(int index) override; - void Reload(ReloadType reload_type, bool check_for_reposts) override; - NavigationItemList GetBackwardItems() const override; - NavigationItemList GetForwardItems() const override; - void CopyStateFromAndPrune(const NavigationManager* source) override; - bool CanPruneAllButLastCommittedItem() const override; + virtual void CommitPendingItem() = 0; // Returns the current list of transient url rewriters, passing ownership to // the caller. // TODO(crbug.com/546197): remove once NavigationItem creation occurs in this // class. - std::unique_ptr<std::vector<BrowserURLRewriter::URLRewriter>> - GetTransientURLRewriters(); + virtual std::unique_ptr<std::vector<BrowserURLRewriter::URLRewriter>> + GetTransientURLRewriters() = 0; // Called to reset the transient url rewriter list. - void RemoveTransientURLRewriters(); + virtual void RemoveTransientURLRewriters() = 0; // Returns the navigation index that differs from the current item (or pending // item if it exists) by the specified |offset|, skipping redirect navigation // items. The index returned is not guaranteed to be valid. // TODO(crbug.com/661316): Make this method private once navigation code is // moved from CRWWebController to NavigationManagerImpl. - int GetIndexForOffset(int offset) const; + virtual int GetIndexForOffset(int offset) const = 0; - private: + protected: // The SessionStorageBuilder functions require access to private variables of // NavigationManagerImpl. friend SessionStorageBuilder; - // Returns true if the PageTransition for the underlying navigation item at - // |index| has ui::PAGE_TRANSITION_IS_REDIRECT_MASK. - bool IsRedirectItemAtIndex(int index) const; + // Identical to GetItemAtIndex() but returns the underlying NavigationItemImpl + // instead of the public NavigationItem interface. This is used by + // SessionStorageBuilder to persist session state. + virtual NavigationItemImpl* GetNavigationItemImplAtIndex( + size_t index) const = 0; - // Returns the most recent NavigationItem that does not have an app-specific - // URL. - NavigationItem* GetLastCommittedNonAppSpecificItem() const; - - // The primary delegate for this manager. - NavigationManagerDelegate* delegate_; - - // The BrowserState that is associated with this instance. - BrowserState* browser_state_; - - // CRWSessionController that backs this instance. - // TODO(stuartmorgan): Fold CRWSessionController into this class. - base::scoped_nsobject<CRWSessionController> session_controller_; - - // List of transient url rewriters added by |AddTransientURLRewriter()|. - std::unique_ptr<std::vector<BrowserURLRewriter::URLRewriter>> - transient_url_rewriters_; - - DISALLOW_COPY_AND_ASSIGN(NavigationManagerImpl); + // Returns the index of the previous item. Only used by SessionStorageBuilder. + virtual size_t GetPreviousItemIndex() const = 0; }; } // namespace web
diff --git a/ios/web/navigation/navigation_manager_impl_unittest.mm b/ios/web/navigation/navigation_manager_impl_unittest.mm index 899d7e3..e57607ae 100644 --- a/ios/web/navigation/navigation_manager_impl_unittest.mm +++ b/ios/web/navigation/navigation_manager_impl_unittest.mm
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/mac/bind_objc_block.h" #import "ios/web/navigation/crw_session_controller+private_constructors.h" +#import "ios/web/navigation/legacy_navigation_manager_impl.h" #import "ios/web/navigation/navigation_manager_delegate.h" #include "ios/web/public/navigation_item.h" #include "ios/web/public/test/fakes/test_browser_state.h" @@ -56,10 +57,20 @@ }; } // namespace -// Test fixture for NavigationManagerImpl testing. -class NavigationManagerTest : public PlatformTest { +// Programmatic test fixture for NavigationManagerImpl testing. +// GetParam() chooses whether to run tests on LegacyNavigationManagerImpl or +// (the soon-to-be-implemented) WKBasedNavigationManagerImpl. +// TODO(crbug.com/734150): cleanup the LegacyNavigationManagerImpl use case. +class NavigationManagerTest : public PlatformTest, + public ::testing::WithParamInterface<bool> { protected: - NavigationManagerTest() : manager_(new NavigationManagerImpl()) { + NavigationManagerTest() { + bool test_legacy_navigation_manager = GetParam(); + if (test_legacy_navigation_manager) { + manager_.reset(new LegacyNavigationManagerImpl); + } else { + DCHECK(false) << "Not implemented."; + } // Setup rewriter. BrowserURLRewriter::GetInstance()->AddURLRewriter(UrlRewriter); url::AddStandardScheme(kSchemeToRewrite, url::SCHEME_WITHOUT_PORT); @@ -72,6 +83,7 @@ } CRWSessionController* session_controller() { return controller_; } NavigationManagerImpl* navigation_manager() { return manager_.get(); } + TestNavigationManagerDelegate navigation_manager_delegate() { return delegate_; } @@ -84,7 +96,7 @@ }; // Tests state of an empty navigation manager. -TEST_F(NavigationManagerTest, EmptyManager) { +TEST_P(NavigationManagerTest, EmptyManager) { EXPECT_EQ(0, navigation_manager()->GetItemCount()); EXPECT_EQ(-1, navigation_manager()->GetLastCommittedItemIndex()); EXPECT_EQ(-1, navigation_manager()->GetLastCommittedItemIndex()); @@ -94,7 +106,7 @@ } // Tests that GetPendingItemIndex() returns -1 if there is no pending entry. -TEST_F(NavigationManagerTest, GetPendingItemIndexWithoutPendingEntry) { +TEST_P(NavigationManagerTest, GetPendingItemIndexWithoutPendingEntry) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -105,7 +117,7 @@ // Tests that GetPendingItemIndex() returns current item index if there is a // pending entry. -TEST_F(NavigationManagerTest, GetPendingItemIndexWithPendingEntry) { +TEST_P(NavigationManagerTest, GetPendingItemIndexWithPendingEntry) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -120,7 +132,7 @@ // Tests that GetPendingItemIndex() returns same index as was set by // -[CRWSessionController setPendingItemIndex:]. -TEST_F(NavigationManagerTest, GetPendingItemIndexWithIndexedPendingEntry) { +TEST_P(NavigationManagerTest, GetPendingItemIndexWithIndexedPendingEntry) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -139,14 +151,14 @@ // Tests that going back or negative offset is not possible without a committed // item. -TEST_F(NavigationManagerTest, CanGoBackWithoutCommitedItem) { +TEST_P(NavigationManagerTest, CanGoBackWithoutCommitedItem) { EXPECT_FALSE(navigation_manager()->CanGoBack()); EXPECT_FALSE(navigation_manager()->CanGoToOffset(-1)); } // Tests that going back or negative offset is not possible if there is a // transient item, but not committed items. -TEST_F(NavigationManagerTest, CanGoBackWithTransientItem) { +TEST_P(NavigationManagerTest, CanGoBackWithTransientItem) { [session_controller() addTransientItemWithURL:GURL("http://www.url.com")]; EXPECT_FALSE(navigation_manager()->CanGoBack()); @@ -155,7 +167,7 @@ // Tests that going back or negative offset is possible if there is a transient // item and at least one committed item. -TEST_F(NavigationManagerTest, CanGoBackWithTransientItemAndCommittedItem) { +TEST_P(NavigationManagerTest, CanGoBackWithTransientItemAndCommittedItem) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -169,7 +181,7 @@ // Tests that going back or negative offset is not possible if there is ony one // committed item and no transient item. -TEST_F(NavigationManagerTest, CanGoBackWithSingleCommitedItem) { +TEST_P(NavigationManagerTest, CanGoBackWithSingleCommitedItem) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -181,7 +193,7 @@ } // Tests going back possibility with multiple committed items. -TEST_F(NavigationManagerTest, CanGoBackWithMultipleCommitedItems) { +TEST_P(NavigationManagerTest, CanGoBackWithMultipleCommitedItems) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -216,14 +228,14 @@ // Tests that going forward or positive offset is not possible without a // committed item. -TEST_F(NavigationManagerTest, CanGoForwardWithoutCommitedItem) { +TEST_P(NavigationManagerTest, CanGoForwardWithoutCommitedItem) { EXPECT_FALSE(navigation_manager()->CanGoForward()); EXPECT_FALSE(navigation_manager()->CanGoToOffset(1)); } // Tests that going forward or positive offset is not possible if there is ony // one committed item and no transient item. -TEST_F(NavigationManagerTest, CanGoForwardWithSingleCommitedItem) { +TEST_P(NavigationManagerTest, CanGoForwardWithSingleCommitedItem) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -235,7 +247,7 @@ } // Tests going forward possibility with multiple committed items. -TEST_F(NavigationManagerTest, CanGoForwardWithMultipleCommitedEntries) { +TEST_P(NavigationManagerTest, CanGoForwardWithMultipleCommitedEntries) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -275,7 +287,7 @@ // Tests CanGoToOffset API for positive, negative and zero delta. Tested // navigation manager will have redirect entries to make sure they are // appropriately skipped. -TEST_F(NavigationManagerTest, OffsetsWithoutPendingIndex) { +TEST_P(NavigationManagerTest, OffsetsWithoutPendingIndex) { navigation_manager()->AddPendingItem( GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_LINK, web::NavigationInitiationType::USER_INITIATED, @@ -502,7 +514,7 @@ // Tests offsets with pending transient entries (specifically gong back and // forward from a pending navigation entry that is added to the middle of the // navigation stack). -TEST_F(NavigationManagerTest, OffsetsWithPendingTransientEntry) { +TEST_P(NavigationManagerTest, OffsetsWithPendingTransientEntry) { // Create a transient item in the middle of the navigation stack and go back // to it (pending index is 1, current index is 2). navigation_manager()->AddPendingItem( @@ -542,7 +554,7 @@ // Tests that when given a pending item, adding a new pending item replaces the // existing pending item if their URLs are different. -TEST_F(NavigationManagerTest, ReplacePendingItemIfDiffernetURL) { +TEST_P(NavigationManagerTest, ReplacePendingItemIfDiffernetURL) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -565,7 +577,7 @@ // Tests that when given a pending item, adding a new pending item with the same // URL doesn't replace the existing pending item if new pending item is not a // form submission. -TEST_F(NavigationManagerTest, NotReplaceSameUrlPendingItemIfNotFormSubmission) { +TEST_P(NavigationManagerTest, NotReplaceSameUrlPendingItemIfNotFormSubmission) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -591,7 +603,7 @@ // Tests that when given a pending item, adding a new pending item with the same // URL replaces the existing pending item if new pending item is a form // submission while existing pending item is not. -TEST_F(NavigationManagerTest, ReplaceSameUrlPendingItemIfFormSubmission) { +TEST_P(NavigationManagerTest, ReplaceSameUrlPendingItemIfFormSubmission) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -617,7 +629,7 @@ // Tests that when given a pending item, adding a new pending item with the same // URL doesn't replace the existing pending item if the user agent override // option is INHERIT. -TEST_F(NavigationManagerTest, NotReplaceSameUrlPendingItemIfOverrideInherit) { +TEST_P(NavigationManagerTest, NotReplaceSameUrlPendingItemIfOverrideInherit) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -644,7 +656,7 @@ // Tests that when given a pending item, adding a new pending item with the same // URL replaces the existing pending item if the user agent override option is // DESKTOP. -TEST_F(NavigationManagerTest, ReplaceSameUrlPendingItemIfOverrideDesktop) { +TEST_P(NavigationManagerTest, ReplaceSameUrlPendingItemIfOverrideDesktop) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -672,7 +684,7 @@ // Tests that when given a pending item, adding a new pending item with the same // URL replaces the existing pending item if the user agent override option is // MOBILE. -TEST_F(NavigationManagerTest, ReplaceSameUrlPendingItemIfOverrideMobile) { +TEST_P(NavigationManagerTest, ReplaceSameUrlPendingItemIfOverrideMobile) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -699,7 +711,7 @@ // Tests that when the last committed item exists, adding a pending item // succeeds if the new item's URL is different from the last committed item. -TEST_F(NavigationManagerTest, AddPendingItemIfDiffernetURL) { +TEST_P(NavigationManagerTest, AddPendingItemIfDiffernetURL) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -723,7 +735,7 @@ // Tests that when the last committed item exists, adding a pending item with // the same URL fails if the new item is not form submission. -TEST_F(NavigationManagerTest, NotAddSameUrlPendingItemIfNotFormSubmission) { +TEST_P(NavigationManagerTest, NotAddSameUrlPendingItemIfNotFormSubmission) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -748,7 +760,7 @@ // Tests that when the last committed item exists, adding a pending item with // the same URL succeeds if the new item is a form submission while the last // committed item is not. -TEST_F(NavigationManagerTest, AddSameUrlPendingItemIfFormSubmission) { +TEST_P(NavigationManagerTest, AddSameUrlPendingItemIfFormSubmission) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -777,7 +789,7 @@ // Tests that when the last committed item exists, adding a pending item with // the same URL fails if both the new item and the last committed item are form // submissions. -TEST_F(NavigationManagerTest, +TEST_P(NavigationManagerTest, NotAddSameUrlPendingItemIfDuplicateFormSubmission) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( @@ -799,7 +811,7 @@ // Tests that when the last committed item exists, adding a pending item with // the same URL fails if the user agent override option is INHERIT. -TEST_F(NavigationManagerTest, NotAddSameUrlPendingItemIfOverrideInherit) { +TEST_P(NavigationManagerTest, NotAddSameUrlPendingItemIfOverrideInherit) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -822,7 +834,7 @@ // Tests that when the last committed item exists, adding a pending item with // the same URL succeeds if the user agent override option is DESKTOP. -TEST_F(NavigationManagerTest, AddSameUrlPendingItemIfOverrideDesktop) { +TEST_P(NavigationManagerTest, AddSameUrlPendingItemIfOverrideDesktop) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -851,7 +863,7 @@ // Tests that when the last committed item exists, adding a pending item with // the same URL succeeds if the user agent override option is MOBILE. -TEST_F(NavigationManagerTest, AddSameUrlPendingItemIfOverrideMobile) { +TEST_P(NavigationManagerTest, AddSameUrlPendingItemIfOverrideMobile) { GURL existing_url = GURL("http://www.existing.com"); navigation_manager()->AddPendingItem( existing_url, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -879,7 +891,7 @@ // Tests that desktop user agent can be enforced to use for next pending item // when UserAgentOverrideOption is DESKTOP. -TEST_F(NavigationManagerTest, OverrideUserAgentWithDesktop) { +TEST_P(NavigationManagerTest, OverrideUserAgentWithDesktop) { navigation_manager()->AddPendingItem( GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -902,7 +914,7 @@ // Tests that mobile user agent can be enforced to use for next pending item // when UserAgentOverrideOption is MOBILE. -TEST_F(NavigationManagerTest, OverrideUserAgentWithMobile) { +TEST_P(NavigationManagerTest, OverrideUserAgentWithMobile) { navigation_manager()->AddPendingItem( GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -924,7 +936,7 @@ // Tests that the UserAgentType of an INHERIT item is propagated to subsequent // item when UserAgentOverrideOption is INHERIT -TEST_F(NavigationManagerTest, OverrideUserAgentWithInheritAfterInherit) { +TEST_P(NavigationManagerTest, OverrideUserAgentWithInheritAfterInherit) { navigation_manager()->AddPendingItem( GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -946,7 +958,7 @@ // Tests that the UserAgentType of a MOBILE item is propagated to subsequent // item when UserAgentOverrideOption is INHERIT -TEST_F(NavigationManagerTest, OverrideUserAgentWithInheritAfterMobile) { +TEST_P(NavigationManagerTest, OverrideUserAgentWithInheritAfterMobile) { navigation_manager()->AddPendingItem( GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -968,7 +980,7 @@ // Tests that the UserAgentType of a DESKTOP item is propagated to subsequent // item when UserAgentOverrideOption is INHERIT -TEST_F(NavigationManagerTest, OverrideUserAgentWithInheritAfterDesktop) { +TEST_P(NavigationManagerTest, OverrideUserAgentWithInheritAfterDesktop) { navigation_manager()->AddPendingItem( GURL("http://www.1.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -990,7 +1002,7 @@ // Tests that the UserAgentType is propagated to subsequent NavigationItems if // a native URL exists in between naviations. -TEST_F(NavigationManagerTest, UserAgentTypePropagationPastNativeItems) { +TEST_P(NavigationManagerTest, UserAgentTypePropagationPastNativeItems) { // GURL::Replacements that will replace a GURL's scheme with the test native // scheme. GURL::Replacements native_scheme_replacement; @@ -1047,7 +1059,7 @@ // Tests that adding transient item for a pending item with mobile user agent // type results in a transient item with mobile user agent type. -TEST_F(NavigationManagerTest, AddTransientItemForMobilePendingItem) { +TEST_P(NavigationManagerTest, AddTransientItemForMobilePendingItem) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -1066,7 +1078,7 @@ // Tests that adding transient item for a pending item with desktop user agent // type results in a transient item with desktop user agent type. -TEST_F(NavigationManagerTest, AddTransientItemForDesktopPendingItem) { +TEST_P(NavigationManagerTest, AddTransientItemForDesktopPendingItem) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -1085,7 +1097,7 @@ // Tests that calling |Reload| with web::ReloadType::NORMAL is no-op when there // are no transient, pending and committed items. -TEST_F(NavigationManagerTest, ReloadEmptyWithNormalType) { +TEST_P(NavigationManagerTest, ReloadEmptyWithNormalType) { ASSERT_FALSE(navigation_manager()->GetTransientItem()); ASSERT_FALSE(navigation_manager()->GetPendingItem()); ASSERT_FALSE(navigation_manager()->GetLastCommittedItem()); @@ -1101,7 +1113,7 @@ // Tests that calling |Reload| with web::ReloadType::NORMAL leaves the url of // the renderer initiated pending item unchanged when there is one. -TEST_F(NavigationManagerTest, ReloadRendererPendingItemWithNormalType) { +TEST_P(NavigationManagerTest, ReloadRendererPendingItemWithNormalType) { GURL url_before_reload = GURL("http://www.url.com"); navigation_manager()->AddPendingItem( url_before_reload, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -1119,7 +1131,7 @@ // Tests that calling |Reload| with web::ReloadType::NORMAL leaves the url of // the user initiated pending item unchanged when there is one. -TEST_F(NavigationManagerTest, ReloadUserPendingItemWithNormalType) { +TEST_P(NavigationManagerTest, ReloadUserPendingItemWithNormalType) { GURL url_before_reload = GURL("http://www.url.com"); navigation_manager()->AddPendingItem( url_before_reload, Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -1137,7 +1149,7 @@ // Tests that calling |Reload| with web::ReloadType::NORMAL leaves the url of // the last committed item unchanged when there is no pending item. -TEST_F(NavigationManagerTest, ReloadLastCommittedItemWithNormalType) { +TEST_P(NavigationManagerTest, ReloadLastCommittedItemWithNormalType) { navigation_manager()->AddPendingItem( GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -1163,7 +1175,7 @@ // Tests that calling |Reload| with web::ReloadType::NORMAL leaves the url of // the last committed item unchanged when there is no pending item, but there // forward items after last committed item. -TEST_F(NavigationManagerTest, +TEST_P(NavigationManagerTest, ReloadLastCommittedItemWithNormalTypeWithForwardItems) { navigation_manager()->AddPendingItem( GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -1198,7 +1210,7 @@ // Tests that calling |Reload| with web::ReloadType::ORIGINAL_REQUEST_URL is // no-op when there are no transient, pending and committed items. -TEST_F(NavigationManagerTest, ReloadEmptyWithOriginalType) { +TEST_P(NavigationManagerTest, ReloadEmptyWithOriginalType) { ASSERT_FALSE(navigation_manager()->GetTransientItem()); ASSERT_FALSE(navigation_manager()->GetPendingItem()); ASSERT_FALSE(navigation_manager()->GetLastCommittedItem()); @@ -1215,7 +1227,7 @@ // Tests that calling |Reload| with web::ReloadType::ORIGINAL_REQUEST_URL // changes the renderer initiated pending item's url to its original request url // when there is one. -TEST_F(NavigationManagerTest, ReloadRendererPendingItemWithOriginalType) { +TEST_P(NavigationManagerTest, ReloadRendererPendingItemWithOriginalType) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::RENDERER_INITIATED, @@ -1237,7 +1249,7 @@ // Tests that calling |Reload| with web::ReloadType::ORIGINAL_REQUEST_URL // changes the user initiated pending item's url to its original request url // when there is one. -TEST_F(NavigationManagerTest, ReloadUserPendingItemWithOriginalType) { +TEST_P(NavigationManagerTest, ReloadUserPendingItemWithOriginalType) { navigation_manager()->AddPendingItem( GURL("http://www.url.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -1259,7 +1271,7 @@ // Tests that calling |Reload| with web::ReloadType::ORIGINAL_REQUEST_URL // changes the last committed item's url to its original request url when there // is no pending item. -TEST_F(NavigationManagerTest, ReloadLastCommittedItemWithOriginalType) { +TEST_P(NavigationManagerTest, ReloadLastCommittedItemWithOriginalType) { navigation_manager()->AddPendingItem( GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, @@ -1288,7 +1300,7 @@ // Tests that calling |Reload| with web::ReloadType::ORIGINAL_REQUEST_URL // changes the last committed item's url to its original request url when there // is no pending item, but there are forward items after last committed item. -TEST_F(NavigationManagerTest, +TEST_P(NavigationManagerTest, ReloadLastCommittedItemWithOriginalTypeWithForwardItems) { navigation_manager()->AddPendingItem( GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -1326,7 +1338,7 @@ // Tests that app-specific URLs are not rewritten for renderer-initiated loads // unless requested by a page with app-specific url. -TEST_F(NavigationManagerTest, RewritingAppSpecificUrls) { +TEST_P(NavigationManagerTest, RewritingAppSpecificUrls) { // URL should not be rewritten as there is no committed URL. GURL url1(url::SchemeHostPort(kSchemeToRewrite, "test", 0).Serialize()); navigation_manager()->AddPendingItem( @@ -1367,7 +1379,7 @@ } // Tests that GetIndexOfItem() returns the correct values. -TEST_F(NavigationManagerTest, GetIndexOfItem) { +TEST_P(NavigationManagerTest, GetIndexOfItem) { // Create two items and add them to the NavigationManagerImpl. navigation_manager()->AddPendingItem( GURL("http://www.url.com/0"), Referrer(), ui::PAGE_TRANSITION_TYPED, @@ -1390,4 +1402,9 @@ EXPECT_EQ(-1, navigation_manager()->GetIndexOfItem(item_not_found.get())); } +INSTANTIATE_TEST_CASE_P( + ProgrammaticNavigationManagerTest, + NavigationManagerTest, + ::testing::Values(true /* test_legacy_navigation_manager */)); + } // namespace web
diff --git a/ios/web/navigation/navigation_manager_util_unittest.mm b/ios/web/navigation/navigation_manager_util_unittest.mm index 83b3b18..4b343cb 100644 --- a/ios/web/navigation/navigation_manager_util_unittest.mm +++ b/ios/web/navigation/navigation_manager_util_unittest.mm
@@ -7,7 +7,7 @@ #include "base/memory/ptr_util.h" #import "ios/web/navigation/crw_session_controller+private_constructors.h" #import "ios/web/navigation/crw_session_controller.h" -#import "ios/web/navigation/navigation_manager_impl.h" +#import "ios/web/navigation/legacy_navigation_manager_impl.h" #import "ios/web/public/navigation_item.h" #include "ios/web/public/test/fakes/test_browser_state.h" #include "testing/platform_test.h" @@ -18,16 +18,26 @@ namespace web { -// Test fixture testing navigation_manager_util.h functions. -class NavigationManagerUtilTest : public PlatformTest { +// Parameterized fixture testing navigation_manager_util.h functions. +// GetParam() chooses whether to run the tests on LegacyNavigationManagerImpl +// or (the soon-to-be-added) WKBasedNavigationManagerImpl. +// TODO(crbug.com/734150): cleanup LegacyNavigationManagerImpl use case. +class NavigationManagerUtilTest : public PlatformTest, + public ::testing::WithParamInterface<bool> { protected: NavigationManagerUtilTest() : controller_([[CRWSessionController alloc] initWithBrowserState:&browser_state_]) { - manager_.SetSessionController(controller_); + bool test_legacy_navigation_manager = GetParam(); + if (test_legacy_navigation_manager) { + manager_.reset(new LegacyNavigationManagerImpl); + manager_->SetSessionController(controller_); + } else { + DCHECK(false) << "Not yet implemented."; + } } - NavigationManagerImpl manager_; + std::unique_ptr<NavigationManagerImpl> manager_; CRWSessionController* controller_; private: @@ -38,36 +48,41 @@ // GetItemWithUniqueID functions. // TODO(crbug.com/733658): test was incorrectly moved to a separate target // and not run and a refactoring broke it. Disable until the issue is fixed. -TEST_F(NavigationManagerUtilTest, DISABLED_GetCommittedItemWithUniqueID) { +TEST_P(NavigationManagerUtilTest, DISABLED_GetCommittedItemWithUniqueID) { // Start with NavigationManager that only has a pending item. - manager_.AddPendingItem( + manager_->AddPendingItem( GURL("http://chromium.org"), Referrer(), ui::PAGE_TRANSITION_TYPED, web::NavigationInitiationType::USER_INITIATED, web::NavigationManager::UserAgentOverrideOption::INHERIT); - NavigationItem* item = manager_.GetPendingItem(); + NavigationItem* item = manager_->GetPendingItem(); int unique_id = item->GetUniqueID(); - EXPECT_FALSE(GetCommittedItemWithUniqueID(&manager_, unique_id)); - EXPECT_EQ(item, GetItemWithUniqueID(&manager_, unique_id)); - EXPECT_EQ(-1, GetCommittedItemIndexWithUniqueID(&manager_, unique_id)); + EXPECT_FALSE(GetCommittedItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_EQ(item, GetItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_EQ(-1, GetCommittedItemIndexWithUniqueID(manager_.get(), unique_id)); // Commit that pending item. [controller_ commitPendingItem]; - EXPECT_EQ(item, GetCommittedItemWithUniqueID(&manager_, unique_id)); - EXPECT_EQ(item, GetItemWithUniqueID(&manager_, unique_id)); - EXPECT_EQ(0, GetCommittedItemIndexWithUniqueID(&manager_, unique_id)); + EXPECT_EQ(item, GetCommittedItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_EQ(item, GetItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_EQ(0, GetCommittedItemIndexWithUniqueID(manager_.get(), unique_id)); // Remove committed item. - manager_.RemoveItemAtIndex(0); - EXPECT_FALSE(GetCommittedItemWithUniqueID(&manager_, unique_id)); - EXPECT_FALSE(GetItemWithUniqueID(&manager_, unique_id)); - EXPECT_EQ(-1, GetCommittedItemIndexWithUniqueID(&manager_, unique_id)); + manager_->RemoveItemAtIndex(0); + EXPECT_FALSE(GetCommittedItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_FALSE(GetItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_EQ(-1, GetCommittedItemIndexWithUniqueID(manager_.get(), unique_id)); // Add transient item. [controller_ addTransientItemWithURL:GURL("http://chromium.org")]; - item = manager_.GetTransientItem(); - EXPECT_FALSE(GetCommittedItemWithUniqueID(&manager_, unique_id)); - EXPECT_EQ(item, GetItemWithUniqueID(&manager_, unique_id)); - EXPECT_EQ(-1, GetCommittedItemIndexWithUniqueID(&manager_, unique_id)); + item = manager_->GetTransientItem(); + EXPECT_FALSE(GetCommittedItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_EQ(item, GetItemWithUniqueID(manager_.get(), unique_id)); + EXPECT_EQ(-1, GetCommittedItemIndexWithUniqueID(manager_.get(), unique_id)); } +INSTANTIATE_TEST_CASE_P( + ProgrammaticNavigationManagerUtilTest, + NavigationManagerUtilTest, + ::testing::Values(true /* test_legacy_navigation_manager */)); + } // namespace web
diff --git a/ios/web/navigation/session_storage_builder.mm b/ios/web/navigation/session_storage_builder.mm index 24ff60e..323fd82 100644 --- a/ios/web/navigation/session_storage_builder.mm +++ b/ios/web/navigation/session_storage_builder.mm
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #import "ios/web/navigation/crw_session_controller+private_constructors.h" #import "ios/web/navigation/crw_session_controller.h" +#import "ios/web/navigation/legacy_navigation_manager_impl.h" #import "ios/web/navigation/navigation_item_impl.h" #import "ios/web/navigation/navigation_item_storage_builder.h" #include "ios/web/navigation/navigation_manager_impl.h" @@ -42,15 +43,18 @@ DCHECK(navigation_manager); CRWSessionStorage* session_storage = [[CRWSessionStorage alloc] init]; session_storage.hasOpener = web_state->HasOpener(); - CRWSessionController* session_controller = - navigation_manager->GetSessionController(); session_storage.lastCommittedItemIndex = - session_controller.lastCommittedItemIndex; - session_storage.previousItemIndex = session_controller.previousItemIndex; + navigation_manager->GetLastCommittedItemIndex(); + session_storage.previousItemIndex = + static_cast<NSInteger>(navigation_manager->GetPreviousItemIndex()); NSMutableArray* item_storages = [[NSMutableArray alloc] init]; NavigationItemStorageBuilder item_storage_builder; - for (size_t index = 0; index < session_controller.items.size(); ++index) { - web::NavigationItemImpl* item = session_controller.items[index].get(); + for (size_t index = 0; + index < static_cast<size_t>(navigation_manager->GetItemCount()); + ++index) { + web::NavigationItemImpl* item = + navigation_manager->GetNavigationItemImplAtIndex(index); + ; [item_storages addObject:item_storage_builder.BuildStorage(item)]; } session_storage.itemStorages = item_storages; @@ -85,8 +89,11 @@ navigationItems:std::move(items) lastCommittedItemIndex:last_committed_item_index]); [session_controller setPreviousItemIndex:storage.previousItemIndex]; - web_state->navigation_manager_.reset(new NavigationManagerImpl()); - web_state->navigation_manager_->SetSessionController(session_controller); + + auto navigation_manager = base::MakeUnique<LegacyNavigationManagerImpl>(); + navigation_manager->SetSessionController(session_controller); + web_state->navigation_manager_.reset(navigation_manager.release()); + SessionCertificatePolicyCacheStorageBuilder cert_builder; std::unique_ptr<SessionCertificatePolicyCacheImpl> cert_policy_cache = cert_builder.BuildSessionCertificatePolicyCache(
diff --git a/ios/web/net/crw_ssl_status_updater_unittest.mm b/ios/web/net/crw_ssl_status_updater_unittest.mm index dc9d4878..e2021876b 100644 --- a/ios/web/net/crw_ssl_status_updater_unittest.mm +++ b/ios/web/net/crw_ssl_status_updater_unittest.mm
@@ -9,6 +9,7 @@ #include "base/strings/sys_string_conversions.h" #import "ios/web/navigation/crw_session_controller+private_constructors.h" #import "ios/web/navigation/crw_session_controller.h" +#import "ios/web/navigation/legacy_navigation_manager_impl.h" #import "ios/web/navigation/navigation_manager_impl.h" #import "ios/web/public/navigation_item.h" #include "ios/web/public/ssl_status.h" @@ -86,7 +87,7 @@ delegate_ = [OCMockObject mockForProtocol:@protocol(CRWSSLStatusUpdaterDelegate)]; - nav_manager_.reset(new NavigationManagerImpl()); + nav_manager_.reset(new LegacyNavigationManagerImpl()); nav_manager_->SetBrowserState(GetBrowserState()); ssl_status_updater_ =
diff --git a/ios/web/web_state/web_state_impl.mm b/ios/web/web_state/web_state_impl.mm index de5e4b97..d973508 100644 --- a/ios/web/web_state/web_state_impl.mm +++ b/ios/web/web_state/web_state_impl.mm
@@ -13,6 +13,7 @@ #include "base/strings/sys_string_conversions.h" #import "ios/web/interstitials/web_interstitial_impl.h" #import "ios/web/navigation/crw_session_controller.h" +#import "ios/web/navigation/legacy_navigation_manager_impl.h" #import "ios/web/navigation/navigation_item_impl.h" #import "ios/web/navigation/session_storage_builder.h" #include "ios/web/public/browser_state.h" @@ -80,7 +81,8 @@ SessionStorageBuilder session_storage_builder; session_storage_builder.ExtractSessionState(this, session_storage); } else { - navigation_manager_ = base::MakeUnique<NavigationManagerImpl>(); + navigation_manager_ = base::WrapUnique<NavigationManagerImpl>( + new LegacyNavigationManagerImpl); certificate_policy_cache_ = base::MakeUnique<SessionCertificatePolicyCacheImpl>(); }
diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc index e55f96f..d4b2b641 100644 --- a/mojo/edk/system/node_controller.cc +++ b/mojo/edk/system/node_controller.cc
@@ -998,6 +998,8 @@ } node_->AcceptEvent(std::move(event)); + + AttemptShutdownIfRequested(); } void NodeController::OnRequestPortMerge(
diff --git a/net/android/java/src/org/chromium/net/X509Util.java b/net/android/java/src/org/chromium/net/X509Util.java index ffe25d7..8536b2d 100644 --- a/net/android/java/src/org/chromium/net/X509Util.java +++ b/net/android/java/src/org/chromium/net/X509Util.java
@@ -143,9 +143,10 @@ } @Override - public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, - String authType, - String host) throws CertificateException { + @SuppressLint("NewApi") + public List<X509Certificate> checkServerTrusted( + X509Certificate[] chain, String authType, String host) throws CertificateException { + // API Level 17: android.net.http.X509TrustManagerExtensions#checkServerTrusted return mTrustManagerExtensions.checkServerTrusted(chain, authType, host); } }
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc index 8e3158a..4372bde3 100644 --- a/net/cookies/canonical_cookie.cc +++ b/net/cookies/canonical_cookie.cc
@@ -226,6 +226,7 @@ if (options.has_server_time()) server_time = options.server_time(); + DCHECK(!creation_time.is_null()); Time cookie_expires = CanonicalCookie::CanonExpiration(parsed_cookie, creation_time, server_time); @@ -447,6 +448,11 @@ return true; } +void CanonicalCookie::SetCreationDate(base::Time new_creation_date) { + DCHECK(CreationDate().is_null()); + creation_date_ = new_creation_date; +} + // static CanonicalCookie::CookiePrefix CanonicalCookie::GetCookiePrefix( const std::string& name) {
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h index 1d3b3ed5..78870ec 100644 --- a/net/cookies/canonical_cookie.h +++ b/net/cookies/canonical_cookie.h
@@ -47,8 +47,8 @@ // Supports the default copy constructor. // Creates a new |CanonicalCookie| from the |cookie_line| and the - // |creation_time|. Canonicalizes and validates inputs. May return NULL if - // an attribute value is invalid. + // |creation_time|. Canonicalizes and validates inputs. May return NULL if + // an attribute value is invalid. |creation_time| may not be null. static std::unique_ptr<CanonicalCookie> Create( const GURL& url, const std::string& cookie_line, @@ -159,6 +159,11 @@ // greater than the last access time. bool IsCanonical() const; + // Sets the creation date of the cookie to the specified value. It + // is only valid to call this method if the existing creation date + // is null. + void SetCreationDate(base::Time new_creation_date); + private: FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms);
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc index aaa9c69d..a2f3cf7 100644 --- a/net/cookies/canonical_cookie_unittest.cc +++ b/net/cookies/canonical_cookie_unittest.cc
@@ -864,6 +864,17 @@ .IsCanonical()); } +TEST(CanonicalCookieTest, TestSetCreationDate) { + CanonicalCookie cookie("A", "B", "x.y", "/path", base::Time(), base::Time(), + base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW); + EXPECT_TRUE(cookie.CreationDate().is_null()); + + base::Time now(base::Time::Now()); + cookie.SetCreationDate(now); + EXPECT_EQ(now, cookie.CreationDate()); +} + TEST(CanonicalCookieTest, TestPrefixHistograms) { base::HistogramTester histograms; const char kCookiePrefixHistogram[] = "Cookie.CookiePrefix";
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 7ccf452..60eccfe 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -694,6 +694,42 @@ return this->cookie_monster()->DeleteCanonicalCookie(cookie_); } +// Task class for SetCanonicalCookie call. +class CookieMonster::SetCanonicalCookieTask : public CookieMonsterTask { + public: + SetCanonicalCookieTask(CookieMonster* cookie_monster, + std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) + : CookieMonsterTask(cookie_monster), + cookie_(std::move(cookie)), + secure_source_(secure_source), + modify_http_only_(modify_http_only), + callback_(callback) {} + + // CookieMonsterTask: + void Run() override; + + protected: + ~SetCanonicalCookieTask() override {} + + private: + std::unique_ptr<CanonicalCookie> cookie_; + bool secure_source_; + bool modify_http_only_; + SetCookiesCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(SetCanonicalCookieTask); +}; + +void CookieMonster::SetCanonicalCookieTask::Run() { + bool result = this->cookie_monster()->SetCanonicalCookie( + std::move(cookie_), secure_source_, modify_http_only_); + if (!callback_.is_null()) + callback_.Run(result); +} + // Task class for SetCookieWithOptions call. class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask { public: @@ -902,6 +938,22 @@ DoCookieTask(task); } +void CookieMonster::SetCanonicalCookieAsync( + std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) { + DCHECK(cookie->IsCanonical()); + scoped_refptr<SetCanonicalCookieTask> task = new SetCanonicalCookieTask( + this, std::move(cookie), secure_source, modify_http_only, callback); + + // TODO(rdsmith): Switch to DoCookieTaskForURL (or the equivalent). + // This is tricky because we don't have the scheme in this routine + // and DoCookieTaskForURL uses cookie_util::GetEffectiveDomain(scheme, host) + // to generate the database key to block behind. + DoCookieTask(task); +} + void CookieMonster::SetCookieWithOptionsAsync( const GURL& url, const std::string& cookie_line, @@ -1067,16 +1119,6 @@ if (!HasCookieableScheme(url)) return false; - // TODO(mmenke): This class assumes each cookie to have a unique creation - // time. Allowing the caller to set the creation time violates that - // assumption. Worth fixing? Worth noting that time changes between browser - // restarts can cause the same issue. - base::Time actual_creation_time = creation_time; - if (creation_time.is_null()) { - actual_creation_time = CurrentTime(); - last_time_seen_ = actual_creation_time; - } - // Validate consistency of passed arguments. if (ParsedCookie::ParseTokenString(name) != name || ParsedCookie::ParseValueString(value) != value || @@ -1103,9 +1145,8 @@ canon_path_component.len); std::unique_ptr<CanonicalCookie> cc(base::MakeUnique<CanonicalCookie>( - name, value, cookie_domain, cookie_path, actual_creation_time, - expiration_time, last_access_time, secure, http_only, same_site, - priority)); + name, value, cookie_domain, cookie_path, creation_time, expiration_time, + last_access_time, secure, http_only, same_site, priority)); return SetCanonicalCookie(std::move(cc), url.SchemeIsCryptographic(), true); } @@ -1765,9 +1806,19 @@ if (cc->IsSecure() && !secure_source) return false; - Time creation_time = cc->CreationDate(); const std::string key(GetKey(cc->Domain())); - bool already_expired = cc->IsExpired(creation_time); + + // TODO(mmenke): This class assumes each cookie to have a unique creation + // time. Allowing the caller to set the creation time violates that + // assumption. Worth fixing? Worth noting that time changes between browser + // restarts can cause the same issue. + base::Time creation_date = cc->CreationDate(); + if (creation_date.is_null()) { + creation_date = CurrentTime(); + cc->SetCreationDate(creation_date); + last_time_seen_ = creation_date; + } + bool already_expired = cc->IsExpired(creation_date); if (DeleteAnyEquivalentCookie(key, *cc, secure_source, !modify_http_only, already_expired)) { @@ -1789,7 +1840,7 @@ // See InitializeHistograms() for details. if (cc->IsPersistent()) { histogram_expiration_duration_minutes_->Add( - (cc->ExpiryDate() - creation_time).InMinutes()); + (cc->ExpiryDate() - creation_date).InMinutes()); } // Histogram the type of scheme used on URLs that set cookies. This @@ -1817,7 +1868,7 @@ // make sure that we garbage collect... We can also make the assumption that // if a cookie was set, in the common case it will be used soon after, // and we will purge the expired cookies in GetCookies(). - GarbageCollect(creation_time, key); + GarbageCollect(creation_date, key); return true; }
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h index 42afd9a..9382e935 100644 --- a/net/cookies/cookie_monster.h +++ b/net/cookies/cookie_monster.h
@@ -176,6 +176,10 @@ CookieSameSite same_site, CookiePriority priority, const SetCookiesCallback& callback) override; + void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) override; void GetCookiesWithOptionsAsync(const GURL& url, const CookieOptions& options, const GetCookiesCallback& callback) override; @@ -247,6 +251,7 @@ class SetAllCookiesTask; class SetCookieWithDetailsTask; class SetCookieWithOptionsTask; + class SetCanonicalCookieTask; class DeleteSessionCookiesTask; // Testing support. @@ -427,6 +432,15 @@ CookieSameSite same_site, CookiePriority priority); + // Sets a canonical cookie, deletes equivalents and performs garbage + // collection. |source_secure| indicates if the cookie is being set + // from a secure source (e.g. a cryptographic scheme). + // |modify_http_only| indicates if this setting operation is allowed + // to affect http_only cookies. + bool SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool can_modify_httponly); + CookieList GetAllCookies(); CookieList GetCookieListWithOptions(const GURL& url, @@ -545,15 +559,6 @@ const base::Time& creation_time, const CookieOptions& options); - // Sets a canonical cookie, deletes equivalents and performs garbage - // collection. |source_secure| indicates if the cookie is being set - // from a secure source (e.g. a cryptographic scheme). - // |modify_http_only| indicates if this setting operation is allowed - // to affect http_only cookies. - bool SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cookie, - bool secure_source, - bool can_modify_httponly); - // Sets all cookies from |list| after deleting any equivalent cookie. // For data gathering purposes, this routine is treated as if it is // restoring saved cookies; some statistics are not gathered in this case.
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 0b60812a..6878898 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -148,6 +148,20 @@ return callback.result(); } + bool SetCanonicalCookie(std::unique_ptr<CookieMonster> cm, + std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only) { + DCHECK(cm); + ResultSavingCookieCallback<bool> callback; + cm->SetCanonicalCookieAsync( + std::move(cookie), secure_source, modify_http_only, + base::Bind(&ResultSavingCookieCallback<bool>::Run, + base::Unretained(&callback))); + callback.WaitUntilDone(); + return callback.result(); + } + int DeleteAllCreatedBetween(CookieMonster* cm, const base::Time& delete_begin, const base::Time& delete_end) { @@ -2303,7 +2317,7 @@ // When passed to the CookieMonster, it takes ownership of the pointed to // cookies. cookies.push_back( - CanonicalCookie::Create(kUrl, "a=b", base::Time(), CookieOptions())); + CanonicalCookie::Create(kUrl, "a=b", base::Time::Now(), CookieOptions())); ASSERT_TRUE(cookies[0]); store->commands()[0].loaded_callback.Run(std::move(cookies));
diff --git a/net/cookies/cookie_store.h b/net/cookies/cookie_store.h index a2be255..931b2ea1 100644 --- a/net/cookies/cookie_store.h +++ b/net/cookies/cookie_store.h
@@ -127,6 +127,18 @@ CookiePriority priority, const SetCookiesCallback& callback) = 0; + // TODO(rdsmith): Remove SetCookieWithDetailsAsync in favor of this. + // Set the cookie on the cookie store. |cookie.IsCanonical()| must + // be true. |secure_source| indicates if the source of the setting + // may be considered secure (if from a URL, the scheme is + // cryptographic), and |modify_http_only| indicates if the source of + // the setting may modify http_only cookies. The current time will + // be used in place of a null creation time. + virtual void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) = 0; + // TODO(???): what if the total size of all the cookies >4k, can we have a // header that big or do we need multiple Cookie: headers? // Note: Some sites, such as Facebook, occasionally use Cookie headers >4k.
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc index bed506f1..d1c1ed5 100644 --- a/net/cookies/cookie_store_test_helpers.cc +++ b/net/cookies/cookie_store_test_helpers.cc
@@ -92,6 +92,14 @@ NOTREACHED(); } +void DelayedCookieMonster::SetCanonicalCookieAsync( + std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) { + NOTREACHED(); +} + void DelayedCookieMonster::GetCookiesWithOptionsAsync( const GURL& url, const CookieOptions& options,
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h index bb6d656b..7a9c34c 100644 --- a/net/cookies/cookie_store_test_helpers.h +++ b/net/cookies/cookie_store_test_helpers.h
@@ -45,6 +45,11 @@ CookiePriority priority, const SetCookiesCallback& callback) override; + void SetCanonicalCookieAsync(std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool modify_http_only, + const SetCookiesCallback& callback) override; + void GetCookiesWithOptionsAsync( const GURL& url, const CookieOptions& options,
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h index 14aa3e9..4aa2a3c 100644 --- a/net/cookies/cookie_store_unittest.h +++ b/net/cookies/cookie_store_unittest.h
@@ -181,6 +181,20 @@ return callback.result(); } + bool SetCanonicalCookie(CookieStore* cs, + std::unique_ptr<CanonicalCookie> cookie, + bool secure_source, + bool can_modify_httponly) { + DCHECK(cs); + ResultSavingCookieCallback<bool> callback; + cs->SetCanonicalCookieAsync( + std::move(cookie), secure_source, can_modify_httponly, + base::Bind(&ResultSavingCookieCallback<bool>::Run, + base::Unretained(&callback))); + callback.WaitUntilDone(); + return callback.result(); + } + bool SetCookieWithServerTime(CookieStore* cs, const GURL& url, const std::string& cookie_line, @@ -465,6 +479,131 @@ EXPECT_TRUE(++it == cookies.end()); } +TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { + CookieStore* cs = this->GetCookieStore(); + + base::Time two_hours_ago = base::Time::Now() - base::TimeDelta::FromHours(2); + base::Time one_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1); + base::Time one_hour_from_now = + base::Time::Now() + base::TimeDelta::FromHours(1); + + std::string foo_foo_host(this->www_foo_foo_.url().host()); + std::string foo_bar_domain(this->www_foo_bar_.domain()); + std::string http_foo_host(this->http_www_foo_.url().host()); + std::string https_foo_host(this->https_www_foo_.url().host()); + + EXPECT_TRUE(this->SetCanonicalCookie( + cs, + base::MakeUnique<CanonicalCookie>( + "A", "B", foo_foo_host, "/foo", one_hour_ago, one_hour_from_now, + base::Time(), false, false, CookieSameSite::DEFAULT_MODE, + COOKIE_PRIORITY_DEFAULT), + false, true)); + // Note that for the creation time to be set exactly, without modification, + // it must be different from the one set by the line above. + EXPECT_TRUE(this->SetCanonicalCookie( + cs, + base::MakeUnique<CanonicalCookie>( + "C", "D", "." + foo_bar_domain, "/bar", two_hours_ago, base::Time(), + one_hour_ago, false, true, CookieSameSite::DEFAULT_MODE, + COOKIE_PRIORITY_DEFAULT), + false, true)); + + // A secure source is required for creating secure cookies. + EXPECT_FALSE(this->SetCanonicalCookie( + cs, + base::MakeUnique<CanonicalCookie>( + "E", "F", http_foo_host, "/", base::Time(), base::Time(), + base::Time(), true, false, CookieSameSite::DEFAULT_MODE, + COOKIE_PRIORITY_DEFAULT), + false, true)); + + // A secure source is also required for overwriting secure cookies. Writing + // a secure cookie then overwriting it from a non-secure source should fail. + EXPECT_TRUE(this->SetCanonicalCookie( + cs, + base::MakeUnique<CanonicalCookie>( + "E", "F", http_foo_host, "/", base::Time(), base::Time(), + base::Time(), true, false, CookieSameSite::DEFAULT_MODE, + COOKIE_PRIORITY_DEFAULT), + true, true)); + + EXPECT_FALSE(this->SetCanonicalCookie( + cs, + base::MakeUnique<CanonicalCookie>( + "E", "F", http_foo_host, "/", base::Time(), base::Time(), + base::Time(), true, false, CookieSameSite::DEFAULT_MODE, + COOKIE_PRIORITY_DEFAULT), + false, true)); + + // Get all the cookies for a given URL, regardless of properties. This 'get()' + // operation shouldn't update the access time, as the test checks that the + // access time is set properly upon creation. Updating the access time would + // make that difficult. + CookieOptions options; + options.set_include_httponly(); + options.set_same_site_cookie_mode( + CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX); + options.set_do_not_update_access_time(); + + CookieList cookies = + this->GetCookieListWithOptions(cs, this->www_foo_foo_.url(), options); + CookieList::iterator it = cookies.begin(); + + ASSERT_EQ(1u, cookies.size()); + EXPECT_EQ("A", it->Name()); + EXPECT_EQ("B", it->Value()); + EXPECT_EQ(this->www_foo_foo_.host(), it->Domain()); + EXPECT_EQ("/foo", it->Path()); + EXPECT_EQ(one_hour_ago, it->CreationDate()); + EXPECT_TRUE(it->IsPersistent()); + // Expect expiration date is in the right range. Some cookie implementations + // may not record it with millisecond accuracy. + EXPECT_LE((one_hour_from_now - it->ExpiryDate()).magnitude().InSeconds(), 5); + // Some CookieStores don't store last access date. + if (!it->LastAccessDate().is_null()) + EXPECT_EQ(one_hour_ago, it->LastAccessDate()); + EXPECT_FALSE(it->IsSecure()); + EXPECT_FALSE(it->IsHttpOnly()); + + // Get the cookie using the wide open |options|: + cookies = + this->GetCookieListWithOptions(cs, this->www_foo_bar_.url(), options); + ASSERT_EQ(1u, cookies.size()); + it = cookies.begin(); + + EXPECT_EQ("C", it->Name()); + EXPECT_EQ("D", it->Value()); + EXPECT_EQ(this->www_foo_bar_.Format(".%D"), it->Domain()); + EXPECT_EQ("/bar", it->Path()); + EXPECT_EQ(two_hours_ago, it->CreationDate()); + EXPECT_FALSE(it->IsPersistent()); + // Some CookieStores don't store last access date. + if (!it->LastAccessDate().is_null()) + EXPECT_EQ(one_hour_ago, it->LastAccessDate()); + EXPECT_FALSE(it->IsSecure()); + EXPECT_TRUE(it->IsHttpOnly()); + + cookies = + this->GetCookieListWithOptions(cs, this->https_www_foo_.url(), options); + ASSERT_EQ(1u, cookies.size()); + it = cookies.begin(); + + EXPECT_EQ("E", it->Name()); + EXPECT_EQ("F", it->Value()); + EXPECT_EQ("/", it->Path()); + EXPECT_EQ(this->https_www_foo_.host(), it->Domain()); + // Cookie should have its creation time set, and be in a reasonable range. + EXPECT_LE((base::Time::Now() - it->CreationDate()).magnitude().InMinutes(), + 2); + EXPECT_FALSE(it->IsPersistent()); + // Some CookieStores don't store last access date. + if (!it->LastAccessDate().is_null()) + EXPECT_EQ(it->CreationDate(), it->LastAccessDate()); + EXPECT_TRUE(it->IsSecure()); + EXPECT_FALSE(it->IsHttpOnly()); +} + // Test enforcement around setting secure cookies. TYPED_TEST_P(CookieStoreTest, SetCookieWithDetailsSecureEnforcement) { CookieStore* cs = this->GetCookieStore(); @@ -1476,6 +1615,7 @@ REGISTER_TYPED_TEST_CASE_P(CookieStoreTest, SetCookieWithDetailsAsync, + SetCanonicalCookieTest, SetCookieWithDetailsSecureEnforcement, EmptyKeyTest, DomainTest,
diff --git a/services/service_manager/embedder/switches.cc b/services/service_manager/embedder/switches.cc index a4559d08..4e42a51 100644 --- a/services/service_manager/embedder/switches.cc +++ b/services/service_manager/embedder/switches.cc
@@ -32,7 +32,7 @@ const char kEnableLogging[] = "enable-logging"; // Indicates the type of process to run. This may be "service-manager", -// "service", or any other arbitrary value supported by the embedder. +// "service-runner", or any other arbitrary value supported by the embedder. const char kProcessType[] = "type"; // The value of the |kProcessType| switch which tells the executable to assume @@ -41,7 +41,7 @@ // The value of the |kProcessType| switch which tells the executable to assume // the role of a service instance. -const char kProcessTypeService[] = "service"; +const char kProcessTypeService[] = "service-runner"; // Describes the file descriptors passed to a child process in the following // list format:
diff --git a/services/ui/gpu/BUILD.gn b/services/ui/gpu/BUILD.gn index c7b669f..6deaf4b 100644 --- a/services/ui/gpu/BUILD.gn +++ b/services/ui/gpu/BUILD.gn
@@ -21,7 +21,6 @@ deps = [ "//cc", - "//components/viz/common", "//components/viz/service", "//gpu/ipc:command_buffer", "//gpu/ipc/common",
diff --git a/services/ui/gpu/gpu_main.cc b/services/ui/gpu/gpu_main.cc index e590b355..dd40807 100644 --- a/services/ui/gpu/gpu_main.cc +++ b/services/ui/gpu/gpu_main.cc
@@ -9,7 +9,6 @@ #include "base/message_loop/message_loop.h" #include "base/power_monitor/power_monitor_device_source.h" #include "base/single_thread_task_runner.h" -#include "components/viz/common/server_gpu_memory_buffer_manager.h" #include "components/viz/service/display_compositor/gpu_display_provider.h" #include "components/viz/service/frame_sinks/mojo_frame_sink_manager.h" #include "gpu/command_buffer/common/activity_flags.h" @@ -174,37 +173,22 @@ gpu_thread_task_runner_, gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(), gpu_service_->share_group()); - gpu::ImageFactory* image_factory = gpu_service_->gpu_image_factory(); - - // If the FrameSinkManager creation was delayed because GpuService had not - // been created yet, then this is called, in gpu thread, right after - // GpuService is created. - mojom::GpuServicePtr gpu_service; - BindGpuInternalOnGpuThread(mojo::MakeRequest(&gpu_service)); compositor_thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&GpuMain::CreateFrameSinkManagerOnCompositorThread, - base::Unretained(this), image_factory, - base::Passed(gpu_service.PassInterface()), - base::Passed(std::move(request)), - base::Passed(std::move(client_info)))); + FROM_HERE, + base::Bind(&GpuMain::CreateFrameSinkManagerOnCompositorThread, + base::Unretained(this), base::Passed(std::move(request)), + base::Passed(std::move(client_info)))); } void GpuMain::CreateFrameSinkManagerOnCompositorThread( - gpu::ImageFactory* image_factory, - mojom::GpuServicePtrInfo gpu_service_info, cc::mojom::FrameSinkManagerRequest request, cc::mojom::FrameSinkManagerClientPtrInfo client_info) { DCHECK(!frame_sink_manager_); cc::mojom::FrameSinkManagerClientPtr client; client.Bind(std::move(client_info)); - gpu_internal_.Bind(std::move(gpu_service_info)); - display_provider_ = base::MakeUnique<viz::GpuDisplayProvider>( - gpu_command_service_, - base::MakeUnique<viz::ServerGpuMemoryBufferManager>(gpu_internal_.get(), - 1 /* client_id */), - image_factory); + gpu_command_service_, gpu_service_->gpu_channel_manager()); frame_sink_manager_ = base::MakeUnique<viz::MojoFrameSinkManager>( true, display_provider_.get()); @@ -215,7 +199,6 @@ void GpuMain::TearDownOnCompositorThread() { frame_sink_manager_.reset(); display_provider_.reset(); - gpu_internal_.reset(); } void GpuMain::TearDownOnGpuThread() { @@ -242,10 +225,6 @@ } } -void GpuMain::BindGpuInternalOnGpuThread(mojom::GpuServiceRequest request) { - gpu_service_->Bind(std::move(request)); -} - void GpuMain::PreSandboxStartup() { // TODO(sad): https://crbug.com/645602 }
diff --git a/services/ui/gpu/gpu_main.h b/services/ui/gpu/gpu_main.h index 4b87174..bfc3c27 100644 --- a/services/ui/gpu/gpu_main.h +++ b/services/ui/gpu/gpu_main.h
@@ -15,7 +15,6 @@ namespace gpu { class GpuMemoryBufferFactory; -class ImageFactory; } namespace viz { @@ -55,15 +54,12 @@ cc::mojom::FrameSinkManagerRequest request, cc::mojom::FrameSinkManagerClientPtrInfo client_info); void CreateFrameSinkManagerOnCompositorThread( - gpu::ImageFactory* image_factory, - mojom::GpuServicePtrInfo gpu_service_info, cc::mojom::FrameSinkManagerRequest request, cc::mojom::FrameSinkManagerClientPtrInfo client_info); void CreateGpuServiceOnGpuThread(mojom::GpuServiceRequest request, mojom::GpuHostPtr gpu_host, const gpu::GpuPreferences& preferences, gpu::GpuProcessActivityFlags activity_flags); - void BindGpuInternalOnGpuThread(mojom::GpuServiceRequest request); void TearDownOnCompositorThread(); void TearDownOnGpuThread(); @@ -76,10 +72,6 @@ std::unique_ptr<gpu::GpuInit> gpu_init_; std::unique_ptr<GpuService> gpu_service_; - // The message-pipe used by the FrameSinkManager to request gpu memory - // buffers. - mojom::GpuServicePtr gpu_internal_; - // The InCommandCommandBuffer::Service used by the frame sink manager. scoped_refptr<gpu::InProcessCommandBuffer::Service> gpu_command_service_;
diff --git a/services/ui/gpu/gpu_service.h b/services/ui/gpu/gpu_service.h index 0cf5d3c..21b6c24e 100644 --- a/services/ui/gpu/gpu_service.h +++ b/services/ui/gpu/gpu_service.h
@@ -73,6 +73,9 @@ } gpu::ImageFactory* gpu_image_factory(); + gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory() { + return gpu_memory_buffer_factory_.get(); + } gpu::GpuWatchdogThread* watchdog_thread() { return watchdog_thread_.get(); }
diff --git a/testing/buildbot/filters/fuchsia.base_unittests.filter b/testing/buildbot/filters/fuchsia.base_unittests.filter index e2f8f85..8242149bc 100644 --- a/testing/buildbot/filters/fuchsia.base_unittests.filter +++ b/testing/buildbot/filters/fuchsia.base_unittests.filter
@@ -149,7 +149,6 @@ -ProcessTest.TerminateCurrentProcessImmediatelyWithNonZeroExitCode -ProcessTest.TerminateCurrentProcessImmediatelyWithZeroExitCode -ProcessTest.WaitForExitWithTimeout --ProcessUtilTest.CurrentDirectory -ProcessUtilTest.DelayedTermination -ProcessUtilTest.FDRemapping -ProcessUtilTest.GetAppOutput
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 6ae40072..b2bd6b07 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -18704,9 +18704,8 @@ crbug.com/591099 overflow/overflow-basic-005.html [ Failure Pass ] crbug.com/591099 overflow/overflow-basic-006.html [ Failure Pass ] crbug.com/591099 overflow/overflow-bug-chrome-ng-001.html [ Failure ] -crbug.com/591099 overflow/overflow-position-001.html [ Failure ] -crbug.com/591099 overflow/overflow-position-002.html [ Failure ] crbug.com/591099 overflow/overflow-position-003.html [ Failure ] +crbug.com/591099 overflow/overflow-position-004.html [ Failure ] crbug.com/591099 overflow/overflow-transform-001.html [ Failure Pass ] crbug.com/591099 paint/background/background-and-shadow.html [ Failure ] crbug.com/591099 paint/background/fieldset-legend-background-shadow-border-radius.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service index ac84c2b..24ea5cf 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
@@ -709,6 +709,11 @@ Bug(none) external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest.https.sub.html [ Failure Timeout ] Bug(none) external/wpt/payment-request/historical.https.html [ Failure Timeout ] Bug(none) external/wpt/payment-request/interfaces.https.html [ Failure Timeout ] +Bug(none) external/wpt/payment-request/payment-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html [ Timeout ] +Bug(none) external/wpt/payment-request/payment-allowed-by-feature-policy-attribute.https.sub.html [ Timeout ] +Bug(none) external/wpt/payment-request/payment-allowed-by-feature-policy.https.sub.html [ Timeout ] +Bug(none) external/wpt/payment-request/payment-default-feature-policy.https.sub.html [ Timeout ] +Bug(none) external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html [ Timeout ] Bug(none) external/wpt/payment-request/payment-request-abort-method.https.html [ Failure Timeout ] Bug(none) external/wpt/payment-request/payment-request-constructor-crash.https.html [ Failure Timeout ] Bug(none) external/wpt/payment-request/payment-request-constructor.https.html [ Failure Timeout ] @@ -1497,6 +1502,7 @@ Bug(none) external/wpt/websockets/Secure-Send-binary-blob.htm [ Failure Timeout ] Bug(none) external/wpt/websockets/Send-binary-blob.htm [ Failure Timeout ] Bug(none) external/wpt/webusb/idlharness.https.html [ Failure Timeout ] +Bug(none) external/wpt/webusb/usb-allowed-by-feature-policy-attribute-redirect-on-load.https.sub.html [ Timeout ] Bug(none) external/wpt/webusb/usb-allowed-by-feature-policy-attribute.https.sub.html [ Failure Timeout ] Bug(none) external/wpt/webusb/usb-allowed-by-feature-policy.https.sub.html [ Failure Timeout ] Bug(none) external/wpt/webusb/usb-default-feature-policy.https.sub.html [ Failure Timeout ] @@ -3312,6 +3318,7 @@ Bug(none) webaudio/unit-tests/audit.html [ Timeout ] Bug(none) webshare/share-arity.html [ Timeout ] Bug(none) webshare/share-error.html [ Timeout ] +Bug(none) webshare/share-nonutf8-encoding.html [ Timeout ] Bug(none) webshare/share-success.html [ Timeout ] Bug(none) webshare/share-types.html [ Timeout ] Bug(none) webshare/share-without-user-gesture.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index c5f934ba..59114103 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -759,9 +759,8 @@ crbug.com/724701 virtual/layout_ng/overflow/overflow-basic-004.html [ Failure ] crbug.com/728378 virtual/layout_ng/overflow/overflow-bug-chrome-ng-001.html [ Failure ] crbug.com/728378 virtual/layout_ng/overflow/overflow-transform-002.html [ Failure ] -crbug.com/728378 virtual/layout_ng/overflow/overflow-position-001.html [ Failure ] -crbug.com/728378 virtual/layout_ng/overflow/overflow-position-002.html [ Failure ] crbug.com/728378 virtual/layout_ng/overflow/overflow-position-003.html [ Failure ] +crbug.com/728378 virtual/layout_ng/overflow/overflow-position-004.html [ Failure ] # ====== LayoutNG-only failures until here ======
diff --git a/third_party/WebKit/LayoutTests/overflow/overflow-position-004.html b/third_party/WebKit/LayoutTests/overflow/overflow-position-004.html new file mode 100644 index 0000000..33347c0 --- /dev/null +++ b/third_party/WebKit/LayoutTests/overflow/overflow-position-004.html
@@ -0,0 +1,50 @@ +<!doctype html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<style> +html, body { + margin: 0; padding: 0; +} +#container { + overflow: scroll; + direction: rtl; + position: relative; + width: 200px; + height: 200px; + box-shadow: 0px 0px 12px 0px black; +} +#target { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 100px; + background-color: green; +} +</style> +<p>Overflow: origin of absolutely positioned child with rtl parent with scrollbars should be next to scrollbar</p> +<div id="container"> + <div id="target">foo</div> +</div> +<script> + +var container = document.querySelector('#container'); +var target = document.querySelector('#target'); + +function getTargetOffset() { + var containerRect = container.getBoundingClientRect(); + var targetRect = target.getBoundingClientRect(); + return { + top: targetRect.top - containerRect.top, + left: targetRect.left - containerRect.left + } +} + +test(function() { + var targetOffset = getTargetOffset(); + assert_equals(targetOffset.top, container.clientTop, "top"); + assert_equals(targetOffset.left, container.clientLeft, "left"); +}, "absolute position with rtl scrollbars"); + +</script> +
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index 3f9bd30..84fd9da 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -314,13 +314,12 @@ // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes. // It seems to crash because Frame is detached before LocalFrameView. // Verify here that any LocalFrameView has been detached by now. - CHECK(!view_->IsAttached()); - if (HTMLFrameOwnerElement* owner = DeprecatedLocalOwner()) { - if (EmbeddedContentView* owner_view = owner->OwnedEmbeddedContentView()) { - CHECK(!owner_view->IsAttached()); - CHECK_EQ(owner_view, view_); - } + if (view_->IsAttached()) { + CHECK(DeprecatedLocalOwner()); + CHECK(DeprecatedLocalOwner()->OwnedEmbeddedContentView()); + CHECK_EQ(view_, DeprecatedLocalOwner()->OwnedEmbeddedContentView()); } + CHECK(!view_->IsAttached()); SetView(nullptr);
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameClient.h b/third_party/WebKit/Source/core/frame/LocalFrameClient.h index 979bc3a..0ebbbbe 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameClient.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameClient.h
@@ -225,11 +225,6 @@ virtual WebRemotePlaybackClient* CreateWebRemotePlaybackClient( HTMLMediaElement&) = 0; - virtual ObjectContentType GetObjectContentType( - const KURL&, - const String& mime_type, - bool should_prefer_plug_ins_for_images) = 0; - virtual void DidCreateNewDocument() = 0; virtual void DispatchDidClearWindowObjectInMainWorld() = 0; virtual void DocumentElementAvailable() = 0;
diff --git a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp index 891cff3..1a88683 100644 --- a/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLEmbedElement.cpp
@@ -175,7 +175,7 @@ service_type_ = "text/html"; } - RequestObject(url_, service_type_, param_names, param_values); + RequestObject(param_names, param_values); } bool HTMLEmbedElement::LayoutObjectIsNeeded(const ComputedStyle& style) {
diff --git a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp index e961096..d31992b 100644 --- a/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp
@@ -241,6 +241,12 @@ return; if (embedded_content_view_) { + // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout + // crashes. Perhaps view is getting reattached while document is shutting + // down. + if (doc) { + CHECK_NE(doc->Lifecycle().GetState(), DocumentLifecycle::kStopping); + } layout_embedded_content_item.UpdateOnEmbeddedContentViewChange(); DCHECK_EQ(GetDocument().View(),
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp index 24d4f76..30cf907 100644 --- a/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.cpp
@@ -148,11 +148,8 @@ // TODO(schenney): crbug.com/572908 This function should not deal with url or // serviceType! void HTMLObjectElement::ParametersForPlugin(Vector<String>& param_names, - Vector<String>& param_values, - String& url, - String& service_type) { + Vector<String>& param_values) { HashSet<StringImpl*, CaseFoldingHash> unique_param_names; - String url_parameter; // Scan the PARAM children and store their name/value pairs. // Get the URL and type from the params if we don't already have them. @@ -168,35 +165,25 @@ // TODO(schenney): crbug.com/572908 url adjustment does not belong in this // function. - if (url.IsEmpty() && url_parameter.IsEmpty() && - (DeprecatedEqualIgnoringCase(name, "src") || - DeprecatedEqualIgnoringCase(name, "movie") || - DeprecatedEqualIgnoringCase(name, "code") || - DeprecatedEqualIgnoringCase(name, "url"))) - url_parameter = StripLeadingAndTrailingHTMLSpaces(p->Value()); + // HTML5 says that an object resource's URL is specified by the object's + // data attribute, not by a param element. However, for compatibility, allow + // the resource's URL to be given by a param named "src", "movie", "code" or + // "url" if we know that resource points to a plugin. + if (url_.IsEmpty() && (DeprecatedEqualIgnoringCase(name, "src") || + DeprecatedEqualIgnoringCase(name, "movie") || + DeprecatedEqualIgnoringCase(name, "code") || + DeprecatedEqualIgnoringCase(name, "url"))) { + url_ = StripLeadingAndTrailingHTMLSpaces(p->Value()); + } // TODO(schenney): crbug.com/572908 serviceType calculation does not belong // in this function. - if (service_type.IsEmpty() && DeprecatedEqualIgnoringCase(name, "type")) { - service_type = p->Value(); - size_t pos = service_type.Find(";"); + if (service_type_.IsEmpty() && DeprecatedEqualIgnoringCase(name, "type")) { + size_t pos = p->Value().Find(";"); if (pos != kNotFound) - service_type = service_type.Left(pos); + service_type_ = p->Value().GetString().Left(pos); } } - // When OBJECT is used for an applet via Sun's Java plugin, the CODEBASE - // attribute in the tag points to the Java plugin itself (an ActiveX - // component) while the actual applet CODEBASE is in a PARAM tag. See - // <http://java.sun.com/products/plugin/1.2/docs/tags.html>. This means we - // have to explicitly suppress the tag's CODEBASE attribute if there is none - // in a PARAM, else our Java plugin will misinterpret it. [4004531] - String codebase; - if (MIMETypeRegistry::IsJavaAppletMIMEType(service_type)) { - codebase = "codebase"; - unique_param_names.insert( - codebase.Impl()); // pretend we found it in a PARAM already - } - // Turn the attributes of the <object> element into arrays, but don't override // <param> values. AttributeCollection attributes = this->Attributes(); @@ -209,17 +196,6 @@ } MapDataParamToSrc(¶m_names, ¶m_values); - - // HTML5 says that an object resource's URL is specified by the object's data - // attribute, not by a param element. However, for compatibility, allow the - // resource's URL to be given by a param named "src", "movie", "code" or "url" - // if we know that resource points to a plugin. - if (url.IsEmpty() && !url_parameter.IsEmpty()) { - KURL completed_url = GetDocument().CompleteURL(url_parameter); - bool use_fallback; - if (ShouldUsePlugin(completed_url, service_type, false, use_fallback)) - url = url_parameter; - } } bool HTMLObjectElement::HasFallbackContent() const { @@ -292,17 +268,14 @@ return; } - String url = this->Url(); - String service_type = service_type_; - // TODO(schenney): crbug.com/572908 These should be joined into a // PluginParameters class. Vector<String> param_names; Vector<String> param_values; - ParametersForPlugin(param_names, param_values, url, service_type); + ParametersForPlugin(param_names, param_values); // Note: url is modified above by parametersForPlugin. - if (!AllowedToLoadFrameURL(url)) { + if (!AllowedToLoadFrameURL(url_)) { DispatchErrorEvent(); return; } @@ -317,13 +290,12 @@ GetDocument().GetFrame()->Loader().Client()->OverrideFlashEmbedWithHTML( GetDocument().CompleteURL(url_)); if (!overriden_url.IsEmpty()) { - url = url_ = overriden_url.GetString(); - service_type = service_type_ = "text/html"; + url_ = overriden_url.GetString(); + service_type_ = "text/html"; } - if (!HasValidClassId() || - !RequestObject(url, service_type, param_names, param_values)) { - if (!url.IsEmpty()) + if (!HasValidClassId() || !RequestObject(param_names, param_values)) { + if (!url_.IsEmpty()) DispatchErrorEvent(); if (HasFallbackContent()) RenderFallbackContent();
diff --git a/third_party/WebKit/Source/core/html/HTMLObjectElement.h b/third_party/WebKit/Source/core/html/HTMLObjectElement.h index 673f1a4..ee887df 100644 --- a/third_party/WebKit/Source/core/html/HTMLObjectElement.h +++ b/third_party/WebKit/Source/core/html/HTMLObjectElement.h
@@ -110,9 +110,7 @@ // FIXME: This function should not deal with url or serviceType // so that we can better share code between <object> and <embed>. void ParametersForPlugin(Vector<String>& param_names, - Vector<String>& param_values, - String& url, - String& service_type); + Vector<String>& param_values); bool HasValidClassId() const;
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp index 660e159..0dd0ce0 100644 --- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.cpp
@@ -118,23 +118,22 @@ } bool HTMLPlugInElement::RequestObjectInternal( - const String& url, - const String& mime_type, const Vector<String>& param_names, const Vector<String>& param_values) { - if (url.IsEmpty() && mime_type.IsEmpty()) + if (url_.IsEmpty() && service_type_.IsEmpty()) return false; - if (ProtocolIsJavaScript(url)) + if (ProtocolIsJavaScript(url_)) return false; - KURL completed_url = url.IsEmpty() ? KURL() : GetDocument().CompleteURL(url); - if (!AllowedToLoadObject(completed_url, mime_type)) + KURL completed_url = + url_.IsEmpty() ? KURL() : GetDocument().CompleteURL(url_); + if (!AllowedToLoadObject(completed_url, service_type_)) return false; - bool use_fallback; - if (!ShouldUsePlugin(completed_url, mime_type, HasFallbackContent(), - use_fallback)) { + ObjectContentType object_type = GetObjectContentType(); + if (object_type == ObjectContentType::kFrame || + object_type == ObjectContentType::kImage) { // If the plugin element already contains a subframe, // loadOrRedirectSubframe will re-use it. Otherwise, it will create a // new frame and set it as the LayoutEmbeddedContent's EmbeddedContentView, @@ -142,7 +141,11 @@ return LoadOrRedirectSubframe(completed_url, GetNameAttribute(), true); } - return LoadPlugin(completed_url, mime_type, param_names, param_values, + // If an object's content can't be handled and it has no fallback, let + // it be handled as a plugin to show the broken plugin icon. + bool use_fallback = + object_type == ObjectContentType::kNone && HasFallbackContent(); + return LoadPlugin(completed_url, service_type_, param_names, param_values, use_fallback, true); } @@ -194,7 +197,7 @@ image_loader_->UpdateFromElement(); } else if (NeedsPluginUpdate() && !GetLayoutEmbeddedItem().IsNull() && !GetLayoutEmbeddedItem().ShowsUnavailablePluginIndicator() && - !WouldLoadAsNetscapePlugin(url_, service_type_) && + GetObjectContentType() != ObjectContentType::kPlugin && !is_delaying_load_event_) { is_delaying_load_event_ = true; GetDocument().IncrementLoadEventDelayCount(); @@ -485,17 +488,46 @@ return plugin_is_available_; } +HTMLPlugInElement::ObjectContentType HTMLPlugInElement::GetObjectContentType() { + String mime_type = service_type_; + KURL url = GetDocument().CompleteURL(url_); + if (mime_type.IsEmpty()) { + // Try to guess the MIME type based off the extension. + String filename = url.LastPathComponent(); + int extension_pos = filename.ReverseFind('.'); + if (extension_pos >= 0) { + String extension = filename.Substring(extension_pos + 1); + mime_type = MIMETypeRegistry::GetWellKnownMIMETypeForExtension(extension); + } + + if (mime_type.IsEmpty()) + return ObjectContentType::kFrame; + } + + // If Chrome is started with the --disable-plugins switch, pluginData is 0. + PluginData* plugin_data = GetDocument().GetFrame()->GetPluginData(); + bool plugin_supports_mime_type = + plugin_data && plugin_data->SupportsMimeType(mime_type); + + if (MIMETypeRegistry::IsSupportedImageMIMEType(mime_type)) { + return should_prefer_plug_ins_for_images_ && plugin_supports_mime_type + ? ObjectContentType::kPlugin + : ObjectContentType::kImage; + } + + if (plugin_supports_mime_type) + return ObjectContentType::kPlugin; + if (MIMETypeRegistry::IsSupportedNonImageMIMEType(mime_type)) + return ObjectContentType::kFrame; + return ObjectContentType::kNone; +} + bool HTMLPlugInElement::IsImageType() { if (service_type_.IsEmpty() && ProtocolIs(url_, "data")) service_type_ = MimeTypeFromDataURL(url_); - if (LocalFrame* frame = GetDocument().GetFrame()) { - KURL completed_url = GetDocument().CompleteURL(url_); - return frame->Loader().Client()->GetObjectContentType( - completed_url, service_type_, ShouldPreferPlugInsForImages()) == - kObjectContentImage; - } - + if (GetDocument().GetFrame()) + return GetObjectContentType() == ObjectContentType::kImage; return Image::SupportsType(service_type_); } @@ -516,25 +548,9 @@ ContentFrame()->GetSecurityContext()->GetSecurityOrigin())); } -// We don't use m_url, or m_serviceType as they may not be the final values -// that <object> uses depending on <param> values. -bool HTMLPlugInElement::WouldLoadAsNetscapePlugin(const String& url, - const String& service_type) { - DCHECK(GetDocument().GetFrame()); - KURL completed_url; - if (!url.IsEmpty()) - completed_url = GetDocument().CompleteURL(url); - return GetDocument().GetFrame()->Loader().Client()->GetObjectContentType( - completed_url, service_type, ShouldPreferPlugInsForImages()) == - kObjectContentNetscapePlugin; -} - -bool HTMLPlugInElement::RequestObject(const String& url, - const String& mime_type, - const Vector<String>& param_names, +bool HTMLPlugInElement::RequestObject(const Vector<String>& param_names, const Vector<String>& param_values) { - bool result = - RequestObjectInternal(url, mime_type, param_names, param_values); + bool result = RequestObjectInternal(param_names, param_values); DEFINE_STATIC_LOCAL( EnumerationHistogram, result_histogram, @@ -609,20 +625,6 @@ return true; } -bool HTMLPlugInElement::ShouldUsePlugin(const KURL& url, - const String& mime_type, - bool has_fallback, - bool& use_fallback) { - ObjectContentType object_type = - GetDocument().GetFrame()->Loader().Client()->GetObjectContentType( - url, mime_type, ShouldPreferPlugInsForImages()); - // If an object's content can't be handled and it has no fallback, let - // it be handled as a plugin to show the broken plugin icon. - use_fallback = object_type == kObjectContentNone && has_fallback; - return object_type == kObjectContentNone || - object_type == kObjectContentNetscapePlugin; -} - void HTMLPlugInElement::DispatchErrorEvent() { if (GetDocument().IsPluginDocument() && GetDocument().LocalOwner()) GetDocument().LocalOwner()->DispatchEvent(
diff --git a/third_party/WebKit/Source/core/html/HTMLPlugInElement.h b/third_party/WebKit/Source/core/html/HTMLPlugInElement.h index 6e41930..0176d2f8 100644 --- a/third_party/WebKit/Source/core/html/HTMLPlugInElement.h +++ b/third_party/WebKit/Source/core/html/HTMLPlugInElement.h
@@ -109,19 +109,10 @@ virtual LayoutEmbeddedContent* LayoutEmbeddedContentForJSBindings() const; bool IsImageType(); - bool ShouldPreferPlugInsForImages() const { - return should_prefer_plug_ins_for_images_; - } LayoutEmbeddedItem GetLayoutEmbeddedItem() const; bool AllowedToLoadFrameURL(const String& url); - bool RequestObject(const String& url, - const String& mime_type, - const Vector<String>& param_names, + bool RequestObject(const Vector<String>& param_names, const Vector<String>& param_values); - bool ShouldUsePlugin(const KURL&, - const String& mime_type, - bool has_fallback, - bool& use_fallback); void DispatchErrorEvent(); bool IsErrorplaceholder(); @@ -176,13 +167,18 @@ bool AllowedToLoadPlugin(const KURL&, const String& mime_type); // Perform checks based on the URL and MIME-type of the object to load. bool AllowedToLoadObject(const KURL&, const String& mime_type); - bool WouldLoadAsNetscapePlugin(const String& url, const String& service_type); + + enum class ObjectContentType { + kNone, + kImage, + kFrame, + kPlugin, + }; + ObjectContentType GetObjectContentType(); void SetPersistedPlugin(PluginView*); - bool RequestObjectInternal(const String& url, - const String& mime_type, - const Vector<String>& param_names, + bool RequestObjectInternal(const Vector<String>& param_names, const Vector<String>& param_values); v8::Global<v8::Object> plugin_wrapper_;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc index 8747903..d9ca861b 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -172,7 +172,7 @@ if (known_fragment_offset) return known_fragment_offset.value() - ContainerBfcOffset(); LayoutUnit inline_offset = - border_and_padding_.inline_start + child_margins.inline_start; + border_scrollbar_padding_.inline_start + child_margins.inline_start; // TODO(ikilpatrick): Using the content_size_ here looks suspicious - check. return {inline_offset, content_size_}; } @@ -182,9 +182,9 @@ if (NeedMinMaxContentSize(ConstraintSpace(), Style())) min_max_size = ComputeMinMaxContentSize(); - border_and_padding_ = ComputeBorders(ConstraintSpace(), Style()) + - ComputePadding(ConstraintSpace(), Style()); - + border_scrollbar_padding_ = ComputeBorders(ConstraintSpace(), Style()) + + ComputePadding(ConstraintSpace(), Style()) + + GetScrollbarSizes(Node().GetLayoutObject()); // TODO(layout-ng): For quirks mode, should we pass blockSize instead of -1? NGLogicalSize size( ComputeInlineSizeForFragment(ConstraintSpace(), Style(), min_max_size), @@ -195,10 +195,13 @@ // If so, just leave the size as NGSizeIndefinite instead of subtracting // borders and padding. NGLogicalSize adjusted_size(size); - if (size.block_size == NGSizeIndefinite) - adjusted_size.inline_size -= border_and_padding_.InlineSum(); - else - adjusted_size -= border_and_padding_; + if (size.block_size == NGSizeIndefinite) { + adjusted_size.inline_size -= border_scrollbar_padding_.InlineSum(); + } else { + adjusted_size -= border_scrollbar_padding_; + adjusted_size.block_size = std::max(adjusted_size.block_size, LayoutUnit()); + } + adjusted_size.inline_size = std::max(adjusted_size.inline_size, LayoutUnit()); child_available_size_ = adjusted_size; child_percentage_size_ = adjusted_size; @@ -216,7 +219,8 @@ // If we are resuming from a break token our start border and padding is // within a previous fragment. - content_size_ = BreakToken() ? LayoutUnit() : border_and_padding_.block_start; + content_size_ = + BreakToken() ? LayoutUnit() : border_scrollbar_padding_.block_start; NGMarginStrut input_margin_strut = ConstraintSpace().MarginStrut(); LayoutUnit input_bfc_block_offset = @@ -225,7 +229,7 @@ // Margins collapsing: // Do not collapse margins between parent and its child if there is // border/padding between them. - if (border_and_padding_.block_start) { + if (border_scrollbar_padding_.block_start) { input_bfc_block_offset += input_margin_strut.Sum(); MaybeUpdateFragmentBfcOffset(ConstraintSpace(), input_bfc_block_offset, &container_builder_); @@ -285,8 +289,8 @@ // Bottom margins of an in-flow block box doesn't collapse with its last // in-flow block-level child's bottom margin if the box has bottom // border/padding. - content_size_ += border_and_padding_.block_end; - if (border_and_padding_.block_end || + content_size_ += border_scrollbar_padding_.block_end; + if (border_scrollbar_padding_.block_end || ConstraintSpace().IsNewFormattingContext()) { content_size_ += end_margin_strut.Sum(); end_margin_strut = NGMarginStrut(); @@ -318,7 +322,6 @@ end_margin_strut = NGMarginStrut(); } container_builder_.SetEndMarginStrut(end_margin_strut); - container_builder_.SetOverflowSize( NGLogicalSize(max_inline_size_, content_size_)); @@ -335,7 +338,7 @@ void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned( const NGPreviousInflowPosition& previous_inflow_position, NGBlockNode child) { - NGLogicalOffset offset = {border_and_padding_.inline_start, + NGLogicalOffset offset = {border_scrollbar_padding_.inline_start, previous_inflow_position.logical_block_offset}; // We only include the margin strut in the OOF static-position if we know we @@ -354,7 +357,7 @@ NGBoxStrut margins = CalculateMargins(child); NGLogicalOffset origin_offset = constraint_space_->BfcOffset(); - origin_offset.inline_offset += border_and_padding_.inline_start; + origin_offset.inline_offset += border_scrollbar_padding_.inline_start; RefPtr<NGUnpositionedFloat> unpositioned_float = NGUnpositionedFloat::Create( child_available_size_, child_percentage_size_, origin_offset, constraint_space_->BfcOffset(), margins, child, token); @@ -410,7 +413,7 @@ NGLogicalOffset child_bfc_offset = { ConstraintSpace().BfcOffset().inline_offset + - border_and_padding_.inline_start + margins.inline_start, + border_scrollbar_padding_.inline_start + margins.inline_start, bfc_block_offset}; bool is_new_fc = IsNewFormattingContextForBlockLevelChild(Style(), child); @@ -485,7 +488,7 @@ content_size_, logical_offset.block_offset + fragment.BlockSize()); max_inline_size_ = std::max( max_inline_size_, fragment.InlineSize() + child_data.margins.InlineSum() + - border_and_padding_.InlineSum()); + border_scrollbar_padding_.InlineSum()); container_builder_.AddChild(layout_result, logical_offset); @@ -530,7 +533,7 @@ container_builder_.UnpositionedFloats(), tmp_space.Get()); NGLogicalOffset origin_offset = {ConstraintSpace().BfcOffset().inline_offset + - border_and_padding_.inline_start, + border_scrollbar_padding_.inline_start, child_bfc_offset_estimate}; AdjustToClearance( GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()), @@ -557,7 +560,7 @@ MutableConstraintSpace()); origin_offset = {ConstraintSpace().BfcOffset().inline_offset + - border_and_padding_.inline_start, + border_scrollbar_padding_.inline_start, child_bfc_offset_estimate}; AdjustToClearance( GetClearanceOffset(ConstraintSpace().Exclusions(), child_style.Clear()), @@ -597,7 +600,8 @@ NGLogicalOffset bfc_offset = { ConstraintSpace().BfcOffset().inline_offset + - border_and_padding_.inline_start + child_data.margins.inline_start, + border_scrollbar_padding_.inline_start + + child_data.margins.inline_start, child_data.bfc_offset_estimate.block_offset + margin_strut.Sum()}; AdjustToClearance(space.ClearanceOffset(), &bfc_offset); PositionPendingFloatsFromOffset(bfc_offset.block_offset, @@ -610,7 +614,7 @@ const NGConstraintSpace& child_space, const NGInflowChildData& child_data) { NGLogicalOffset bfc_offset = {ConstraintSpace().BfcOffset().inline_offset + - border_and_padding_.inline_start + + border_scrollbar_padding_.inline_start + child_data.margins.inline_start, child_data.bfc_offset_estimate.block_offset}; AdjustToClearance(child_space.ClearanceOffset(), &bfc_offset);
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h index d77086d..1e1a584 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.h
@@ -131,7 +131,7 @@ NGLogicalSize child_available_size_; NGLogicalSize child_percentage_size_; - NGBoxStrut border_and_padding_; + NGBoxStrut border_scrollbar_padding_; LayoutUnit content_size_; LayoutUnit max_inline_size_; };
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc index aa69d04..645a908 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_node.cc
@@ -250,18 +250,18 @@ NGLayoutResult* layout_result) { NGPhysicalBoxFragment* physical_fragment = ToNGPhysicalBoxFragment(layout_result->PhysicalFragment().Get()); - if (box_->Style()->SpecifiesColumns()) UpdateLegacyMultiColumnFlowThread(box_, physical_fragment); box_->SetWidth(physical_fragment->Size().width); box_->SetHeight(physical_fragment->Size().height); - NGBoxStrut border_and_padding = ComputeBorders(constraint_space, Style()) + - ComputePadding(constraint_space, Style()); + NGBoxStrut border_scrollbar_padding = + ComputeBorders(constraint_space, Style()) + + ComputePadding(constraint_space, Style()) + GetScrollbarSizes(box_); LayoutUnit intrinsic_logical_height = box_->Style()->IsHorizontalWritingMode() ? physical_fragment->OverflowSize().height : physical_fragment->OverflowSize().width; - intrinsic_logical_height -= border_and_padding.BlockSum(); + intrinsic_logical_height -= border_scrollbar_padding.BlockSum(); box_->SetIntrinsicContentLogicalHeight(intrinsic_logical_height); // TODO(ikilpatrick) is this the right thing to do? @@ -289,7 +289,7 @@ FromPlatformWritingMode(Style().GetWritingMode()); NGBoxFragment fragment(writing_mode, physical_fragment); ToLayoutBlock(box_)->ComputeOverflow(fragment.OverflowSize().block_size - - border_and_padding.block_end); + border_scrollbar_padding.block_end); } box_->UpdateAfterLayout();
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc index c42696b5..368e872 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -181,6 +181,7 @@ NGLogicalSize available_size{inline_size, block_size}; + // TODO(atotic) will need to be adjusted for scrollbars. NGConstraintSpaceBuilder builder(writing_mode); builder.SetAvailableSize(available_size); builder.SetPercentageResolutionSize(container_size);
diff --git a/third_party/WebKit/Source/core/loader/EmptyClients.h b/third_party/WebKit/Source/core/loader/EmptyClients.h index d66d8e41..7fc7ecf 100644 --- a/third_party/WebKit/Source/core/loader/EmptyClients.h +++ b/third_party/WebKit/Source/core/loader/EmptyClients.h
@@ -340,12 +340,6 @@ WebRemotePlaybackClient* CreateWebRemotePlaybackClient( HTMLMediaElement&) override; - ObjectContentType GetObjectContentType(const KURL&, - const String&, - bool) override { - return ObjectContentType(); - } - void DidCreateNewDocument() override {} void DispatchDidClearWindowObjectInMainWorld() override {} void DocumentElementAvailable() override {}
diff --git a/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h b/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h index 97a514633..67fff48 100644 --- a/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h +++ b/third_party/WebKit/Source/core/loader/FrameLoaderTypes.h
@@ -51,13 +51,6 @@ kNavigationTypeOther }; -enum ObjectContentType { - kObjectContentNone, - kObjectContentImage, - kObjectContentFrame, - kObjectContentNetscapePlugin, -}; - enum ShouldSendReferrer { kMaybeSendReferrer, kNeverSendReferrer }; enum ShouldSetOpener { kMaybeSetOpener, kNeverSetOpener };
diff --git a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp index 067834f1..5e3ad60 100644 --- a/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp +++ b/third_party/WebKit/Source/platform/graphics/OffscreenCanvasFrameDispatcherImpl.cpp
@@ -497,23 +497,11 @@ if (it == resources_.end()) continue; - if (it->value->image_) { - if (it->value->image_->HasMailbox()) { - it->value->image_->UpdateSyncToken(resource.sync_token); - } else if (SharedGpuContext::IsValid() && resource.sync_token.HasData()) { - // Although image has MailboxTextureHolder at the time when it is - // inserted to m_cachedImages, the - // OffscreenCanvasPlaceHolder::placeholderFrame() exposes this image - // to everyone accessing the placeholder canvas as an image source, - // some of which may want to consume the image as a SkImage, thereby - // converting the MailTextureHolder to a SkiaTextureHolder. In this - // case, we need to wait for the new sync token passed by - // CompositorFrameSink. - SharedGpuContext::Gl()->WaitSyncTokenCHROMIUM( - resource.sync_token.GetConstData()); - } - ReclaimResourceInternal(it); + if (SharedGpuContext::IsValid() && resource.sync_token.HasData()) { + SharedGpuContext::Gl()->WaitSyncTokenCHROMIUM( + resource.sync_token.GetConstData()); } + ReclaimResourceInternal(it); } }
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp index 8eaa0b6..3dc9df2 100644 --- a/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp +++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.cpp
@@ -81,7 +81,6 @@ #include "platform/feature_policy/FeaturePolicy.h" #include "platform/loader/fetch/ResourceFetcher.h" #include "platform/network/HTTPParsers.h" -#include "platform/network/mime/MIMETypeRegistry.h" #include "platform/plugins/PluginData.h" #include "platform/wtf/PtrUtil.h" #include "platform/wtf/StringExtras.h" @@ -854,47 +853,6 @@ return HTMLMediaElementRemotePlayback::remote(html_media_element); } -ObjectContentType LocalFrameClientImpl::GetObjectContentType( - const KURL& url, - const String& explicit_mime_type, - bool should_prefer_plug_ins_for_images) { - // This code is based on Apple's implementation from - // WebCoreSupport/WebFrameBridge.mm. - - String mime_type = explicit_mime_type; - if (mime_type.IsEmpty()) { - // Try to guess the MIME type based off the extension. - String filename = url.LastPathComponent(); - int extension_pos = filename.ReverseFind('.'); - if (extension_pos >= 0) { - String extension = filename.Substring(extension_pos + 1); - mime_type = MIMETypeRegistry::GetWellKnownMIMETypeForExtension(extension); - } - - if (mime_type.IsEmpty()) - return kObjectContentFrame; - } - - // If Chrome is started with the --disable-plugins switch, pluginData is 0. - PluginData* plugin_data = web_frame_->GetFrame()->GetPluginData(); - bool plug_in_supports_mime_type = - plugin_data && plugin_data->SupportsMimeType(mime_type); - - if (MIMETypeRegistry::IsSupportedImageMIMEType(mime_type)) { - return should_prefer_plug_ins_for_images && plug_in_supports_mime_type - ? kObjectContentNetscapePlugin - : kObjectContentImage; - } - - if (plug_in_supports_mime_type) - return kObjectContentNetscapePlugin; - - if (MIMETypeRegistry::IsSupportedNonImageMIMEType(mime_type)) - return kObjectContentFrame; - - return kObjectContentNone; -} - WebCookieJar* LocalFrameClientImpl::CookieJar() const { if (!web_frame_->Client()) return 0;
diff --git a/third_party/WebKit/Source/web/LocalFrameClientImpl.h b/third_party/WebKit/Source/web/LocalFrameClientImpl.h index 5ef26bd..f96edc5 100644 --- a/third_party/WebKit/Source/web/LocalFrameClientImpl.h +++ b/third_party/WebKit/Source/web/LocalFrameClientImpl.h
@@ -169,10 +169,6 @@ WebMediaPlayerClient*) override; WebRemotePlaybackClient* CreateWebRemotePlaybackClient( HTMLMediaElement&) override; - ObjectContentType GetObjectContentType( - const KURL&, - const WTF::String& mime_type, - bool should_prefer_plug_ins_for_images) override; void DidChangeScrollOffset() override; void DidUpdateCurrentHistoryItem() override;
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py index 91a8f17..fada685 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/layout_tests/port/server_process_unittest.py
@@ -60,6 +60,9 @@ self._server_process.broken_pipes.append(self) raise IOError + def read(self): + return '' + def close(self): self.closed = True
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 196c83b..ceabedd0 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -32360,8 +32360,9 @@ <enum name="SBClientPhishingSkipClassificationReason"> <int value="0" label="Not skipped"/> - <int value="1" label="Skipped: HTTPS"/> + <int value="1" label="(Deprecated) Skipped: HTTPS"/> <int value="2" label="Skipped: Not a GET request"/> + <int value="3" label="Skipped: Unsupported scheme"/> </enum> <enum name="SBDownloadFeedbackUploadResult"> @@ -35962,7 +35963,7 @@ <int value="3" label="Infobar dismissed"/> </enum> -<enum name="ThumbnailTopSitesEvent" type="int"> +<enum name="ThumbnailTopSitesEvent"> <int value="0" label="Not added: Failure"/> <int value="1" label="Not added: TopSites is full"/> <int value="2" label="Not added: Existing thumbnail is better"/>
diff --git a/ui/gfx/icc_profile_mac.mm b/ui/gfx/icc_profile_mac.mm index 1aa768cc..70b899a 100644 --- a/ui/gfx/icc_profile_mac.mm +++ b/ui/gfx/icc_profile_mac.mm
@@ -4,9 +4,20 @@ #include "ui/gfx/icc_profile.h" +#include <AvailabilityMacros.h> + #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" +#if defined(MAC_OS_X_VERSION_10_13) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 +// https://crbug.com/729896, https://openradar.appspot.com/32883726 +#undef CGColorSpaceCopyICCProfile +extern "C" { +CFDataRef CGColorSpaceCopyICCProfile(CGColorSpaceRef); +} // extern "C" +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 + namespace gfx { // static
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc index 606c345a..3cf9b60 100644 --- a/ui/gfx/mac/io_surface.cc +++ b/ui/gfx/mac/io_surface.cc
@@ -4,6 +4,7 @@ #include "ui/gfx/mac/io_surface.h" +#include <AvailabilityMacros.h> #include <stddef.h> #include <stdint.h> @@ -17,6 +18,15 @@ #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/color_space_switches.h" +#if defined(MAC_OS_X_VERSION_10_13) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 +// https://crbug.com/729896, https://openradar.appspot.com/32883726 +#undef CGColorSpaceCopyICCProfile +extern "C" { +CFDataRef CGColorSpaceCopyICCProfile(CGColorSpaceRef); +} // extern "C" +#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 + namespace gfx { namespace {
diff --git a/ui/ozone/demo/BUILD.gn b/ui/ozone/demo/BUILD.gn index b284dc9..ad191666 100644 --- a/ui/ozone/demo/BUILD.gn +++ b/ui/ozone/demo/BUILD.gn
@@ -25,6 +25,7 @@ deps = [ "//base", "//build/config:exe_and_shlib_deps", + "//components/tracing:startup_tracing", "//skia", "//ui/display/types", "//ui/events",
diff --git a/ui/ozone/demo/DEPS b/ui/ozone/demo/DEPS index f59fd384..2dbcda8 100644 --- a/ui/ozone/demo/DEPS +++ b/ui/ozone/demo/DEPS
@@ -1,3 +1,4 @@ include_rules = [ + "+components/tracing", "+ui/gl", ]
diff --git a/ui/ozone/demo/ozone_demo.cc b/ui/ozone/demo/ozone_demo.cc index d14c60cc..1977457 100644 --- a/ui/ozone/demo/ozone_demo.cc +++ b/ui/ozone/demo/ozone_demo.cc
@@ -12,6 +12,9 @@ #include "base/run_loop.h" #include "base/task_scheduler/task_scheduler.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/trace_event/trace_event.h" +#include "components/tracing/common/trace_to_console.h" +#include "components/tracing/common/tracing_switches.h" #include "ui/display/types/display_snapshot.h" #include "ui/display/types/native_display_delegate.h" #include "ui/display/types/native_display_observer.h" @@ -338,6 +341,15 @@ logging::LoggingSettings settings; logging::InitLogging(settings); + // Initialize tracing. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kTraceToConsole)) { + base::trace_event::TraceConfig trace_config = + tracing::GetConfigForTraceToConsole(); + base::trace_event::TraceLog::GetInstance()->SetEnabled( + trace_config, base::trace_event::TraceLog::RECORDING_MODE); + } + // Build UI thread message loop. This is used by platform // implementations for event polling & running background tasks. base::MessageLoopForUI message_loop;
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.cc b/ui/ozone/platform/drm/gpu/drm_buffer.cc index d511661b..784549f 100644 --- a/ui/ozone/platform/drm/gpu/drm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/drm_buffer.cc
@@ -107,6 +107,10 @@ return fb_pixel_format_; } +uint64_t DrmBuffer::GetFormatModifier() const { + return DRM_FORMAT_MOD_NONE; +} + uint32_t DrmBuffer::GetHandle() const { return handle_; }
diff --git a/ui/ozone/platform/drm/gpu/drm_buffer.h b/ui/ozone/platform/drm/gpu/drm_buffer.h index dd162198..dc6ed49 100644 --- a/ui/ozone/platform/drm/gpu/drm_buffer.h +++ b/ui/ozone/platform/drm/gpu/drm_buffer.h
@@ -40,6 +40,7 @@ uint32_t GetFramebufferPixelFormat() const override; uint32_t GetOpaqueFramebufferId() const override; uint32_t GetOpaqueFramebufferPixelFormat() const override; + uint64_t GetFormatModifier() const override; uint32_t GetHandle() const override; gfx::Size GetSize() const override; const DrmDevice* GetDrmDevice() const override;
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc index dff2d96..85b22c28 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -83,11 +83,6 @@ return planes_[index].size; } -uint64_t GbmBuffer::GetFormatModifier(size_t index) const { - DCHECK_LT(index, planes_.size()); - return planes_[index].modifier; -} - // TODO(reveman): This should not be needed once crbug.com/597932 is fixed, // as the size would be queried directly from the underlying bo. gfx::Size GbmBuffer::GetSize() const { @@ -168,7 +163,8 @@ gbm_bo* bo = gbm_bo_create(gbm->device(), size.width(), size.height(), format, flags); - return CreateBufferForBO(gbm, bo, format, size, flags, 0, 0); + return CreateBufferForBO(gbm, bo, format, size, flags, + gbm_bo_get_format_modifier(bo), 0); } // static @@ -250,7 +246,7 @@ } handle.planes.emplace_back(buffer_->GetStride(i), buffer_->GetOffset(i), buffer_->GetSize(i), - buffer_->GetFormatModifier(i)); + buffer_->GetFormatModifier()); } return handle; } @@ -283,7 +279,7 @@ } uint64_t GbmPixmap::GetDmaBufModifier(size_t plane) const { - return buffer_->GetFormatModifier(plane); + return buffer_->GetFormatModifier(); } gfx::BufferFormat GbmPixmap::GetBufferFormat() const {
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.h b/ui/ozone/platform/drm/gpu/gbm_buffer.h index 2823243..da9b687 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.h +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.h
@@ -48,7 +48,6 @@ int GetStride(size_t plane) const; int GetOffset(size_t plane) const; size_t GetSize(size_t plane) const; - uint64_t GetFormatModifier(size_t plane) const; gfx::Size GetSize() const override; private:
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc index 7dac027..8af49a8d 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer_base.cc
@@ -24,6 +24,7 @@ framebuffer_pixel_format_ = format; opaque_framebuffer_pixel_format_ = GetFourCCFormatForOpaqueFramebuffer( GetBufferFormatFromFourCCFormat(format)); + format_modifier_ = modifier; uint32_t handles[4] = {0}; uint32_t strides[4] = {0}; @@ -86,6 +87,11 @@ return opaque_framebuffer_pixel_format_; } +uint64_t GbmBufferBase::GetFormatModifier() const { + DCHECK(framebuffer_); + return format_modifier_; +} + const DrmDevice* GbmBufferBase::GetDrmDevice() const { return drm_.get(); }
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer_base.h b/ui/ozone/platform/drm/gpu/gbm_buffer_base.h index 1aca1bb..48a15253 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer_base.h +++ b/ui/ozone/platform/drm/gpu/gbm_buffer_base.h
@@ -32,6 +32,7 @@ gfx::Size GetSize() const override; uint32_t GetFramebufferPixelFormat() const override; uint32_t GetOpaqueFramebufferPixelFormat() const override; + uint64_t GetFormatModifier() const override; const DrmDevice* GetDrmDevice() const override; bool RequiresGlFinish() const override; @@ -54,6 +55,7 @@ // otherwise it is set to 0. uint32_t opaque_framebuffer_ = 0; uint32_t opaque_framebuffer_pixel_format_ = 0; + uint64_t format_modifier_ = 0; DISALLOW_COPY_AND_ASSIGN(GbmBufferBase); };
diff --git a/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc b/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc index 409ac445..ec26ff8 100644 --- a/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc +++ b/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc
@@ -18,6 +18,7 @@ const std::vector<uint32_t>& crtcs, uint32_t planes_per_crtc) { const int kPlaneBaseId = 50; + const struct drm_format_modifier linear_modifier { 0x1, DRM_FORMAT_MOD_NONE }; drm_ = drm; crtcs_ = crtcs; for (size_t crtc_idx = 0; crtc_idx < crtcs_.size(); crtc_idx++) { @@ -25,7 +26,7 @@ std::unique_ptr<HardwareDisplayPlane> plane( new HardwareDisplayPlane(kPlaneBaseId + i, 1 << crtc_idx)); plane->Initialize(drm, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888), - std::vector<drm_format_modifier>(), // modifiers + std::vector<drm_format_modifier>(1, linear_modifier), false, true); planes_.push_back(std::move(plane)); }
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc index 91c0082d..fd15615 100644 --- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc +++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.cc
@@ -3,16 +3,30 @@ // found in the LICENSE file. #include "ui/ozone/platform/drm/gpu/mock_scanout_buffer.h" +#include "ui/ozone/platform/drm/gpu/mock_drm_device.h" namespace ui { -MockScanoutBuffer::MockScanoutBuffer(const gfx::Size& size, uint32_t format) - : size_(size), format_(format) {} +namespace { + +uint32_t g_current_framebuffer_id = 1; + +} // namespace + +MockScanoutBuffer::MockScanoutBuffer(const gfx::Size& size, + uint32_t format, + uint64_t modifier, + const scoped_refptr<DrmDevice>& drm) + : size_(size), + format_(format), + modifier_(modifier), + id_(g_current_framebuffer_id++), + drm_(drm) {} MockScanoutBuffer::~MockScanoutBuffer() {} uint32_t MockScanoutBuffer::GetFramebufferId() const { - return 1; + return id_; } uint32_t MockScanoutBuffer::GetOpaqueFramebufferId() const { @@ -35,8 +49,12 @@ return format_; } +uint64_t MockScanoutBuffer::GetFormatModifier() const { + return modifier_; +} + const DrmDevice* MockScanoutBuffer::GetDrmDevice() const { - return nullptr; + return drm_.get(); } bool MockScanoutBuffer::RequiresGlFinish() const {
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h index e2e9046..33f5977 100644 --- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h +++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer.h
@@ -16,7 +16,9 @@ class MockScanoutBuffer : public ScanoutBuffer { public: MockScanoutBuffer(const gfx::Size& size, - uint32_t format = DRM_FORMAT_XRGB8888); + uint32_t format = DRM_FORMAT_XRGB8888, + uint64_t modifier = DRM_FORMAT_MOD_NONE, + const scoped_refptr<DrmDevice>& drm = nullptr); // ScanoutBuffer: uint32_t GetFramebufferId() const override; @@ -25,6 +27,7 @@ gfx::Size GetSize() const override; uint32_t GetFramebufferPixelFormat() const override; uint32_t GetOpaqueFramebufferPixelFormat() const override; + uint64_t GetFormatModifier() const override; const DrmDevice* GetDrmDevice() const override; bool RequiresGlFinish() const override; @@ -33,6 +36,9 @@ gfx::Size size_; uint32_t format_; + uint64_t modifier_; + uint32_t id_; + scoped_refptr<DrmDevice> drm_; DISALLOW_COPY_AND_ASSIGN(MockScanoutBuffer); };
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc index ccf53a3..08cd50a 100644 --- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc +++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.cc
@@ -17,10 +17,19 @@ const scoped_refptr<DrmDevice>& drm, uint32_t format, const gfx::Size& size) { + return CreateWithModifier(drm, format, DRM_FORMAT_MOD_NONE, size); +} + +scoped_refptr<ScanoutBuffer> MockScanoutBufferGenerator::CreateWithModifier( + const scoped_refptr<DrmDevice>& drm, + uint32_t format, + uint64_t modifier, + const gfx::Size& size) { if (allocation_failure_) return nullptr; - scoped_refptr<MockScanoutBuffer> buffer(new MockScanoutBuffer(size, format)); + scoped_refptr<MockScanoutBuffer> buffer( + new MockScanoutBuffer(size, format, modifier, drm)); return buffer; }
diff --git a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h index fde77e3..2cb3161 100644 --- a/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h +++ b/ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h
@@ -21,6 +21,12 @@ uint32_t format, const gfx::Size& size) override; + scoped_refptr<ScanoutBuffer> CreateWithModifier( + const scoped_refptr<DrmDevice>& drm, + uint32_t format, + uint64_t modifier, + const gfx::Size& size); + void set_allocation_failure(bool allocation_failure) { allocation_failure_ = allocation_failure; }
diff --git a/ui/ozone/platform/drm/gpu/scanout_buffer.h b/ui/ozone/platform/drm/gpu/scanout_buffer.h index 8a5cd13c..b6b58856 100644 --- a/ui/ozone/platform/drm/gpu/scanout_buffer.h +++ b/ui/ozone/platform/drm/gpu/scanout_buffer.h
@@ -34,6 +34,9 @@ // scanout when used as an opaque buffer. virtual uint32_t GetOpaqueFramebufferPixelFormat() const = 0; + // Returns format modifier for buffer. + virtual uint64_t GetFormatModifier() const = 0; + // Handle for the buffer. This is received when allocating the buffer. virtual uint32_t GetHandle() const = 0;
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc index 5dd2666..899f0a5 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager.cc +++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -348,17 +348,30 @@ HardwareDisplayController* controller, const gfx::Rect& bounds) { DrmWindow* window = FindWindowAt(bounds); + + gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat(); + uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(format); + if (window) { const OverlayPlane* primary = window->GetLastModesetBuffer(); const DrmDevice* drm = controller->GetAllocationDrmDevice().get(); if (primary && primary->buffer->GetSize() == bounds.size() && - primary->buffer->GetDrmDevice() == drm) - return *primary; + primary->buffer->GetDrmDevice() == drm) { + // If the controller doesn't advertise modifiers, wont have a + // modifier either and we can reuse the buffer. Otherwise, check + // to see if the controller supports the buffers format + // modifier. + const auto& modifiers = controller->GetFormatModifiers(fourcc_format); + if (modifiers.empty()) + return *primary; + for (const uint64_t modifier : modifiers) { + if (modifier == primary->buffer->GetFormatModifier()) + return *primary; + } + } } - gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat(); scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice(); - uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(format); scoped_refptr<ScanoutBuffer> buffer = buffer_generator_->Create(drm, fourcc_format, bounds.size()); if (!buffer) {
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc index c35b3808c..de0c717 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc +++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -16,7 +16,7 @@ #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h" +#include "ui/ozone/platform/drm/gpu/mock_scanout_buffer_generator.h" #include "ui/ozone/platform/drm/gpu/screen_manager.h" namespace { @@ -51,9 +51,10 @@ } void SetUp() override { - drm_ = new ui::MockDrmDevice(); + drm_ = new ui::MockDrmDevice(false, std::vector<uint32_t>(1, kPrimaryCrtc), + 4 /* planes per crtc */); device_manager_.reset(new ui::DrmDeviceManager(nullptr)); - buffer_generator_.reset(new ui::MockDumbBufferGenerator()); + buffer_generator_.reset(new ui::MockScanoutBufferGenerator()); screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); } void TearDown() override { @@ -64,7 +65,7 @@ protected: scoped_refptr<ui::MockDrmDevice> drm_; std::unique_ptr<ui::DrmDeviceManager> device_manager_; - std::unique_ptr<ui::MockDumbBufferGenerator> buffer_generator_; + std::unique_ptr<ui::MockScanoutBufferGenerator> buffer_generator_; std::unique_ptr<ui::ScreenManager> screen_manager_; private: @@ -516,3 +517,33 @@ window = screen_manager_->RemoveWindow(1); window->Shutdown(); } + +TEST_F(ScreenManagerTest, RejectBufferWithIncompatibleModifiers) { + std::unique_ptr<ui::DrmWindow> window( + new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); + window->Initialize(buffer_generator_.get()); + window->SetBounds(GetPrimaryBounds()); + scoped_refptr<ui::ScanoutBuffer> buffer = + buffer_generator_->CreateWithModifier(drm_, DRM_FORMAT_XRGB8888, + I915_FORMAT_MOD_X_TILED, + GetPrimaryBounds().size()); + + window->SchedulePageFlip( + std::vector<ui::OverlayPlane>(1, ui::OverlayPlane(buffer)), + base::Bind(&EmptySwapCallback)); + screen_manager_->AddWindow(1, std::move(window)); + + screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector); + screen_manager_->ConfigureDisplayController( + drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(), + kDefaultMode); + + // ScreenManager::GetModesetBuffer (called to get a buffer to + // modeset the new controller) should reject the buffer with + // I915_FORMAT_MOD_X_TILED modifier we created above and the two + // framebuffer IDs should be different. + EXPECT_NE(buffer->GetFramebufferId(), drm_->current_framebuffer()); + + window = screen_manager_->RemoveWindow(1); + window->Shutdown(); +}