diff --git a/DEPS b/DEPS index 948df7b..ed050f4 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'f4e498601755073fb43cdbe8db02f236ce1249a3', + 'skia_revision': 'd0e0a8ff416abf9b4736ddac8f6faeb11023ab80', # 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': '714590de1ae834be0e2982742a6725f353877819', + 'v8_revision': '493d8b47ade62b5b331c13a102282102bce14489', # 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.
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc index 79a453d..d13f2f9d 100644 --- a/chrome/browser/banners/app_banner_manager.cc +++ b/chrome/browser/banners/app_banner_manager.cc
@@ -555,7 +555,7 @@ UpdateState(State::COMPLETE); } -void AppBannerManager::DisplayAppBanner() { +void AppBannerManager::DisplayAppBanner(bool user_gesture) { if (is_pending_event()) { // Simulate a non-canceled OnBannerPromptReply to show the delayed banner. OnBannerPromptReply(blink::mojom::AppBannerPromptReply::NONE, referrer_);
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h index 4c13d14..d14251b7d 100644 --- a/chrome/browser/banners/app_banner_manager.h +++ b/chrome/browser/banners/app_banner_manager.h
@@ -268,7 +268,7 @@ // blink::mojom::AppBannerService overrides. // Called when Blink has prevented a banner from being shown, and is now // requesting that it be shown later. - void DisplayAppBanner() override; + void DisplayAppBanner(bool user_gesture) override; // Fetches the data required to display a banner for the current page. InstallableManager* manager_;
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc index 4e5834d5..7342524 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_async_file_util_unittest.cc
@@ -31,6 +31,7 @@ constexpr char kArcUrl[] = "content://org.chromium.foo/bar"; constexpr char kData[] = "abcdef"; +constexpr char kMimeType[] = "application/octet-stream"; class ArcContentFileSystemAsyncFileUtilTest : public testing::Test { public: @@ -38,7 +39,8 @@ ~ArcContentFileSystemAsyncFileUtilTest() override = default; void SetUp() override { - fake_file_system_.AddFile(File(kArcUrl, kData, File::Seekable::NO)); + fake_file_system_.AddFile( + File(kArcUrl, kData, kMimeType, File::Seekable::NO)); arc_service_manager_ = base::MakeUnique<ArcServiceManager>(nullptr); arc_service_manager_->AddService(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc index 14d99657..52d1c70 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
@@ -36,6 +36,8 @@ constexpr char kData[] = "abcdefghijklmnopqrstuvwxyz"; +constexpr char kMimeType[] = "application/octet-stream"; + // Reads data from the reader to fill the buffer. bool ReadData(ArcContentFileSystemFileStreamReader* reader, net::IOBufferWithSize* buffer) { @@ -62,8 +64,10 @@ ~ArcContentFileSystemFileStreamReaderTest() override = default; void SetUp() override { - fake_file_system_.AddFile(File(kArcUrlFile, kData, File::Seekable::YES)); - fake_file_system_.AddFile(File(kArcUrlPipe, kData, File::Seekable::NO)); + fake_file_system_.AddFile( + File(kArcUrlFile, kData, kMimeType, File::Seekable::YES)); + fake_file_system_.AddFile( + File(kArcUrlPipe, kData, kMimeType, File::Seekable::NO)); arc_service_manager_ = base::MakeUnique<ArcServiceManager>(nullptr); arc_service_manager_->AddService(
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.cc index 4603258..c0a9a8c 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.cc
@@ -47,9 +47,13 @@ } GURL FileSystemUrlToArcUrl(const storage::FileSystemURL& url) { + return PathToArcUrl(url.path()); +} + +GURL PathToArcUrl(const base::FilePath& path) { base::FilePath path_after_mount_point; if (!base::FilePath(kContentFileSystemMountPointPath) - .AppendRelativePath(url.path(), &path_after_mount_point)) { + .AppendRelativePath(path, &path_after_mount_point)) { return GURL(); } return UnescapeArcUrl(path_after_mount_point.AsUTF8Unsafe());
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.h b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.h index 1a49c78..a6daddc 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.h
@@ -40,6 +40,12 @@ // Converts a FileSystemURL to a URL which can be used within the ARC container. GURL FileSystemUrlToArcUrl(const storage::FileSystemURL& url); +// Converts a path which was returned by FileSystemURL::path() (not to be +// confused with virtual_path()) to a URL which can be used within the ARC +// container. If the given path is not under the ARC content file system mount +// point, returns an empty GURL. +GURL PathToArcUrl(const base::FilePath& path); + } // namespace arc #endif // CHROME_BROWSER_CHROMEOS_ARC_FILEAPI_ARC_CONTENT_FILE_SYSTEM_URL_UTIL_H_
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util_unittest.cc index e77f3cf..e58c0f5 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util_unittest.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util_unittest.cc
@@ -78,4 +78,13 @@ EXPECT_EQ(arc_url, FileSystemUrlToArcUrl(file_system_url)); } +TEST(ArcContentFileSystemUrlUtilTest, PathToArcUrl) { + GURL arc_url("content://org.chromium.foo/bar/baz"); + + base::FilePath path = + base::FilePath(kContentFileSystemMountPointPath) + .Append(base::FilePath::FromUTF8Unsafe(EscapeArcUrl(arc_url))); + EXPECT_EQ(arc_url, PathToArcUrl(path)); +} + } // namespace arc
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc index 77bcfeb..b1de0ee 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.cc
@@ -104,6 +104,26 @@ file_system_instance->GetFileSize(url.spec(), callback); } +void ArcFileSystemOperationRunner::GetMimeType( + const GURL& url, + const GetMimeTypeCallback& callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (should_defer_) { + deferred_operations_.emplace_back( + base::Bind(&ArcFileSystemOperationRunner::GetMimeType, + weak_ptr_factory_.GetWeakPtr(), url, callback)); + return; + } + auto* file_system_instance = ARC_GET_INSTANCE_FOR_METHOD( + arc_bridge_service()->file_system(), GetMimeType); + if (!file_system_instance) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback, base::nullopt)); + return; + } + file_system_instance->GetMimeType(url.spec(), callback); +} + void ArcFileSystemOperationRunner::OpenFileToRead( const GURL& url, const OpenFileToReadCallback& callback) {
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h index e378270b..6f40f97 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h
@@ -55,6 +55,7 @@ public InstanceHolder<mojom::FileSystemInstance>::Observer { public: using GetFileSizeCallback = mojom::FileSystemInstance::GetFileSizeCallback; + using GetMimeTypeCallback = mojom::FileSystemInstance::GetMimeTypeCallback; using OpenFileToReadCallback = mojom::FileSystemInstance::OpenFileToReadCallback; using GetDocumentCallback = mojom::FileSystemInstance::GetDocumentCallback; @@ -99,6 +100,7 @@ // Runs file system operations. See file_system.mojom for documentation. void GetFileSize(const GURL& url, const GetFileSizeCallback& callback); + void GetMimeType(const GURL& url, const GetMimeTypeCallback& callback); void OpenFileToRead(const GURL& url, const OpenFileToReadCallback& callback); void GetDocument(const std::string& authority, const std::string& document_id,
diff --git a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc index 0d04ab3..d334a08e 100644 --- a/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc +++ b/chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner_unittest.cc
@@ -79,6 +79,13 @@ runner_->GetFileSize( GURL(kUrl), base::Bind([](int* counter, int64_t size) { ++*counter; }, counter)); + runner_->GetMimeType( + GURL(kUrl), + base::Bind( + [](int* counter, const base::Optional<std::string>& mime_type) { + ++*counter; + }, + counter)); runner_->OpenFileToRead( GURL(kUrl), base::Bind([](int* counter, mojo::ScopedHandle handle) { ++*counter; }, @@ -105,7 +112,7 @@ CallSetShouldDefer(false); CallAllFunctions(&counter); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(6, counter); + EXPECT_EQ(7, counter); } TEST_F(ArcFileSystemOperationRunnerTest, DeferAndRun) { @@ -117,7 +124,7 @@ CallSetShouldDefer(false); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(6, counter); + EXPECT_EQ(7, counter); } TEST_F(ArcFileSystemOperationRunnerTest, DeferAndDiscard) { @@ -140,7 +147,7 @@ CallSetShouldDefer(false); CallAllFunctions(&counter); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(6, counter); + EXPECT_EQ(7, counter); } } // namespace arc
diff --git a/chrome/browser/chromeos/file_manager/filesystem_api_util.cc b/chrome/browser/chromeos/file_manager/filesystem_api_util.cc index ccf4a84d..8a435cb 100644 --- a/chrome/browser/chromeos/file_manager/filesystem_api_util.cc +++ b/chrome/browser/chromeos/file_manager/filesystem_api_util.cc
@@ -9,6 +9,9 @@ #include "base/callback.h" #include "base/files/file.h" #include "base/files/file_path.h" +#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/chromeos/arc/fileapi/arc_content_file_system_url_util.h" +#include "chrome/browser/chromeos/arc/fileapi/arc_file_system_operation_runner.h" #include "chrome/browser/chromeos/drive/file_system_util.h" #include "chrome/browser/chromeos/file_manager/app_id.h" #include "chrome/browser/chromeos/file_manager/fileapi_util.h" @@ -16,6 +19,7 @@ #include "chrome/browser/chromeos/file_system_provider/provided_file_system_interface.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile.h" +#include "components/arc/arc_service_manager.h" #include "components/drive/chromeos/file_system_interface.h" #include "components/drive/file_errors.h" #include "components/drive/file_system_core_util.h" @@ -59,6 +63,19 @@ callback.Run(true, *metadata->mime_type); } +// Helper function used to implement GetNonNativeLocalPathMimeType. It passes +// the returned mime type to the callback. +void GetMimeTypeAfterGetMimeTypeForArcContentFileSystem( + const base::Callback<void(bool, const std::string&)>& callback, + const base::Optional<std::string>& mime_type) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (mime_type.has_value()) { + callback.Run(true, mime_type.value()); + } else { + callback.Run(false, std::string()); + } +} + // Helper function to converts a callback that takes boolean value to that takes // File::Error, by regarding FILE_OK as the only successful value. void BoolCallbackAsFileErrorCallback( @@ -181,6 +198,23 @@ return; } + if (arc::IsArcAllowedForProfile(profile) && + base::FilePath(arc::kContentFileSystemMountPointPath).IsParent(path)) { + GURL arc_url = arc::PathToArcUrl(path); + auto* runner = arc::ArcServiceManager::GetGlobalService< + arc::ArcFileSystemOperationRunner>(); + if (!runner) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::BindOnce(callback, false, std::string())); + return; + } + runner->GetMimeType( + arc_url, base::Bind(&GetMimeTypeAfterGetMimeTypeForArcContentFileSystem, + callback)); + return; + } + // We don't have a way to obtain metadata other than drive and FSP. Returns an // error with empty MIME type, that leads fallback guessing mime type from // file extensions.
diff --git a/chrome/browser/permissions/mock_permission_request.cc b/chrome/browser/permissions/mock_permission_request.cc index ae21796..f436de82 100644 --- a/chrome/browser/permissions/mock_permission_request.cc +++ b/chrome/browser/permissions/mock_permission_request.cc
@@ -36,14 +36,14 @@ request_type, gesture_type) {} -MockPermissionRequest::MockPermissionRequest( - const std::string& text, - const GURL& url) +MockPermissionRequest::MockPermissionRequest(const std::string& text, + PermissionRequestType request_type, + const GURL& url) : MockPermissionRequest(text, "button", "button", url, - PermissionRequestType::UNKNOWN, + request_type, PermissionRequestGestureType::UNKNOWN) {} MockPermissionRequest::MockPermissionRequest(
diff --git a/chrome/browser/permissions/mock_permission_request.h b/chrome/browser/permissions/mock_permission_request.h index 8bcfe1b..1310290 100644 --- a/chrome/browser/permissions/mock_permission_request.h +++ b/chrome/browser/permissions/mock_permission_request.h
@@ -16,7 +16,9 @@ MockPermissionRequest(const std::string& text, PermissionRequestType request_type, PermissionRequestGestureType gesture_type); - MockPermissionRequest(const std::string& text, const GURL& url); + MockPermissionRequest(const std::string& text, + PermissionRequestType request_type, + const GURL& url); MockPermissionRequest(const std::string& text, const std::string& accept_label, const std::string& deny_label);
diff --git a/chrome/browser/permissions/permission_request_manager.cc b/chrome/browser/permissions/permission_request_manager.cc index 61346ec..982e4ff 100644 --- a/chrome/browser/permissions/permission_request_manager.cc +++ b/chrome/browser/permissions/permission_request_manager.cc
@@ -70,6 +70,27 @@ return false; } +// We only group together media requests. We don't display grouped requests for +// any other permissions at present. +bool ShouldGroupRequests(PermissionRequest* a, PermissionRequest* b) { + if (a->GetOrigin() != b->GetOrigin()) + return false; + + if (a->GetPermissionRequestType() == + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC) { + return b->GetPermissionRequestType() == + PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA; + } + + if (a->GetPermissionRequestType() == + PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA) { + return b->GetPermissionRequestType() == + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC; + } + + return false; +} + } // namespace // PermissionRequestManager::Observer ------------------------------------------ @@ -107,8 +128,6 @@ request->RequestFinished(); for (PermissionRequest* request : queued_requests_) request->RequestFinished(); - for (PermissionRequest* request : queued_frame_requests_) - request->RequestFinished(); for (const auto& entry : duplicate_requests_) entry.second->RequestFinished(); } @@ -148,12 +167,11 @@ base::RecordAction( base::UserMetricsAction("PermissionBubbleRequestQueued")); } - queued_requests_.push_back(request); } else { base::RecordAction( base::UserMetricsAction("PermissionBubbleIFrameRequestQueued")); - queued_frame_requests_.push_back(request); } + queued_requests_.push_back(request); if (!IsBubbleVisible()) ScheduleShowBubble(); @@ -162,25 +180,17 @@ void PermissionRequestManager::CancelRequest(PermissionRequest* request) { // First look in the queued requests, where we can simply finish the request // and go on. - std::vector<PermissionRequest*>::iterator requests_iter; - for (requests_iter = queued_requests_.begin(); - requests_iter != queued_requests_.end(); - requests_iter++) { - if (*requests_iter == request) { - RequestFinishedIncludingDuplicates(*requests_iter); - queued_requests_.erase(requests_iter); - return; - } - } - for (requests_iter = queued_frame_requests_.begin(); - requests_iter != queued_frame_requests_.end(); requests_iter++) { - if (*requests_iter == request) { - RequestFinishedIncludingDuplicates(*requests_iter); - queued_frame_requests_.erase(requests_iter); + std::deque<PermissionRequest*>::iterator queued_requests_iter; + for (queued_requests_iter = queued_requests_.begin(); + queued_requests_iter != queued_requests_.end(); queued_requests_iter++) { + if (*queued_requests_iter == request) { + RequestFinishedIncludingDuplicates(*queued_requests_iter); + queued_requests_.erase(queued_requests_iter); return; } } + std::vector<PermissionRequest*>::iterator requests_iter; std::vector<bool>::iterator accepts_iter = accept_states_.begin(); for (requests_iter = requests_.begin(), accepts_iter = accept_states_.begin(); requests_iter != requests_.end(); @@ -212,7 +222,7 @@ return; } - // Since |request| wasn't found in queued_requests_, queued_frame_requests_ or + // Since |request| wasn't found in queued_requests_ or // requests_ it must have been marked as a duplicate. We can't search // duplicate_requests_ by value, so instead use GetExistingRequest to find the // key (request it was duped against), and iterate through duplicates of that. @@ -399,13 +409,17 @@ return; if (!main_frame_has_fully_loaded_) return; - if (queued_requests_.empty() && queued_frame_requests_.empty()) + if (queued_requests_.empty()) return; - if (queued_requests_.size()) - requests_.swap(queued_requests_); - else - requests_.swap(queued_frame_requests_); + requests_.push_back(queued_requests_.front()); + queued_requests_.pop_front(); + + if (!queued_requests_.empty() && + ShouldGroupRequests(requests_.front(), queued_requests_.front())) { + requests_.push_back(queued_requests_.front()); + queued_requests_.pop_front(); + } // Sets the default value for each request to be 'accept'. accept_states_.resize(requests_.size(), true); @@ -439,24 +453,18 @@ } requests_.clear(); accept_states_.clear(); - if (queued_requests_.size() || queued_frame_requests_.size()) + if (queued_requests_.size()) DequeueRequestsAndShowBubble(); } void PermissionRequestManager::CancelPendingQueues() { - std::vector<PermissionRequest*>::iterator requests_iter; + std::deque<PermissionRequest*>::iterator requests_iter; for (requests_iter = queued_requests_.begin(); requests_iter != queued_requests_.end(); requests_iter++) { RequestFinishedIncludingDuplicates(*requests_iter); } - for (requests_iter = queued_frame_requests_.begin(); - requests_iter != queued_frame_requests_.end(); - requests_iter++) { - RequestFinishedIncludingDuplicates(*requests_iter); - } queued_requests_.clear(); - queued_frame_requests_.clear(); } PermissionRequest* PermissionRequestManager::GetExistingRequest( @@ -467,9 +475,6 @@ for (PermissionRequest* existing_request : queued_requests_) if (IsMessageTextEqual(existing_request, request)) return existing_request; - for (PermissionRequest* existing_request : queued_frame_requests_) - if (IsMessageTextEqual(existing_request, request)) - return existing_request; return nullptr; } @@ -488,7 +493,7 @@ void PermissionRequestManager::PermissionDeniedIncludingDuplicates( PermissionRequest* request) { DCHECK_EQ(request, GetExistingRequest(request)) - << "Only requests in [queued_[frame_]]requests_ can have duplicates"; + << "Only requests in [queued_]requests_ can have duplicates"; request->set_persist(persist_); request->PermissionDenied(); auto range = duplicate_requests_.equal_range(request); @@ -500,7 +505,7 @@ void PermissionRequestManager::CancelledIncludingDuplicates( PermissionRequest* request) { DCHECK_EQ(request, GetExistingRequest(request)) - << "Only requests in [queued_[frame_]]requests_ can have duplicates"; + << "Only requests in [queued_]requests_ can have duplicates"; request->Cancelled(); auto range = duplicate_requests_.equal_range(request); for (auto it = range.first; it != range.second; ++it) @@ -509,13 +514,11 @@ void PermissionRequestManager::RequestFinishedIncludingDuplicates( PermissionRequest* request) { // We can't call GetExistingRequest here, because other entries in requests_, - // queued_requests_ or queued_frame_requests_ might already have been deleted. + // queued_requests_ might already have been deleted. DCHECK_EQ(1, std::count(requests_.begin(), requests_.end(), request) + - std::count(queued_requests_.begin(), queued_requests_.end(), - request) + - std::count(queued_frame_requests_.begin(), - queued_frame_requests_.end(), request)) - << "Only requests in [queued_[frame_]]requests_ can have duplicates"; + std::count(queued_requests_.begin(), queued_requests_.end(), + request)) + << "Only requests in [queued_]requests_ can have duplicates"; request->RequestFinished(); // Beyond this point, |request| has probably been deleted. auto range = duplicate_requests_.equal_range(request);
diff --git a/chrome/browser/permissions/permission_request_manager.h b/chrome/browser/permissions/permission_request_manager.h index ffc4af1..275f968 100644 --- a/chrome/browser/permissions/permission_request_manager.h +++ b/chrome/browser/permissions/permission_request_manager.h
@@ -5,8 +5,8 @@ #ifndef CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_ #define CHROME_BROWSER_PERMISSIONS_PERMISSION_REQUEST_MANAGER_H_ +#include <deque> #include <unordered_map> -#include <vector> #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" @@ -188,8 +188,7 @@ std::unique_ptr<PermissionPrompt> view_; std::vector<PermissionRequest*> requests_; - std::vector<PermissionRequest*> queued_requests_; - std::vector<PermissionRequest*> queued_frame_requests_; + std::deque<PermissionRequest*> queued_requests_; // Maps from the first request of a kind to subsequent requests that were // duped against it. std::unordered_multimap<PermissionRequest*, PermissionRequest*>
diff --git a/chrome/browser/permissions/permission_request_manager_browsertest.cc b/chrome/browser/permissions/permission_request_manager_browsertest.cc index 4b2b62c..a6de20a 100644 --- a/chrome/browser/permissions/permission_request_manager_browsertest.cc +++ b/chrome/browser/permissions/permission_request_manager_browsertest.cc
@@ -211,16 +211,6 @@ void PermissionDialogTest::ShowDialog(const std::string& name) { constexpr const char* kMultipleName = "multiple"; - // Permissions to request for a "multiple" request. Only types handled in - // PermissionRequestImpl::GetMessageTextFragment() are valid. - constexpr ContentSettingsType kMultipleRequests[] = { - CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - CONTENT_SETTINGS_TYPE_MIDI_SYSEX, - }; - constexpr ContentSettingsType kMultipleRequestsWithMedia[] = { - CONTENT_SETTINGS_TYPE_GEOLOCATION, CONTENT_SETTINGS_TYPE_NOTIFICATIONS, - CONTENT_SETTINGS_TYPE_MIDI_SYSEX, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, - CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA}; constexpr struct { const char* name; ContentSettingsType type; @@ -274,15 +264,13 @@ manager->AddRequest(MakePermissionRequest(it->type)); break; case CONTENT_SETTINGS_TYPE_DEFAULT: + // Permissions to request for a "multiple" request. Only mic/camera + // requests are grouped together. EXPECT_EQ(kMultipleName, name); - if (base::FeatureList::IsEnabled( - features::kUsePermissionManagerForMediaRequests)) { - for (auto request : kMultipleRequestsWithMedia) - manager->AddRequest(MakePermissionRequest(request)); - } else { - for (auto request : kMultipleRequests) - manager->AddRequest(MakePermissionRequest(request)); - } + manager->AddRequest( + MakePermissionRequest(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)); + manager->AddRequest( + MakePermissionRequest(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)); break; default: @@ -348,7 +336,7 @@ bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(2, bubble_factory()->show_count()); - EXPECT_EQ(4, bubble_factory()->TotalRequestCount()); + EXPECT_EQ(2, bubble_factory()->TotalRequestCount()); } // Navigating twice to the same URL with a hash should be navigation within the @@ -377,7 +365,7 @@ bubble_factory()->WaitForPermissionBubble(); EXPECT_EQ(1, bubble_factory()->show_count()); - EXPECT_EQ(2, bubble_factory()->TotalRequestCount()); + EXPECT_EQ(1, bubble_factory()->TotalRequestCount()); } // Bubble requests should be shown after in-page navigation. @@ -522,13 +510,6 @@ // Shows a permissions bubble with multiple requests. IN_PROC_BROWSER_TEST_F(PermissionDialogTest, InvokeDialog_multiple) { RunDialog(); - - { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - features::kUsePermissionManagerForMediaRequests); - RunDialog(); - } } // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER is ChromeOS only.
diff --git a/chrome/browser/permissions/permission_request_manager_unittest.cc b/chrome/browser/permissions/permission_request_manager_unittest.cc index a9d6cc1..54fd984 100644 --- a/chrome/browser/permissions/permission_request_manager_unittest.cc +++ b/chrome/browser/permissions/permission_request_manager_unittest.cc
@@ -28,10 +28,22 @@ request2_("test2", PermissionRequestType::DOWNLOAD, PermissionRequestGestureType::NO_GESTURE), + request_mic_("mic", + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC, + PermissionRequestGestureType::NO_GESTURE), + request_camera_("cam", + PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA, + PermissionRequestGestureType::NO_GESTURE), iframe_request_same_domain_("iframe", + PermissionRequestType::UNKNOWN, GURL("http://www.google.com/some/url")), - iframe_request_other_domain_("iframe", GURL("http://www.youtube.com")) { - } + iframe_request_other_domain_("iframe", + PermissionRequestType::UNKNOWN, + GURL("http://www.youtube.com")), + iframe_request_mic_other_domain_( + "iframe", + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC, + GURL("http://www.youtube.com")) {} ~PermissionRequestManagerTest() override {} void SetUp() override { @@ -71,7 +83,7 @@ base::RunLoop().RunUntilIdle(); } - void WaitForCoalescing() { + void WaitForBubbleToBeShown() { manager_->DocumentOnLoadCompletedInMainFrame(); base::RunLoop().RunUntilIdle(); } @@ -88,8 +100,11 @@ protected: MockPermissionRequest request1_; MockPermissionRequest request2_; + MockPermissionRequest request_mic_; + MockPermissionRequest request_camera_; MockPermissionRequest iframe_request_same_domain_; MockPermissionRequest iframe_request_other_domain_; + MockPermissionRequest iframe_request_mic_other_domain_; std::unique_ptr<PermissionRequestManager> manager_; std::unique_ptr<MockPermissionPromptFactory> prompt_factory_; }; @@ -97,7 +112,7 @@ TEST_F(PermissionRequestManagerTest, SingleRequest) { manager_->AddRequest(&request1_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 1); @@ -110,7 +125,7 @@ TEST_F(PermissionRequestManagerTest, SingleRequestViewFirst) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 1); @@ -120,27 +135,55 @@ EXPECT_TRUE(request1_.granted()); } -TEST_F(PermissionRequestManagerTest, TwoRequests) { +// Most requests should never be grouped. +TEST_F(PermissionRequestManagerTest, TwoRequestsUngrouped) { manager_->AddRequest(&request1_); manager_->AddRequest(&request2_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + + WaitForBubbleToBeShown(); + EXPECT_TRUE(prompt_factory_->is_visible()); + ASSERT_EQ(prompt_factory_->request_count(), 1); + Accept(); + EXPECT_TRUE(request1_.granted()); + + WaitForBubbleToBeShown(); + EXPECT_TRUE(prompt_factory_->is_visible()); + ASSERT_EQ(prompt_factory_->request_count(), 1); + Accept(); + EXPECT_TRUE(request2_.granted()); +} + +// Only mic/camera requests from the same origin should be grouped. +TEST_F(PermissionRequestManagerTest, MicCameraGrouped) { + manager_->AddRequest(&request_mic_); + manager_->AddRequest(&request_camera_); + manager_->DisplayPendingRequests(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 2); ToggleAccept(0, true); - ToggleAccept(1, false); + ToggleAccept(1, true); Accept(); - EXPECT_TRUE(request1_.granted()); - EXPECT_FALSE(request2_.granted()); + EXPECT_TRUE(request_mic_.granted()); + EXPECT_TRUE(request_camera_.granted()); + + // If the requests come from different origins, they should not be grouped. + manager_->AddRequest(&iframe_request_mic_other_domain_); + manager_->AddRequest(&request_camera_); + WaitForBubbleToBeShown(); + + EXPECT_TRUE(prompt_factory_->is_visible()); + ASSERT_EQ(prompt_factory_->request_count(), 1); } TEST_F(PermissionRequestManagerTest, TwoRequestsTabSwitch) { - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); + manager_->AddRequest(&request_mic_); + manager_->AddRequest(&request_camera_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 2); @@ -152,43 +195,32 @@ EXPECT_FALSE(prompt_factory_->is_visible()); MockTabSwitchBack(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 2); Accept(); - EXPECT_TRUE(request1_.granted()); - EXPECT_FALSE(request2_.granted()); + EXPECT_TRUE(request_mic_.granted()); + EXPECT_FALSE(request_camera_.granted()); } TEST_F(PermissionRequestManagerTest, NoRequests) { manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_FALSE(prompt_factory_->is_visible()); } TEST_F(PermissionRequestManagerTest, NoView) { manager_->AddRequest(&request1_); // Don't display the pending requests. - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_FALSE(prompt_factory_->is_visible()); } -TEST_F(PermissionRequestManagerTest, TwoRequestsCoalesce) { - manager_->DisplayPendingRequests(); - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); - EXPECT_FALSE(prompt_factory_->is_visible()); - WaitForCoalescing(); - - EXPECT_TRUE(prompt_factory_->is_visible()); - ASSERT_EQ(prompt_factory_->request_count(), 2); -} - TEST_F(PermissionRequestManagerTest, TwoRequestsDoNotCoalesce) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); manager_->AddRequest(&request2_); EXPECT_TRUE(prompt_factory_->is_visible()); @@ -198,14 +230,14 @@ TEST_F(PermissionRequestManagerTest, TwoRequestsShownInTwoBubbles) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); manager_->AddRequest(&request2_); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 1); Accept(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 1); @@ -215,18 +247,17 @@ TEST_F(PermissionRequestManagerTest, TestAddDuplicateRequest) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); - ASSERT_EQ(prompt_factory_->request_count(), 2); + ASSERT_EQ(prompt_factory_->request_count(), 1); } TEST_F(PermissionRequestManagerTest, SequentialRequests) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); Accept(); @@ -235,7 +266,7 @@ EXPECT_FALSE(prompt_factory_->is_visible()); manager_->AddRequest(&request2_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); Accept(); EXPECT_FALSE(prompt_factory_->is_visible()); @@ -248,7 +279,7 @@ manager_->AddRequest(&request1_); EXPECT_FALSE(request1_.finished()); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 1); } @@ -268,7 +299,7 @@ TEST_F(PermissionRequestManagerTest, DuplicateQueuedRequest) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); manager_->AddRequest(&request2_); MockPermissionRequest dupe_request("test1"); @@ -293,7 +324,7 @@ TEST_F(PermissionRequestManagerTest, ForgetRequestsOnPageNavigation) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); manager_->AddRequest(&request2_); manager_->AddRequest(&iframe_request_other_domain_); @@ -301,7 +332,7 @@ ASSERT_EQ(prompt_factory_->request_count(), 1); NavigateAndCommit(GURL("http://www2.google.com/")); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_FALSE(prompt_factory_->is_visible()); EXPECT_TRUE(request1_.finished()); @@ -320,7 +351,7 @@ EXPECT_FALSE(prompt_factory_->is_visible()); manager_->AddRequest(&request2_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); ASSERT_EQ(prompt_factory_->request_count(), 1); } @@ -328,13 +359,13 @@ TEST_F(PermissionRequestManagerTest, TestCancelWhileDialogShown) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); prompt_factory_->SetCanUpdateUi(true); EXPECT_TRUE(prompt_factory_->is_visible()); EXPECT_FALSE(request1_.finished()); manager_->CancelRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(request1_.finished()); EXPECT_FALSE(prompt_factory_->is_visible()); } @@ -343,7 +374,7 @@ manager_->DisplayPendingRequests(); prompt_factory_->SetCanUpdateUi(false); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); prompt_factory_->SetCanUpdateUi(false); EXPECT_TRUE(prompt_factory_->is_visible()); @@ -357,7 +388,7 @@ TEST_F(PermissionRequestManagerTest, TestCancelPendingRequest) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); manager_->AddRequest(&request2_); EXPECT_TRUE(prompt_factory_->is_visible()); @@ -372,7 +403,7 @@ TEST_F(PermissionRequestManagerTest, MainFrameNoRequestIFrameRequest) { manager_->DisplayPendingRequests(); manager_->AddRequest(&iframe_request_same_domain_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); WaitForFrameLoad(); EXPECT_TRUE(prompt_factory_->is_visible()); @@ -385,14 +416,19 @@ manager_->AddRequest(&request1_); manager_->AddRequest(&iframe_request_same_domain_); WaitForFrameLoad(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); - ASSERT_EQ(prompt_factory_->request_count(), 2); + ASSERT_EQ(1, prompt_factory_->request_count()); Closing(); EXPECT_TRUE(request1_.finished()); - EXPECT_TRUE(iframe_request_same_domain_.finished()); + EXPECT_FALSE(iframe_request_same_domain_.finished()); + WaitForBubbleToBeShown(); + EXPECT_TRUE(prompt_factory_->is_visible()); + ASSERT_EQ(1, prompt_factory_->request_count()); + Closing(); EXPECT_FALSE(prompt_factory_->is_visible()); + EXPECT_TRUE(iframe_request_same_domain_.finished()); } TEST_F(PermissionRequestManagerTest, MainFrameAndIFrameRequestOtherDomain) { @@ -400,7 +436,7 @@ manager_->AddRequest(&request1_); manager_->AddRequest(&iframe_request_other_domain_); WaitForFrameLoad(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); Closing(); @@ -414,7 +450,7 @@ TEST_F(PermissionRequestManagerTest, IFrameRequestWhenMainRequestVisible) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); manager_->AddRequest(&iframe_request_same_domain_); @@ -433,7 +469,7 @@ IFrameRequestOtherDomainWhenMainRequestVisible) { manager_->DisplayPendingRequests(); manager_->AddRequest(&request1_); - WaitForCoalescing(); + WaitForBubbleToBeShown(); EXPECT_TRUE(prompt_factory_->is_visible()); manager_->AddRequest(&iframe_request_other_domain_); @@ -449,7 +485,7 @@ TEST_F(PermissionRequestManagerTest, RequestsDontNeedUserGesture) { manager_->DisplayPendingRequests(); WaitForFrameLoad(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); manager_->AddRequest(&request1_); manager_->AddRequest(&iframe_request_other_domain_); manager_->AddRequest(&request2_); @@ -463,7 +499,7 @@ manager_->AddRequest(&request1_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); histograms.ExpectUniqueSample( PermissionUmaUtil::kPermissionsPromptShown, static_cast<base::HistogramBase::Sample>(PermissionRequestType::QUOTA), @@ -499,7 +535,7 @@ manager_->AddRequest(&request2_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); histograms.ExpectTotalCount( PermissionUmaUtil::kPermissionsPromptShownGesture, 0); @@ -534,7 +570,7 @@ manager_->AddRequest(&request1_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); // No need to test UMA for showing prompts again, they were tested in // UMAForSimpleAcceptedBubble. @@ -549,10 +585,10 @@ TEST_F(PermissionRequestManagerTest, UMAForMergedAcceptedBubble) { base::HistogramTester histograms; - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); + manager_->AddRequest(&request_mic_); + manager_->AddRequest(&request_camera_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); histograms.ExpectUniqueSample( PermissionUmaUtil::kPermissionsPromptShown, @@ -560,11 +596,13 @@ 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleTypes, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::QUOTA), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC), 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleTypes, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::DOWNLOAD), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA), 1); histograms.ExpectUniqueSample( PermissionUmaUtil::kPermissionsPromptRequestsPerPrompt, 2, 1); @@ -583,21 +621,23 @@ 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::QUOTA), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC), 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::DOWNLOAD), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA), 1); } TEST_F(PermissionRequestManagerTest, UMAForMergedMixedBubble) { base::HistogramTester histograms; - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); + manager_->AddRequest(&request_mic_); + manager_->AddRequest(&request_camera_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); // No need to test UMA for showing prompts again, they were tested in // UMAForMergedAcceptedBubble. @@ -611,21 +651,23 @@ 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleAccepted, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::QUOTA), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC), 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::DOWNLOAD), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA), 1); } TEST_F(PermissionRequestManagerTest, UMAForMergedDeniedBubble) { base::HistogramTester histograms; - manager_->AddRequest(&request1_); - manager_->AddRequest(&request2_); + manager_->AddRequest(&request_mic_); + manager_->AddRequest(&request_camera_); manager_->DisplayPendingRequests(); - WaitForCoalescing(); + WaitForBubbleToBeShown(); // No need to test UMA for showing prompts again, they were tested in // UMAForMergedAcceptedBubble. @@ -639,10 +681,12 @@ 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::QUOTA), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_MIC), 1); histograms.ExpectBucketCount( PermissionUmaUtil::kPermissionsPromptMergedBubbleDenied, - static_cast<base::HistogramBase::Sample>(PermissionRequestType::DOWNLOAD), + static_cast<base::HistogramBase::Sample>( + PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA), 1); }
diff --git a/chrome/browser/resources/md_bookmarks/actions.js b/chrome/browser/resources/md_bookmarks/actions.js index f13c451..744b365f 100644 --- a/chrome/browser/resources/md_bookmarks/actions.js +++ b/chrome/browser/resources/md_bookmarks/actions.js
@@ -241,6 +241,18 @@ }; } + /** + * @param {IncognitoAvailability} availability + * @return {!Action} + */ + function setIncognitoAvailability(availability) { + assert(availability != IncognitoAvailability.FORCED); + return { + name: 'set-incognito-availability', + value: availability, + }; + } + return { changeFolderOpen: changeFolderOpen, clearSearch: clearSearch, @@ -254,6 +266,7 @@ selectAll: selectAll, selectFolder: selectFolder, selectItem: selectItem, + setIncognitoAvailability: setIncognitoAvailability, setSearchResults: setSearchResults, setSearchTerm: setSearchTerm, updateAnchor: updateAnchor,
diff --git a/chrome/browser/resources/md_bookmarks/api_listener.js b/chrome/browser/resources/md_bookmarks/api_listener.js index 95634523..0e54e07 100644 --- a/chrome/browser/resources/md_bookmarks/api_listener.js +++ b/chrome/browser/resources/md_bookmarks/api_listener.js
@@ -78,6 +78,13 @@ chrome.bookmarks.onCreated.addListener(onBookmarkCreated); } + /** + * @param {IncognitoAvailability} availability + */ + function onIncognitoAvailabilityChanged(availability) { + dispatch(bookmarks.actions.setIncognitoAvailability(availability)); + } + function init() { chrome.bookmarks.onChanged.addListener(onBookmarkChanged); chrome.bookmarks.onChildrenReordered.addListener(onChildrenReordered); @@ -86,6 +93,11 @@ chrome.bookmarks.onRemoved.addListener(onBookmarkRemoved); chrome.bookmarks.onImportBegan.addListener(onImportBegan); chrome.bookmarks.onImportEnded.addListener(onImportEnded); + + cr.sendWithPromise('getIncognitoAvailability') + .then(onIncognitoAvailabilityChanged); + cr.addWebUIListener( + 'incognito-availability-changed', onIncognitoAvailabilityChanged); } return {
diff --git a/chrome/browser/resources/md_bookmarks/command_manager.js b/chrome/browser/resources/md_bookmarks/command_manager.js index aef8c5a..e2f84cd 100644 --- a/chrome/browser/resources/md_bookmarks/command_manager.js +++ b/chrome/browser/resources/md_bookmarks/command_manager.js
@@ -92,6 +92,7 @@ }, closeCommandMenu: function() { + this.menuIds_ = new Set(); /** @type {!CrActionMenuElement} */ (this.$.dropdown).close(); }, @@ -154,8 +155,11 @@ switch (command) { case Command.OPEN_NEW_TAB: case Command.OPEN_NEW_WINDOW: - case Command.OPEN_INCOGNITO: return this.expandUrls_(itemIds).length > 0; + case Command.OPEN_INCOGNITO: + return this.expandUrls_(itemIds).length > 0 && + this.getState().prefs.incognitoAvailability != + IncognitoAvailability.DISABLED; default: return true; } @@ -326,8 +330,8 @@ * @private */ onCommandClick_: function(e) { - this.closeCommandMenu(); this.handle(e.target.getAttribute('command'), assert(this.menuIds_)); + this.closeCommandMenu(); }, /** @@ -363,7 +367,7 @@ if (e.path[0] != this.$.dropdown) return; - this.$.dropdown.close(); + this.closeCommandMenu(); }, /** @@ -379,7 +383,7 @@ var label; switch (command) { case Command.EDIT: - if (this.menuIds_.size > 1) + if (this.menuIds_.size != 1) return ''; var id = Array.from(this.menuIds_)[0];
diff --git a/chrome/browser/resources/md_bookmarks/constants.js b/chrome/browser/resources/md_bookmarks/constants.js index e93f0a43..b004992 100644 --- a/chrome/browser/resources/md_bookmarks/constants.js +++ b/chrome/browser/resources/md_bookmarks/constants.js
@@ -32,6 +32,17 @@ OPEN: 'open', }; +/** + * Mirrors the C++ enum from IncognitoModePrefs. + * @enum {number} + * @const + */ +var IncognitoAvailability = { + ENABLED: 0, + DISABLED: 1, + FORCED: 2, +}; + /** @const */ var LOCAL_STORAGE_CLOSED_FOLDERS_KEY = 'closedState';
diff --git a/chrome/browser/resources/md_bookmarks/reducers.js b/chrome/browser/resources/md_bookmarks/reducers.js index 9b84689..7665d35 100644 --- a/chrome/browser/resources/md_bookmarks/reducers.js +++ b/chrome/browser/resources/md_bookmarks/reducers.js
@@ -395,6 +395,24 @@ return newClosedFolders; }; + var PreferencesState = {}; + + /** + * @param {PreferencesState} prefs + * @param {Action} action + * @return {PreferencesState} + */ + PreferencesState.updatePrefs = function(prefs, action) { + switch (action.name) { + case 'set-incognito-availability': + return /** @type {PreferencesState} */ (Object.assign({}, prefs, { + incognitoAvailability: action.value, + })); + default: + return prefs; + } + }; + /** * @param {ClosedFolderState} closedFolders * @param {Action} action @@ -437,6 +455,7 @@ state.selectedFolder, action, state.nodes), closedFolders: ClosedFolderState.updateClosedFolders( state.closedFolders, action, state.nodes), + prefs: PreferencesState.updatePrefs(state.prefs, action), search: SearchState.updateSearch(state.search, action), selection: SelectionState.updateSelection(state.selection, action), }; @@ -446,6 +465,7 @@ reduceAction: reduceAction, ClosedFolderState: ClosedFolderState, NodeState: NodeState, + PreferencesState: PreferencesState, SearchState: SearchState, SelectedFolderState: SelectedFolderState, SelectionState: SelectionState,
diff --git a/chrome/browser/resources/md_bookmarks/types.js b/chrome/browser/resources/md_bookmarks/types.js index d766e35..9b08e8c 100644 --- a/chrome/browser/resources/md_bookmarks/types.js +++ b/chrome/browser/resources/md_bookmarks/types.js
@@ -50,9 +50,17 @@ /** * @typedef {{ + * incognitoAvailability: IncognitoAvailability, + * }} + */ +var PreferencesState; + +/** + * @typedef {{ * nodes: NodeMap, * selectedFolder: string, * closedFolders: ClosedFolderState, + * prefs: PreferencesState, * search: SearchState, * selection: SelectionState, * }}
diff --git a/chrome/browser/resources/md_bookmarks/util.js b/chrome/browser/resources/md_bookmarks/util.js index a660add7..2a9de6a 100644 --- a/chrome/browser/resources/md_bookmarks/util.js +++ b/chrome/browser/resources/md_bookmarks/util.js
@@ -70,6 +70,9 @@ nodes: {}, selectedFolder: '0', closedFolders: new Set(), + prefs: { + incognitoAvailability: IncognitoAvailability.ENABLED, + }, search: { term: '', inProgress: false,
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js index b675fc89..76adf7c6 100644 --- a/chrome/browser/resources/settings/route.js +++ b/chrome/browser/resources/settings/route.js
@@ -168,6 +168,12 @@ r.SITE_SETTINGS_ALL = r.SITE_SETTINGS.createChild('all'); r.SITE_SETTINGS_SITE_DETAILS = r.SITE_SETTINGS_ALL.createChild('/content/siteDetails'); + } else if (loadTimeData.getBoolean('enableSiteDetails')) { + // When there is no "All Sites", pressing 'back' from "Site Details" should + // return to "Content Settings". This should only occur when |kSiteSettings| + // is off and |kSiteDetails| is on. + r.SITE_SETTINGS_SITE_DETAILS = + r.SITE_SETTINGS.createChild('/content/siteDetails'); } r.SITE_SETTINGS_HANDLERS = r.SITE_SETTINGS.createChild('/handlers');
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 710e768..24e5e840 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -948,6 +948,8 @@ "webui/identity_internals_ui.h", "webui/inspect_ui.cc", "webui/inspect_ui.h", + "webui/md_bookmarks/bookmarks_message_handler.cc", + "webui/md_bookmarks/bookmarks_message_handler.h", "webui/md_bookmarks/md_bookmarks_ui.cc", "webui/md_bookmarks/md_bookmarks_ui.h", "webui/md_downloads/downloads_list_tracker.cc",
diff --git a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm index e237b99..0dfd1bc 100644 --- a/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/page_info/page_info_bubble_controller.mm
@@ -541,11 +541,7 @@ - (void)showSiteSettingsData:(id)sender { DCHECK(webContents_); DCHECK(presenter_); - presenter_->RecordPageInfoAction(PageInfo::PAGE_INFO_SITE_SETTINGS_OPENED); - webContents_->OpenURL(content::OpenURLParams( - GURL(chrome::kChromeUIContentSettingsURL), content::Referrer(), - WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, - false)); + presenter_->OpenSiteSettingsView(); } // TODO(lgarron): Move some of this to the presenter for separation of concerns
diff --git a/chrome/browser/ui/page_info/page_info.cc b/chrome/browser/ui/page_info/page_info.cc index b5a07be5..0d815e74 100644 --- a/chrome/browser/ui/page_info/page_info.cc +++ b/chrome/browser/ui/page_info/page_info.cc
@@ -43,6 +43,7 @@ #include "chrome/browser/ui/page_info/page_info_ui.h" #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/grit/theme_resources.h" @@ -66,6 +67,7 @@ #include "net/ssl/ssl_connection_status_flags.h" #include "third_party/boringssl/src/include/openssl/ssl.h" #include "ui/base/l10n/l10n_util.h" +#include "url/origin.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/policy/policy_cert_service.h" @@ -411,6 +413,31 @@ did_revoke_user_ssl_decisions_ = true; } +void PageInfo::OpenSiteSettingsView() { + // By default, this opens the general Content Settings pane. If the + // |kSiteSettings| and/or |kSiteDetails| flags are enabled this opens a + // settings page specific to the current origin of the page. crbug.com/655876 + url::Origin site_origin = url::Origin(site_url()); + std::string link_destination(chrome::kChromeUIContentSettingsURL); + if ((base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableSiteSettings) || + base::FeatureList::IsEnabled(features::kSiteDetails)) && + !site_origin.unique()) { + std::string origin_string = site_origin.Serialize(); + url::RawCanonOutputT<char> percent_encoded_origin; + url::EncodeURIComponent(origin_string.c_str(), origin_string.length(), + &percent_encoded_origin); + link_destination = chrome::kChromeUISiteDetailsPrefixURL + + std::string(percent_encoded_origin.data(), + percent_encoded_origin.length()); + } + web_contents()->OpenURL( + content::OpenURLParams(GURL(link_destination), content::Referrer(), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_LINK, false)); + RecordPageInfoAction(PageInfo::PAGE_INFO_SITE_SETTINGS_OPENED); +} + void PageInfo::Init(const GURL& url, const security_state::SecurityInfo& security_info) { #if !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/chrome/browser/ui/page_info/page_info.h b/chrome/browser/ui/page_info/page_info.h index 49eaff4..f7f981e 100644 --- a/chrome/browser/ui/page_info/page_info.h +++ b/chrome/browser/ui/page_info/page_info.h
@@ -142,6 +142,9 @@ // This method is called when the revoke SSL error bypass button is pressed. void OnRevokeSSLErrorBypassButtonPressed(); + // Handles opening the link to show more site settings and records the event. + void OpenSiteSettingsView(); + // Accessors. SiteConnectionStatus site_connection_status() const { return site_connection_status_;
diff --git a/chrome/browser/ui/view_ids.h b/chrome/browser/ui/view_ids.h index 78a02ed..aa0204a 100644 --- a/chrome/browser/ui/view_ids.h +++ b/chrome/browser/ui/view_ids.h
@@ -95,6 +95,14 @@ // Plus button on location bar. VIEW_ID_ACTION_BOX_BUTTON, + + // Page Info bubble. + VIEW_ID_PAGE_INFO_BUTTON_CLOSE, + VIEW_ID_PAGE_INFO_LABEL_SECURITY_DETAILS, + VIEW_ID_PAGE_INFO_LABEL_RESET_CERTIFICATE_DECISIONS, + VIEW_ID_PAGE_INFO_LINK_COOKIE_DIALOG, + VIEW_ID_PAGE_INFO_LINK_SITE_SETTINGS, + VIEW_ID_PAGE_INFO_LINK_CERTIFICATE_VIEWER, }; #endif // CHROME_BROWSER_UI_VIEW_IDS_H_
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index 71e22e32..abdd29e7 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/page_info/page_info.h" +#include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/collected_cookies_views.h" #include "chrome/browser/ui/views/harmony/chrome_layout_provider.h" #include "chrome/browser/ui/views/harmony/chrome_typography.h" @@ -60,14 +61,14 @@ namespace { -// NOTE(jdonnelly): This use of this process-wide variable assumes that there's -// never more than one page info bubble shown and that it's associated -// with the current window. If this assumption fails in the future, we'll need -// to return a weak pointer from ShowBubble so callers can associate it with the -// current window (or other context) and check if the bubble they care about is -// showing. +// NOTE(jdonnelly): The following two process-wide variables assume that there's +// never more than one page info bubble shown and that it's associated with the +// current window. If this assumption fails in the future, we'll need to return +// a weak pointer from ShowBubble so callers can associate it with the current +// window (or other context) and check if the bubble they care about is showing. PageInfoBubbleView::BubbleType g_shown_bubble_type = PageInfoBubbleView::BUBBLE_NONE; +views::BubbleDialogDelegateView* g_page_info_bubble = nullptr; // General constants ----------------------------------------------------------- @@ -99,14 +100,6 @@ // Spacing between the label and the menu. const int kPermissionMenuSpacing = 16; -// Button/styled label/link IDs ------------------------------------------------ -const int BUTTON_CLOSE = 1337; -const int STYLED_LABEL_SECURITY_DETAILS = 1338; -const int STYLED_LABEL_RESET_CERTIFICATE_DECISIONS = 1339; -const int LINK_COOKIE_DIALOG = 1340; -const int LINK_SITE_SETTINGS = 1341; -const int LINK_CERTIFICATE_VIEWER = 1342; - // The default, ui::kTitleFontSizeDelta, is too large for the page info // bubble (e.g. +3). Use +1 to obtain a smaller font. constexpr int kSummaryFontSizeDelta = 1; @@ -189,13 +182,13 @@ // The label that displays the status of the identity check for this site. // Includes a link to open the Chrome Help Center article about connection // security. - views::StyledLabel* details_label_; + views::StyledLabel* security_details_label_; // A container for the styled label with a link for resetting cert decisions. // This is only shown sometimes, so we use a container to keep track of // where to place it (if needed). views::View* reset_decisions_label_container_; - views::StyledLabel* reset_decisions_label_; + views::StyledLabel* reset_cert_decisions_label_; DISALLOW_COPY_AND_ASSIGN(BubbleHeaderView); }; @@ -234,9 +227,9 @@ views::StyledLabelListener* styled_label_listener, int side_margin) : styled_label_listener_(styled_label_listener), - details_label_(nullptr), + security_details_label_(nullptr), reset_decisions_label_container_(nullptr), - reset_decisions_label_(nullptr) { + reset_cert_decisions_label_(nullptr) { views::GridLayout* layout = new views::GridLayout(this); SetLayoutManager(layout); @@ -245,10 +238,10 @@ layout->AddPaddingRow(0, kHeaderLabelSpacing); layout->StartRow(0, label_column_status); - details_label_ = + security_details_label_ = new views::StyledLabel(base::string16(), styled_label_listener); - details_label_->set_id(STYLED_LABEL_SECURITY_DETAILS); - layout->AddView(details_label_, 1, 1, views::GridLayout::FILL, + security_details_label_->set_id(VIEW_ID_PAGE_INFO_LABEL_SECURITY_DETAILS); + layout->AddView(security_details_label_, 1, 1, views::GridLayout::FILL, views::GridLayout::LEADING); layout->StartRow(0, label_column_status); @@ -272,7 +265,7 @@ base::string16 text = base::ReplaceStringPlaceholders( base::ASCIIToUTF16("$1 $2"), subst, &offsets); - details_label_->SetText(text); + security_details_label_->SetText(text); gfx::Range details_range(offsets[1], text.length()); views::StyledLabel::RangeStyleInfo link_style = @@ -281,7 +274,7 @@ link_style.font_style |= gfx::Font::FontStyle::UNDERLINE; link_style.disable_line_wrapping = false; - details_label_->AddStyleRange(details_range, link_style); + security_details_label_->AddStyleRange(details_range, link_style); } void BubbleHeaderView::AddResetDecisionsLabel() { @@ -295,8 +288,10 @@ base::string16 text = base::ReplaceStringPlaceholders( base::ASCIIToUTF16("$1 $2"), subst, &offsets); - reset_decisions_label_ = new views::StyledLabel(text, styled_label_listener_); - reset_decisions_label_->set_id(STYLED_LABEL_RESET_CERTIFICATE_DECISIONS); + reset_cert_decisions_label_ = + new views::StyledLabel(text, styled_label_listener_); + reset_cert_decisions_label_->set_id( + VIEW_ID_PAGE_INFO_LABEL_RESET_CERTIFICATE_DECISIONS); gfx::Range link_range(offsets[1], text.length()); views::StyledLabel::RangeStyleInfo link_style = @@ -305,10 +300,10 @@ link_style.font_style |= gfx::Font::FontStyle::UNDERLINE; link_style.disable_line_wrapping = false; - reset_decisions_label_->AddStyleRange(link_range, link_style); + reset_cert_decisions_label_->AddStyleRange(link_range, link_style); // Fit the styled label to occupy available width. - reset_decisions_label_->SizeToFit(0); - reset_decisions_label_container_->AddChildView(reset_decisions_label_); + reset_cert_decisions_label_->SizeToFit(0); + reset_decisions_label_container_->AddChildView(reset_cert_decisions_label_); // Now that it contains a label, the container needs padding at the top. reset_decisions_label_container_->SetBorder( @@ -327,6 +322,7 @@ const GURL& url) : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) { g_shown_bubble_type = PageInfoBubbleView::BUBBLE_INTERNAL_PAGE; + g_page_info_bubble = this; set_parent_window(parent_window); int text = IDS_PAGE_INFO_INTERNAL_PAGE; @@ -370,6 +366,7 @@ void InternalPageInfoBubbleView::OnWidgetDestroying(views::Widget* widget) { g_shown_bubble_type = PageInfoBubbleView::BUBBLE_NONE; + g_page_info_bubble = nullptr; } int InternalPageInfoBubbleView::GetDialogButtons() const { @@ -422,6 +419,11 @@ return g_shown_bubble_type; } +// static +views::BubbleDialogDelegateView* PageInfoBubbleView::GetPageInfoBubble() { + return g_page_info_bubble; +} + PageInfoBubbleView::PageInfoBubbleView( views::View* anchor_view, gfx::NativeView parent_window, @@ -439,6 +441,7 @@ permissions_view_(nullptr), weak_factory_(this) { g_shown_bubble_type = BUBBLE_PAGE_INFO; + g_page_info_bubble = this; set_parent_window(parent_window); // Compensate for built-in vertical padding in the anchor view's image. @@ -536,6 +539,7 @@ void PageInfoBubbleView::OnWidgetDestroying(views::Widget* widget) { g_shown_bubble_type = BUBBLE_NONE; + g_page_info_bubble = nullptr; presenter_->OnUIClosing(); } @@ -550,7 +554,7 @@ void PageInfoBubbleView::ButtonPressed(views::Button* button, const ui::Event& event) { - DCHECK_EQ(BUTTON_CLOSE, button->id()); + DCHECK_EQ(VIEW_ID_PAGE_INFO_BUTTON_CLOSE, button->id()); GetWidget()->Close(); } @@ -660,7 +664,7 @@ // Add site settings link. views::Link* site_settings_link = new views::Link( l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_SETTINGS_LINK)); - site_settings_link->set_id(LINK_SITE_SETTINGS); + site_settings_link->set_id(VIEW_ID_PAGE_INFO_LINK_SITE_SETTINGS); site_settings_link->set_listener(this); views::View* link_section = new views::View(); const int kLinkMarginTop = 4; @@ -695,11 +699,12 @@ : IDS_PAGE_INFO_CERTIFICATE_INVALID_LINK); // Create the link to add to the Certificate Section. - views::Link* inspect_link = new views::Link(link_title); - inspect_link->set_id(LINK_CERTIFICATE_VIEWER); - inspect_link->set_listener(this); + views::Link* certificate_viewer_link = new views::Link(link_title); + certificate_viewer_link->set_id( + VIEW_ID_PAGE_INFO_LINK_CERTIFICATE_VIEWER); + certificate_viewer_link->set_listener(this); if (valid_identity) { - inspect_link->SetTooltipText(l10n_util::GetStringFUTF16( + certificate_viewer_link->SetTooltipText(l10n_util::GetStringFUTF16( IDS_PAGE_INFO_CERTIFICATE_VALID_LINK_TOOLTIP, base::UTF8ToUTF16(certificate_->issuer().GetDisplayName()))); } @@ -707,7 +712,8 @@ // Add the Certificate Section. site_settings_view_->AddChildViewAt( CreateInspectLinkSection(PageInfoUI::GetCertificateIcon(), - IDS_PAGE_INFO_CERTIFICATE, inspect_link), + IDS_PAGE_INFO_CERTIFICATE, + certificate_viewer_link), 0); } } @@ -729,7 +735,7 @@ // Create the link and icon for the Certificate section. cookie_dialog_link_ = new views::Link( l10n_util::GetPluralStringFUTF16(IDS_PAGE_INFO_NUM_COOKIES, 0)); - cookie_dialog_link_->set_id(LINK_COOKIE_DIALOG); + cookie_dialog_link_->set_id(VIEW_ID_PAGE_INFO_LINK_COOKIE_DIALOG); cookie_dialog_link_->set_listener(this); PageInfoUI::PermissionInfo info; @@ -752,25 +758,16 @@ if (web_contents() == nullptr || web_contents()->IsBeingDestroyed()) return; switch (source->id()) { - case LINK_SITE_SETTINGS: - // TODO(crbug.com/655876): This opens the general Content Settings pane, - // which is OK for now. But on Android, it opens a page specific to a - // given origin that shows all of the settings for that origin. If/when - // that's available on desktop we should link to that here, too. - web_contents()->OpenURL(content::OpenURLParams( - GURL(chrome::kChromeUIContentSettingsURL), content::Referrer(), - WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, - false)); - presenter_->RecordPageInfoAction( - PageInfo::PAGE_INFO_SITE_SETTINGS_OPENED); + case VIEW_ID_PAGE_INFO_LINK_SITE_SETTINGS: + presenter_->OpenSiteSettingsView(); break; - case LINK_COOKIE_DIALOG: + case VIEW_ID_PAGE_INFO_LINK_COOKIE_DIALOG: // Count how often the Collected Cookies dialog is opened. presenter_->RecordPageInfoAction( PageInfo::PAGE_INFO_COOKIES_DIALOG_OPENED); new CollectedCookiesViews(web_contents()); break; - case LINK_CERTIFICATE_VIEWER: { + case VIEW_ID_PAGE_INFO_LINK_CERTIFICATE_VIEWER: { gfx::NativeWindow top_window = web_contents()->GetTopLevelNativeWindow(); if (certificate_ && top_window) { presenter_->RecordPageInfoAction( @@ -788,7 +785,7 @@ const gfx::Range& range, int event_flags) { switch (label->id()) { - case STYLED_LABEL_SECURITY_DETAILS: + case VIEW_ID_PAGE_INFO_LABEL_SECURITY_DETAILS: web_contents()->OpenURL(content::OpenURLParams( GURL(chrome::kPageInfoHelpCenterURL), content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, @@ -796,7 +793,7 @@ presenter_->RecordPageInfoAction( PageInfo::PAGE_INFO_CONNECTION_HELP_OPENED); break; - case STYLED_LABEL_RESET_CERTIFICATE_DECISIONS: + case VIEW_ID_PAGE_INFO_LABEL_RESET_CERTIFICATE_DECISIONS: presenter_->OnRevokeSSLErrorBypassButtonPressed(); GetWidget()->Close(); break;
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.h b/chrome/browser/ui/views/page_info/page_info_bubble_view.h index d8cfbfd9..41002b1f 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.h +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.h
@@ -88,6 +88,9 @@ // Returns the type of the bubble being shown. static BubbleType GetShownBubbleType(); + // Returns a weak reference to the page info bubble being shown. + static views::BubbleDialogDelegateView* GetPageInfoBubble(); + private: friend class test::PageInfoBubbleViewTestApi;
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc new file mode 100644 index 0000000..29d96d4 --- /dev/null +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -0,0 +1,174 @@ +// Copyright 2016 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 "chrome/browser/ui/views/page_info/page_info_bubble_view.h" + +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/view_ids.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "chrome/browser/ui/views/location_bar/location_icon_view.h" +#include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test_utils.h" +#include "ui/accessibility/ax_action_data.h" + +namespace { + +typedef InProcessBrowserTest PageInfoBubbleViewBrowserTest; + +void PerformMouseClickOnView(views::View* view) { + ui::AXActionData data; + data.action = ui::AX_ACTION_DO_DEFAULT; + view->HandleAccessibleAction(data); +} + +// Clicks the location icon to open the page info bubble. +void OpenPageInfoBubble(Browser* browser) { + BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); + views::View* location_icon_view = + browser_view->toolbar()->location_bar()->location_icon_view(); + ASSERT_TRUE(location_icon_view); + PerformMouseClickOnView(location_icon_view); + views::BubbleDialogDelegateView* page_info = + PageInfoBubbleView::GetPageInfoBubble(); + EXPECT_NE(nullptr, page_info); + page_info->set_close_on_deactivate(false); +} + +// Opens the Page Info bubble and retrieves the "Site settings" button. +views::View* GetSiteSettingsButton(Browser* browser) { + OpenPageInfoBubble(browser); + views::Widget* page_info_bubble = + PageInfoBubbleView::GetPageInfoBubble()->GetWidget(); + EXPECT_TRUE(page_info_bubble); + + // Retrieve the "Site settings" button. + views::View* site_settings_button = + page_info_bubble->GetRootView()->GetViewByID( + VIEW_ID_PAGE_INFO_LINK_SITE_SETTINGS); + EXPECT_TRUE(site_settings_button); + return site_settings_button; +} + +// Clicks the "Site settings" button from Page Info and waits for a "Settings" +// tab to open. +void ClickAndWaitForSettingsPageToOpen(views::View* site_settings_button) { + content::WebContentsAddedObserver new_tab_observer; + PerformMouseClickOnView(site_settings_button); + + base::string16 expected_title(base::ASCIIToUTF16("Settings")); + content::TitleWatcher title_watcher(new_tab_observer.GetWebContents(), + expected_title); + EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); +} + +// Returns the URL of the new tab that's opened on clicking the "Site settings" +// button from Page Info. +const GURL OpenSiteSettingsForUrl(Browser* browser, + const GURL& url, + bool enable_site_details) { + ui_test_utils::NavigateToURL(browser, url); + views::View* site_settings_button = GetSiteSettingsButton(browser); + base::test::ScopedFeatureList feature_list; + if (enable_site_details) + feature_list.InitAndEnableFeature(features::kSiteDetails); + else + feature_list.InitAndDisableFeature(features::kSiteDetails); + ClickAndWaitForSettingsPageToOpen(site_settings_button); + + return browser->tab_strip_model() + ->GetActiveWebContents() + ->GetLastCommittedURL(); +} + +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ShowBubble) { + OpenPageInfoBubble(browser()); + EXPECT_EQ(PageInfoBubbleView::BUBBLE_PAGE_INFO, + PageInfoBubbleView::GetShownBubbleType()); +} + +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ChromeURL) { + ui_test_utils::NavigateToURL(browser(), GURL("chrome://settings")); + OpenPageInfoBubble(browser()); + EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, + PageInfoBubbleView::GetShownBubbleType()); +} + +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ChromeExtensionURL) { + ui_test_utils::NavigateToURL( + browser(), GURL("chrome-extension://extension-id/options.html")); + OpenPageInfoBubble(browser()); + EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, + PageInfoBubbleView::GetShownBubbleType()); +} + +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ChromeDevtoolsURL) { + ui_test_utils::NavigateToURL( + browser(), GURL("chrome-devtools://devtools/bundled/inspector.html")); + OpenPageInfoBubble(browser()); + EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, + PageInfoBubbleView::GetShownBubbleType()); +} + +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ViewSourceURL) { + ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); + chrome::ViewSelectedSource(browser()); + OpenPageInfoBubble(browser()); + EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, + PageInfoBubbleView::GetShownBubbleType()); +} + +// Test opening "Content Settings" via Page Info from an ASCII origin works. +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, SiteSettingsLink) { + GURL url = GURL("https://www.google.com/"); + EXPECT_EQ(GURL(chrome::kChromeUIContentSettingsURL), + OpenSiteSettingsForUrl(browser(), url, false)); +} + +// Test opening "Site Details" via Page Info from an ASCII origin does the +// correct URL canonicalization. +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, + SiteSettingsLinkWithSiteDetailsEnabled) { + GURL url = GURL("https://www.google.com/"); + std::string expected_origin = "https%3A%2F%2Fwww.google.com"; + EXPECT_EQ(GURL(chrome::kChromeUISiteDetailsPrefixURL + expected_origin), + OpenSiteSettingsForUrl(browser(), url, true)); +} + +// Test opening "Site Details" via Page Info from a non-ASCII URL converts it to +// an origin and does punycode conversion as well as URL canonicalization. +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, + SiteSettingsLinkWithSiteDetailsEnabledAndNonAsciiUrl) { + GURL url = GURL("http://🥄.ws/other/stuff.htm"); + std::string expected_origin = "http%3A%2F%2Fxn--9q9h.ws"; + EXPECT_EQ(GURL(chrome::kChromeUISiteDetailsPrefixURL + expected_origin), + OpenSiteSettingsForUrl(browser(), url, true)); +} + +// Test opening "Site Details" via Page Info from an origin with a non-default +// (scheme, port) pair will specify port # in the origin passed to query params. +IN_PROC_BROWSER_TEST_F( + PageInfoBubbleViewBrowserTest, + SiteSettingsLinkWithSiteDetailsEnabledAndNonDefaultPort) { + GURL url = GURL("https://www.example.com:8372"); + std::string expected_origin = "https%3A%2F%2Fwww.example.com%3A8372"; + EXPECT_EQ(GURL(chrome::kChromeUISiteDetailsPrefixURL + expected_origin), + OpenSiteSettingsForUrl(browser(), url, true)); +} + +// Test opening "Site Details" via Page Info from about:blank goes to "Content +// Settings" (the alternative is a blank origin being sent to "Site Details"). +IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, + SiteSettingsLinkAboutBlankWithSiteDetailsEnabled) { + EXPECT_EQ(GURL(chrome::kChromeUIContentSettingsURL), + OpenSiteSettingsForUrl(browser(), GURL(url::kAboutBlankURL), true)); +} + +} // namespace
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_interactive_uitest.cc deleted file mode 100644 index ee22800..0000000 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_interactive_uitest.cc +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2016 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 "chrome/browser/ui/views/page_info/page_info_bubble_view.h" - -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/browser/ui/views/location_bar/location_bar_view.h" -#include "chrome/browser/ui/views/location_bar/location_icon_view.h" -#include "chrome/browser/ui/views/toolbar/toolbar_view.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/interactive_test_utils.h" - -namespace { - -typedef InProcessBrowserTest PageInfoBubbleViewBrowserTest; - -// Clicks the location icon to open the page info bubble. -void ClickAndWait(Browser* browser) { - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); - views::View* location_icon_view = - browser_view->toolbar()->location_bar()->location_icon_view(); - ASSERT_TRUE(location_icon_view); - - scoped_refptr<content::MessageLoopRunner> runner = - new content::MessageLoopRunner; - ui_test_utils::MoveMouseToCenterAndPress( - location_icon_view, ui_controls::LEFT, - ui_controls::DOWN | ui_controls::UP, runner->QuitClosure()); - runner->Run(); -} - -IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ShowBubble) { - ClickAndWait(browser()); - EXPECT_EQ(PageInfoBubbleView::BUBBLE_PAGE_INFO, - PageInfoBubbleView::GetShownBubbleType()); -} - -IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ChromeURL) { - ui_test_utils::NavigateToURL(browser(), GURL("chrome://settings")); - ClickAndWait(browser()); - EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, - PageInfoBubbleView::GetShownBubbleType()); -} - -IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ChromeExtensionURL) { - ui_test_utils::NavigateToURL( - browser(), GURL("chrome-extension://extension-id/options.html")); - ClickAndWait(browser()); - EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, - PageInfoBubbleView::GetShownBubbleType()); -} - -IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ChromeDevtoolsURL) { - ui_test_utils::NavigateToURL( - browser(), GURL("chrome-devtools://devtools/bundled/inspector.html")); - ClickAndWait(browser()); - EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, - PageInfoBubbleView::GetShownBubbleType()); -} - -IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewBrowserTest, ViewSourceURL) { - ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); - chrome::ViewSelectedSource(browser()); - ClickAndWait(browser()); - EXPECT_EQ(PageInfoBubbleView::BUBBLE_INTERNAL_PAGE, - PageInfoBubbleView::GetShownBubbleType()); -} - -} // namespace
diff --git a/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.cc b/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.cc new file mode 100644 index 0000000..47dea5bc --- /dev/null +++ b/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.cc
@@ -0,0 +1,58 @@ +// 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 "chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.h" + +#include "base/bind.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_change_registrar.h" +#include "components/prefs/pref_service.h" + +BookmarksMessageHandler::BookmarksMessageHandler() {} + +BookmarksMessageHandler::~BookmarksMessageHandler() {} + +void BookmarksMessageHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "getIncognitoAvailability", + base::Bind(&BookmarksMessageHandler::HandleGetIncognitoAvailability, + base::Unretained(this))); +} + +void BookmarksMessageHandler::OnJavascriptAllowed() { + PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); + pref_change_registrar_.Init(prefs); + pref_change_registrar_.Add( + prefs::kIncognitoModeAvailability, + base::Bind(&BookmarksMessageHandler::UpdateIncognitoAvailability, + base::Unretained(this))); +} + +void BookmarksMessageHandler::OnJavascriptDisallowed() { + pref_change_registrar_.RemoveAll(); +} + +void BookmarksMessageHandler::UpdateIncognitoAvailability() { + FireWebUIListener("incognito-availability-changed", + base::Value(GetIncognitoAvailability())); +} + +int BookmarksMessageHandler::GetIncognitoAvailability() { + PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs(); + return prefs->GetInteger(prefs::kIncognitoModeAvailability); +} + +void BookmarksMessageHandler::HandleGetIncognitoAvailability( + const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + const base::Value* callback_id; + CHECK(args->Get(0, &callback_id)); + + AllowJavascript(); + + ResolveJavascriptCallback(*callback_id, + base::Value(GetIncognitoAvailability())); +}
diff --git a/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.h b/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.h new file mode 100644 index 0000000..e76640c --- /dev/null +++ b/chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.h
@@ -0,0 +1,35 @@ +// 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 CHROME_BROWSER_UI_WEBUI_MD_BOOKMARKS_BOOKMARKS_MESSAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_MD_BOOKMARKS_BOOKMARKS_MESSAGE_HANDLER_H_ + +#include "components/prefs/pref_change_registrar.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace base { +class ListValue; +}; + +class BookmarksMessageHandler : public content::WebUIMessageHandler { + public: + BookmarksMessageHandler(); + ~BookmarksMessageHandler() override; + + private: + int GetIncognitoAvailability(); + void HandleGetIncognitoAvailability(const base::ListValue* args); + void UpdateIncognitoAvailability(); + + // content::WebUIMessageHandler: + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + PrefChangeRegistrar pref_change_registrar_; + + DISALLOW_COPY_AND_ASSIGN(BookmarksMessageHandler); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_MD_BOOKMARKS_BOOKMARKS_MESSAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc new file mode 100644 index 0000000..fa9ce17 --- /dev/null +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc
@@ -0,0 +1,48 @@ +// 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 "chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.h" + +#include "chrome/browser/prefs/incognito_mode_prefs.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_service.h" + +MdBookmarksBrowserTest::MdBookmarksBrowserTest() {} + +MdBookmarksBrowserTest::~MdBookmarksBrowserTest() {} + +void MdBookmarksBrowserTest::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "testSetIncognito", + base::Bind(&MdBookmarksBrowserTest::HandleSetIncognitoAvailability, + base::Unretained(this))); +} + +void MdBookmarksBrowserTest::SetIncognitoAvailability(int availability) { + ASSERT_TRUE(availability >= 0 && + availability < IncognitoModePrefs::AVAILABILITY_NUM_TYPES); + browser()->profile()->GetPrefs()->SetInteger( + prefs::kIncognitoModeAvailability, availability); +} + +void MdBookmarksBrowserTest::HandleSetIncognitoAvailability( + const base::ListValue* args) { + AllowJavascript(); + + ASSERT_EQ(2U, args->GetSize()); + const base::Value* callback_id; + ASSERT_TRUE(args->Get(0, &callback_id)); + int pref_value; + ASSERT_TRUE(args->GetInteger(1, &pref_value)); + + SetIncognitoAvailability(pref_value); + + ResolveJavascriptCallback(*callback_id, base::Value()); +} + +content::WebUIMessageHandler* MdBookmarksBrowserTest::GetMockMessageHandler() { + return this; +}
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.h b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.h new file mode 100644 index 0000000..4fd3d57 --- /dev/null +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.h
@@ -0,0 +1,31 @@ +// 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 CHROME_BROWSER_UI_WEBUI_MD_BOOKMARKS_MD_BOOKMARKS_BROWSERTEST_H_ +#define CHROME_BROWSER_UI_WEBUI_MD_BOOKMARKS_MD_BOOKMARKS_BROWSERTEST_H_ + +#include "chrome/test/base/web_ui_browser_test.h" +#include "content/public/browser/web_ui_message_handler.h" + +class MdBookmarksBrowserTest : public WebUIBrowserTest, + public content::WebUIMessageHandler { + public: + MdBookmarksBrowserTest(); + ~MdBookmarksBrowserTest() override; + + void SetIncognitoAvailability(int availability); + + private: + void HandleSetIncognitoAvailability(const base::ListValue* args); + + // content::WebUIMessageHandler: + void RegisterMessages() override; + + // WebUIBrowserTest: + content::WebUIMessageHandler* GetMockMessageHandler() override; + + DISALLOW_COPY_AND_ASSIGN(MdBookmarksBrowserTest); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_MD_BOOKMARKS_MD_BOOKMARKS_BROWSERTEST_H_
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc index a7e62da5..76d0fec 100644 --- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -5,9 +5,11 @@ #include "chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.h" #include <algorithm> +#include <string> #include "base/strings/string16.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.h" #include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" @@ -152,6 +154,8 @@ Profile* profile = Profile::FromWebUI(web_ui); content::WebUIDataSource::Add(profile, CreateMdBookmarksUIHTMLSource(profile)); + + web_ui->AddMessageHandler(base::MakeUnique<BookmarksMessageHandler>()); } // static
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 008760be..21c8ad2 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1899,6 +1899,8 @@ html_source->AddBoolean("enableSiteSettings", base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableSiteSettings)); + html_source->AddBoolean("enableSiteDetails", + base::FeatureList::IsEnabled(features::kSiteDetails)); html_source->AddBoolean( "enableSafeBrowsingSubresourceFilter", base::FeatureList::IsEnabled(
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index ea8be8c..82bd662 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -82,6 +82,8 @@ const char kChromeUIRestartURL[] = "chrome://restart/"; const char kChromeUISettingsURL[] = "chrome://settings/"; const char kChromeUIContentSettingsURL[] = "chrome://settings/content"; +const char kChromeUISiteDetailsPrefixURL[] = + "chrome://settings/content/siteDetails?site="; const char kChromeUISettingsFrameURL[] = "chrome://settings-frame/"; const char kChromeUISigninEmailConfirmationURL[] = "chrome://signin-email-confirmation";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index caade9df..a9f875a 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -79,6 +79,7 @@ extern const char kChromeUISettingsFrameURL[]; extern const char kChromeUISigninEmailConfirmationURL[]; extern const char kChromeUISigninErrorURL[]; +extern const char kChromeUISiteDetailsPrefixURL[]; extern const char kChromeUISiteEngagementHost[]; extern const char kChromeUISuggestionsURL[]; extern const char kChromeUISupervisedUserPassphrasePageURL[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 9e73427..603fa20 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -624,7 +624,6 @@ "../browser/ui/views/location_bar/location_icon_view_interactive_uitest.cc", "../browser/ui/views/location_bar/star_view_browsertest.cc", "../browser/ui/views/omnibox/omnibox_view_views_browsertest.cc", - "../browser/ui/views/page_info/page_info_bubble_view_interactive_uitest.cc", "../browser/ui/views/passwords/manage_passwords_icon_view_interactive_uitest.cc", "../browser/ui/views/ssl_client_certificate_selector_browsertest.cc", "../browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc", @@ -1711,6 +1710,8 @@ "../browser/ui/webui/inspect_ui_browsertest.cc", "../browser/ui/webui/interstitials/interstitial_ui_browsertest.cc", "../browser/ui/webui/log_web_ui_url_browsertest.cc", + "../browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.cc", + "../browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.h", "../browser/ui/webui/media_router/media_router_dialog_controller_impl_browsertest.cc", "../browser/ui/webui/net_internals/net_internals_ui_browsertest.cc", "../browser/ui/webui/net_internals/net_internals_ui_browsertest.h", @@ -2098,6 +2099,7 @@ "../browser/ui/views/frame/browser_view_browsertest.cc", "../browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc", "../browser/ui/views/media_router/media_router_ui_browsertest.cc", + "../browser/ui/views/page_info/page_info_bubble_view_browsertest.cc", "../browser/ui/views/passwords/password_dialog_view_browsertest.cc", "../browser/ui/views/session_crashed_bubble_view_browsertest.cc", "../browser/ui/views/task_manager_view_browsertest.cc",
diff --git a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js index d36ae63..7b89786 100644 --- a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js +++ b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js
@@ -10,6 +10,8 @@ GEN_INCLUDE( [ROOT_PATH + 'chrome/test/data/webui/polymer_browser_test_base.js']); GEN('#include "base/command_line.h"'); +GEN('#include "chrome/browser/prefs/incognito_mode_prefs.h"'); +GEN('#include "chrome/browser/ui/webui/md_bookmarks/md_bookmarks_browsertest.h"'); function MaterialBookmarksBrowserTest() {} @@ -21,6 +23,8 @@ commandLineSwitches: [{switchName: 'enable-features', switchValue: 'MaterialDesignBookmarks'}], + typedefCppFixture: 'MdBookmarksBrowserTest', + extraLibraries: PolymerTest.getLibraries(ROOT_PATH).concat([ 'test_command_manager.js', 'test_store.js', @@ -168,6 +172,24 @@ mocha.run(); }); +function MaterialBookmarksPolicyTest() {} + +MaterialBookmarksPolicyTest.prototype = { + __proto__: MaterialBookmarksBrowserTest.prototype, + + testGenPreamble: function() { + GEN('SetIncognitoAvailability(IncognitoModePrefs::DISABLED);'); + }, + + extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + 'policy_test.js', + ]), +}; + +TEST_F('MaterialBookmarksPolicyTest', 'All', function() { + mocha.run(); +}); + function MaterialBookmarksStoreClientTest() {} MaterialBookmarksStoreClientTest.prototype = {
diff --git a/chrome/test/data/webui/md_bookmarks/policy_test.js b/chrome/test/data/webui/md_bookmarks/policy_test.js new file mode 100644 index 0000000..f04fe3df3 --- /dev/null +++ b/chrome/test/data/webui/md_bookmarks/policy_test.js
@@ -0,0 +1,45 @@ +// 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. + +suite('Incognito policy', function() { + var store; + var app; + + setup(function() { + store = new bookmarks.TestStore({ + nodes: testTree(createFolder( + '1', + [ + createItem('11'), + ])), + selectedFolder: '1', + }); + store.setReducersEnabled(true); + store.expectAction('set-incognito-availability'); + bookmarks.Store.instance_ = store; + + app = document.createElement('bookmarks-app'); + replaceBody(app); + }); + + test('updates when changed by the browser', function() { + var commandManager = bookmarks.CommandManager.getInstance(); + // Incognito is disabled during testGenPreamble(). Wait for the front-end to + // load the config. + return store.waitForAction('set-incognito-availability').then(action => { + assertEquals(IncognitoAvailability.DISABLED, + store.data.prefs.incognitoAvailability); + assertFalse( + commandManager.canExecute(Command.OPEN_INCOGNITO, new Set(['11']))); + + return cr.sendWithPromise( + 'testSetIncognito', IncognitoAvailability.ENABLED); + }).then(() => { + assertEquals(IncognitoAvailability.ENABLED, + store.data.prefs.incognitoAvailability); + assertTrue( + commandManager.canExecute(Command.OPEN_INCOGNITO, new Set(['11']))); + }); + }); +});
diff --git a/chrome/test/data/webui/md_bookmarks/test_store.js b/chrome/test/data/webui/md_bookmarks/test_store.js index 10fab15..cdf2571c 100644 --- a/chrome/test/data/webui/md_bookmarks/test_store.js +++ b/chrome/test/data/webui/md_bookmarks/test_store.js
@@ -12,6 +12,8 @@ this.lastAction_ = null; this.acceptInit_ = false; this.enableReducers_ = false; + /** @type {!Map<string, !PromiseResolver>} */ + this.resolverMap_ = new Map(); }; TestStore.prototype = { @@ -54,6 +56,8 @@ this.lastAction_ = action; if (this.enableReducers_) bookmarks.Store.prototype.reduce_.call(this, action); + if (this.resolverMap_.has(action.name)) + this.resolverMap_.get(action.name).resolve(action); }, /** @@ -71,6 +75,32 @@ this.acceptInit_ = true; this.initialized_ = false; }, + + /** + * Track actions called |name|, allowing that type of action to be waited + * for with `waitForAction`. + * @param {string} name + */ + expectAction: function(name) { + this.resolverMap_.set(name, new PromiseResolver()); + }, + + /** + * Returns a Promise that will resolve when an action called |name| is + * dispatched. The promise must be prepared by calling + * `expectAction(name)` before the action is dispatched. + * @param {string} name + * @return {!Promise<!Action>} + */ + waitForAction: function(name) { + assertTrue( + this.resolverMap_.has(name), + 'Must call expectAction before each call to waitForAction'); + return this.resolverMap_.get(name).promise.then((action) => { + this.resolverMap_.delete(name); + return action; + }); + }, }; return {
diff --git a/components/arc/common/file_system.mojom b/components/arc/common/file_system.mojom index 24e4041..aa45972 100644 --- a/components/arc/common/file_system.mojom +++ b/components/arc/common/file_system.mojom
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// Next MinVersion: 4 +// Next MinVersion: 5 module arc.mojom; @@ -51,7 +51,7 @@ [MinVersion=3] OnDocumentChanged@0(int64 watcher_id, ChangeType type); }; -// Next method ID: 8 +// Next method ID: 9 interface FileSystemInstance { // Notes about Android Documents Provider: // @@ -105,6 +105,10 @@ // streams), -1 is returned. [MinVersion=1] GetFileSize@1(string url) => (int64 size); + // Asks the ContentResolver to get the MIME type of the file specified by the + // URL. When an error occurs, returns null value. + [MinVersion=4] GetMimeType@8(string url) => (string? mime_type); + // Establishes full-duplex communication with the host. [MinVersion=3] Init@5(FileSystemHost host_ptr);
diff --git a/components/arc/test/fake_file_system_instance.cc b/components/arc/test/fake_file_system_instance.cc index f522024..88eabd9 100644 --- a/components/arc/test/fake_file_system_instance.cc +++ b/components/arc/test/fake_file_system_instance.cc
@@ -64,8 +64,9 @@ FakeFileSystemInstance::File::File(const std::string& url, const std::string& content, + const std::string& mime_type, Seekable seekable) - : url(url), content(content), seekable(seekable) {} + : url(url), content(content), mime_type(mime_type), seekable(seekable) {} FakeFileSystemInstance::File::~File() = default; @@ -170,6 +171,20 @@ FROM_HERE, base::Bind(callback, file.content.size())); } +void FakeFileSystemInstance::GetMimeType(const std::string& url, + const GetMimeTypeCallback& callback) { + DCHECK(thread_checker_.CalledOnValidThread()); + auto iter = files_.find(url); + if (iter == files_.end()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback, base::nullopt)); + return; + } + const File& file = iter->second; + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback, file.mime_type)); +} + void FakeFileSystemInstance::OpenFileToRead( const std::string& url, const OpenFileToReadCallback& callback) {
diff --git a/components/arc/test/fake_file_system_instance.h b/components/arc/test/fake_file_system_instance.h index b852244..0d84eba 100644 --- a/components/arc/test/fake_file_system_instance.h +++ b/components/arc/test/fake_file_system_instance.h
@@ -29,6 +29,7 @@ // // Content URL based functions are: // - GetFileSize() +// - GetMimeType() // - OpenFileToRead() // Fake files for those functions can be set up by AddFile(). // @@ -56,10 +57,16 @@ // The content of a file. std::string content; + // The MIME type of a file. + std::string mime_type; + // Whether this file is seekable or not. Seekable seekable; - File(const std::string& url, const std::string& content, Seekable seekable); + File(const std::string& url, + const std::string& content, + const std::string& mime_type, + Seekable seekable); File(const File& that); ~File(); }; @@ -130,6 +137,8 @@ const GetDocumentCallback& callback) override; void GetFileSize(const std::string& url, const GetFileSizeCallback& callback) override; + void GetMimeType(const std::string& url, + const GetMimeTypeCallback& callback) override; void Init(mojom::FileSystemHostPtr host) override; void OpenFileToRead(const std::string& url, const OpenFileToReadCallback& callback) override;
diff --git a/components/drive/service/drive_api_service.cc b/components/drive/service/drive_api_service.cc index fd0a027..b62a058f 100644 --- a/components/drive/service/drive_api_service.cc +++ b/components/drive/service/drive_api_service.cc
@@ -17,6 +17,7 @@ #include "google_apis/drive/base_requests.h" #include "google_apis/drive/drive_api_parser.h" #include "google_apis/drive/drive_api_requests.h" +#include "google_apis/drive/drive_switches.h" #include "google_apis/drive/files_list_request_runner.h" #include "google_apis/drive/request_sender.h" #include "google_apis/google_api_keys.h" @@ -39,6 +40,7 @@ using google_apis::FileListCallback; using google_apis::FileResource; using google_apis::FileResourceCallback; +using google_apis::FilesListCorpora; using google_apis::FilesListRequestRunner; using google_apis::GetContentCallback; using google_apis::GetShareUrlCallback; @@ -347,6 +349,10 @@ request->set_max_results(kMaxNumFilesResourcePerRequest); request->set_q("trashed = false"); // Exclude trashed files. request->set_fields(kFileListFields); + if (google_apis::GetTeamDrivesIntegrationSwitch() == + google_apis::TEAM_DRIVES_INTEGRATION_ENABLED) { + request->set_corpora(google_apis::FilesListCorpora::ALL_TEAM_DRIVES); + } return sender_->StartRequestWithAuthRetry(std::move(request)); } @@ -357,6 +363,15 @@ DCHECK(!directory_resource_id.empty()); DCHECK(!callback.is_null()); + // TODO(yamaguchi): Use FileListScope::CreateForTeamDrive instead of + // kAllTeamDrives for efficiency. It'll require to add a new parameter to tell + // which team drive the directory resource belongs to. + FilesListCorpora corpora = + (google_apis::GetTeamDrivesIntegrationSwitch() == + google_apis::TEAM_DRIVES_INTEGRATION_ENABLED) + ? google_apis::FilesListCorpora::ALL_TEAM_DRIVES + : google_apis::FilesListCorpora::DEFAULT; + // Because children.list method on Drive API v2 returns only the list of // children's references, but we need all file resource list. // So, here we use files.list method instead, with setting parents query. @@ -365,7 +380,7 @@ // to client side. // We aren't interested in files in trash in this context, neither. return files_list_request_runner_->CreateAndStartWithSizeBackoff( - kMaxNumFilesResourcePerRequest, + kMaxNumFilesResourcePerRequest, corpora, std::string(), base::StringPrintf( "'%s' in parents and trashed = false", util::EscapeQueryStringValue(directory_resource_id).c_str()), @@ -379,8 +394,14 @@ DCHECK(!search_query.empty()); DCHECK(!callback.is_null()); + FilesListCorpora corpora = + (google_apis::GetTeamDrivesIntegrationSwitch() == + google_apis::TEAM_DRIVES_INTEGRATION_ENABLED) + ? google_apis::FilesListCorpora::ALL_TEAM_DRIVES + : google_apis::FilesListCorpora::DEFAULT; + return files_list_request_runner_->CreateAndStartWithSizeBackoff( - kMaxNumFilesResourcePerRequestForSearch, + kMaxNumFilesResourcePerRequestForSearch, corpora, std::string(), util::TranslateQuery(search_query), kFileListFields, callback); }
diff --git a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc index 5c35cc36..ed7de74 100644 --- a/content/browser/bluetooth/bluetooth_device_chooser_controller.cc +++ b/content/browser/bluetooth/bluetooth_device_chooser_controller.cc
@@ -491,6 +491,7 @@ } void BluetoothDeviceChooserController::PopulateConnectedDevices() { + // TODO(crbug.com/728897): Use RetrieveGattConnectedDevices once implemented. for (const device::BluetoothDevice* device : adapter_->GetDevices()) { if (device->IsGattConnected()) { AddFilteredDevice(*device);
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 264a1b2..cb79637 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -180,6 +180,25 @@ return trace_id; } +void OnEventDispatcherConnectionError( + base::WeakPtr<EmbeddedWorkerInstance> embedded_worker) { + if (!embedded_worker) + return; + + switch (embedded_worker->status()) { + case EmbeddedWorkerStatus::STARTING: + case EmbeddedWorkerStatus::RUNNING: + // In this case the disconnection might be happening because of sudden + // renderer shutdown like crash. + embedded_worker->Detach(); + break; + case EmbeddedWorkerStatus::STOPPING: + case EmbeddedWorkerStatus::STOPPED: + // Do nothing + break; + } +} + } // namespace const int ServiceWorkerVersion::kTimeoutTimerDelaySeconds = 30; @@ -1440,6 +1459,8 @@ std::move(params), mojo::MakeRequest(&event_dispatcher_), base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated, weak_factory_.GetWeakPtr())); + event_dispatcher_.set_connection_error_handler(base::Bind( + &OnEventDispatcherConnectionError, embedded_worker_->AsWeakPtr())); } void ServiceWorkerVersion::StartTimeoutTimer() {
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc index 5dc91dc..8bd2ee2 100644 --- a/content/browser/service_worker/service_worker_version_unittest.cc +++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -282,12 +282,15 @@ // Prepare for OnStopWorker(). instance_host_ptr_map_[embedded_worker_id].Bind( std::move(instance_host)); - break; // Do nothing. + // Just keep the connection alive. + event_dispatcher_request_map_[embedded_worker_id] = std::move(request); + break; case StartMode::FAIL: ASSERT_EQ(current_mock_instance_index_ + 1, mock_instance_clients()->size()); // Remove the connection by peer mock_instance_clients()->at(current_mock_instance_index_).reset(); + std::move(request); break; case StartMode::SUCCEED: MessageReceiver::OnStartWorker( @@ -317,6 +320,9 @@ int /* embedded_worker_id */, mojom::EmbeddedWorkerInstanceHostAssociatedPtr /* instance_host_ptr */> instance_host_ptr_map_; + std::map<int /* embedded_worker_id */, + mojom::ServiceWorkerEventDispatcherRequest> + event_dispatcher_request_map_; DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart); };
diff --git a/content/shell/test_runner/app_banner_service.cc b/content/shell/test_runner/app_banner_service.cc index f912715..2437435a 100644 --- a/content/shell/test_runner/app_banner_service.cc +++ b/content/shell/test_runner/app_banner_service.cc
@@ -33,7 +33,7 @@ base::Unretained(this), callback)); } -void AppBannerService::DisplayAppBanner() { /* do nothing */ +void AppBannerService::DisplayAppBanner(bool user_gesture) { /* do nothing */ } void AppBannerService::OnBannerPromptReply(
diff --git a/content/shell/test_runner/app_banner_service.h b/content/shell/test_runner/app_banner_service.h index 31a31133..9e040d7 100644 --- a/content/shell/test_runner/app_banner_service.h +++ b/content/shell/test_runner/app_banner_service.h
@@ -30,7 +30,7 @@ const base::Callback<void(bool)>& callback); // blink::mojom::AppBannerService overrides. - void DisplayAppBanner() override; + void DisplayAppBanner(bool user_gesture) override; private: void OnBannerPromptReply(const base::Callback<void(bool)>& callback,
diff --git a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom index a9d71fa..98da605 100644 --- a/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom +++ b/device/bluetooth/public/interfaces/test/fake_bluetooth.mojom
@@ -30,6 +30,10 @@ SimulateCentral(CentralState state) => (FakeCentral fake_central); }; +// HCI Error Codes from BT 4.2 Vol 2 Part D 1.3 List Of Error Codes. +const uint16 kHCISuccess = 0x0000; +const uint16 kHCIConnectionTimeout = 0x0008; + // FakeCentral allows clients to simulate events that a device in the // Central/Observer role would receive as well as monitor the operations // performed by the device in the Central/Observer role. @@ -48,7 +52,20 @@ // connected to the system or weren't connected through the UA e.g. a user // connected a peripheral through the system's settings. This method is // intended to simulate peripherals that those methods would return. + // Even though these devices are already connected to the OS, clients + // need to call the respective connect functions to signal they intend to keep + // the connection alive. SimulatePreconnectedPeripheral(string address, string name, array<UUID> known_service_uuids) => (); + + // Sets the next GATT Connection request response for peripheral with + // |address| to |code|. |code| could be an HCI Error Code from + // BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a number outside that range + // returned by specific platforms e.g. Android returns 0x101 to signal a GATT + // failure + // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE + // Calls callback with false if there was any error when simulating the next + // response. + SetNextGATTConnectionResponse(string address, uint16 code) => (bool success); };
diff --git a/device/bluetooth/test/fake_central.cc b/device/bluetooth/test/fake_central.cc index 8bc994f..2b11378 100644 --- a/device/bluetooth/test/fake_central.cc +++ b/device/bluetooth/test/fake_central.cc
@@ -37,13 +37,29 @@ FakePeripheral* fake_peripheral = static_cast<FakePeripheral*>(device_iter->second.get()); fake_peripheral->SetName(name); - fake_peripheral->SetGattConnected(true); + fake_peripheral->SetSystemConnected(true); fake_peripheral->SetServiceUUIDs(device::BluetoothDevice::UUIDSet( known_service_uuids.begin(), known_service_uuids.end())); std::move(callback).Run(); } +void FakeCentral::SetNextGATTConnectionResponse( + const std::string& address, + uint16_t code, + SetNextGATTConnectionResponseCallback callback) { + auto device_iter = devices_.find(address); + if (device_iter == devices_.end()) { + std::move(callback).Run(false); + return; + } + + FakePeripheral* fake_peripheral = + static_cast<FakePeripheral*>(device_iter->second.get()); + fake_peripheral->SetNextGATTConnectionResponse(code); + std::move(callback).Run(true); +} + std::string FakeCentral::GetAddress() const { NOTREACHED(); return std::string();
diff --git a/device/bluetooth/test/fake_central.h b/device/bluetooth/test/fake_central.h index 93fbd93..4b096eca 100644 --- a/device/bluetooth/test/fake_central.h +++ b/device/bluetooth/test/fake_central.h
@@ -29,6 +29,10 @@ const std::string& name, const std::vector<device::BluetoothUUID>& known_service_uuids, SimulatePreconnectedPeripheralCallback callback) override; + void SetNextGATTConnectionResponse( + const std::string& address, + uint16_t code, + SetNextGATTConnectionResponseCallback) override; // BluetoothAdapter overrides: std::string GetAddress() const override;
diff --git a/device/bluetooth/test/fake_peripheral.cc b/device/bluetooth/test/fake_peripheral.cc index acf93c73..a8524e2 100644 --- a/device/bluetooth/test/fake_peripheral.cc +++ b/device/bluetooth/test/fake_peripheral.cc
@@ -4,13 +4,17 @@ #include "device/bluetooth/test/fake_peripheral.h" +#include "base/memory/weak_ptr.h" + namespace bluetooth { FakePeripheral::FakePeripheral(FakeCentral* fake_central, const std::string& address) : device::BluetoothDevice(fake_central), address_(address), - gatt_connected_(false) {} + system_connected_(false), + gatt_connected_(false), + weak_ptr_factory_(this) {} FakePeripheral::~FakePeripheral() {} @@ -18,14 +22,20 @@ name_ = std::move(name); } -void FakePeripheral::SetGattConnected(bool connected) { - gatt_connected_ = connected; +void FakePeripheral::SetSystemConnected(bool connected) { + system_connected_ = connected; } void FakePeripheral::SetServiceUUIDs(UUIDSet service_uuids) { service_uuids_ = std::move(service_uuids); } +void FakePeripheral::SetNextGATTConnectionResponse(uint16_t code) { + DCHECK(!next_connection_response_); + DCHECK(create_gatt_connection_error_callbacks_.empty()); + next_connection_response_ = code; +} + uint32_t FakePeripheral::GetBluetoothClass() const { NOTREACHED(); return 0; @@ -92,7 +102,10 @@ } bool FakePeripheral::IsGattConnected() const { - return gatt_connected_; + // TODO(crbug.com/728870): Return gatt_connected_ only once system connected + // peripherals are supported and Web Bluetooth uses them. See issue for more + // details. + return system_connected_ || gatt_connected_; } bool FakePeripheral::IsConnectable() const { @@ -184,11 +197,43 @@ NOTREACHED(); } +void FakePeripheral::CreateGattConnection( + const GattConnectionCallback& callback, + const ConnectErrorCallback& error_callback) { + create_gatt_connection_success_callbacks_.push_back(callback); + create_gatt_connection_error_callbacks_.push_back(error_callback); + + // TODO(crbug.com/728870): Stop overriding CreateGattConnection once + // IsGattConnected() is fixed. See issue for more details. + if (gatt_connected_) + return DidConnectGatt(); + + CreateGattConnectionImpl(); +} + void FakePeripheral::CreateGattConnectionImpl() { - NOTREACHED(); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FakePeripheral::DispatchConnectionResponse, + weak_ptr_factory_.GetWeakPtr())); +} + +void FakePeripheral::DispatchConnectionResponse() { + DCHECK(next_connection_response_); + + uint16_t code = next_connection_response_.value(); + next_connection_response_.reset(); + + if (code == mojom::kHCISuccess) { + gatt_connected_ = true; + DidConnectGatt(); + } else if (code == mojom::kHCIConnectionTimeout) { + DidFailToConnectGatt(ERROR_FAILED); + } else { + DidFailToConnectGatt(ERROR_UNKNOWN); + } } void FakePeripheral::DisconnectGatt() { - NOTREACHED(); } + } // namespace bluetooth
diff --git a/device/bluetooth/test/fake_peripheral.h b/device/bluetooth/test/fake_peripheral.h index 8e6222234..b105c4f1 100644 --- a/device/bluetooth/test/fake_peripheral.h +++ b/device/bluetooth/test/fake_peripheral.h
@@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/optional.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/test/fake_central.h" @@ -24,13 +25,20 @@ // Changes the name of the device. void SetName(base::Optional<std::string> name); - // Set it to indicate if the Peripheral is connected or not. - void SetGattConnected(bool gatt_connected); + // Set it to indicate if the system has connected to the Peripheral outside of + // the Bluetooth interface e.g. the user connected to the device through + // system settings. + void SetSystemConnected(bool gatt_connected); // Updates the peripheral's UUIDs that are returned by // BluetoothDevice::GetUUIDs(). void SetServiceUUIDs(UUIDSet service_uuids); + // If |code| is kHCISuccess calls a pending success callback for + // CreateGattConnection. Otherwise calls a pending error callback + // with the ConnectErrorCode corresponding to |code|. + void SetNextGATTConnectionResponse(uint16_t code); + // BluetoothDevice overrides: uint32_t GetBluetoothClass() const override; #if defined(OS_CHROMEOS) || defined(OS_LINUX) @@ -78,16 +86,31 @@ const device::BluetoothUUID& uuid, const ConnectToServiceCallback& callback, const ConnectToServiceErrorCallback& error_callback) override; + void CreateGattConnection( + const GattConnectionCallback& callback, + const ConnectErrorCallback& error_callback) override; protected: void CreateGattConnectionImpl() override; void DisconnectGatt() override; private: + void DispatchConnectionResponse(); + const std::string address_; base::Optional<std::string> name_; - bool gatt_connected_; UUIDSet service_uuids_; + // True when the system has connected to the device outside of the Bluetooth + // interface e.g. the user connected to the device through system settings. + bool system_connected_; + // True when this Bluetooth interface is connected to the device. + bool gatt_connected_; + + // Used to decide which callback should be called when + // CreateGattConnection is called. + base::Optional<uint16_t> next_connection_response_; + + base::WeakPtrFactory<FakePeripheral> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(FakePeripheral); };
diff --git a/google_apis/drive/drive_api_requests.cc b/google_apis/drive/drive_api_requests.cc index 0c3c3e1..e9799c6 100644 --- a/google_apis/drive/drive_api_requests.cc +++ b/google_apis/drive/drive_api_requests.cc
@@ -557,20 +557,21 @@ //============================= FilesListRequest ============================= -FilesListRequest::FilesListRequest( - RequestSender* sender, - const DriveApiUrlGenerator& url_generator, - const FileListCallback& callback) +FilesListRequest::FilesListRequest(RequestSender* sender, + const DriveApiUrlGenerator& url_generator, + const FileListCallback& callback) : DriveApiDataRequest<FileList>(sender, callback), url_generator_(url_generator), - max_results_(100) { + max_results_(100), + corpora_(FilesListCorpora::DEFAULT) { DCHECK(!callback.is_null()); } FilesListRequest::~FilesListRequest() {} GURL FilesListRequest::GetURLInternal() const { - return url_generator_.GetFilesListUrl(max_results_, page_token_, q_); + return url_generator_.GetFilesListUrl(max_results_, page_token_, corpora_, + team_drive_id_, q_); } //======================== FilesListNextPageRequest =========================
diff --git a/google_apis/drive/drive_api_requests.h b/google_apis/drive/drive_api_requests.h index 3649291..4cb9d6b 100644 --- a/google_apis/drive/drive_api_requests.h +++ b/google_apis/drive/drive_api_requests.h
@@ -532,6 +532,14 @@ page_token_ = page_token; } + FilesListCorpora corpora() const { return corpora_; } + void set_corpora(FilesListCorpora corpora) { corpora_ = corpora; } + + const std::string& team_drive_id() const { return team_drive_id_; } + void set_team_drive_id(const std::string& team_drive_id) { + team_drive_id_ = team_drive_id; + } + const std::string& q() const { return q_; } void set_q(const std::string& q) { q_ = q; } @@ -543,6 +551,8 @@ const DriveApiUrlGenerator url_generator_; int max_results_; std::string page_token_; + FilesListCorpora corpora_; + std::string team_drive_id_; std::string q_; DISALLOW_COPY_AND_ASSIGN(FilesListRequest);
diff --git a/google_apis/drive/drive_api_url_generator.cc b/google_apis/drive/drive_api_url_generator.cc index e79bf0de..8daf59e 100644 --- a/google_apis/drive/drive_api_url_generator.cc +++ b/google_apis/drive/drive_api_url_generator.cc
@@ -42,6 +42,11 @@ const char kIncludeTeamDriveItems[] = "includeTeamDriveItems"; const char kSupportsTeamDrives[] = "supportsTeamDrives"; +const char kCorpora[] = "corpora"; +const char kCorporaAllTeamDrives[] = "default,allTeamDrives"; +const char kCorporaDefault[] = "default"; +const char kCorporaTeamDrive[] = "teamDrive"; +const char kTeamDriveId[] = "teamDriveId"; // apps.delete and file.authorize API is exposed through a special endpoint // v2internal that is accessible only by the official API key for Chrome. @@ -59,6 +64,19 @@ return net::AppendOrReplaceQueryParameter(url, "uploadType", "multipart"); } +const char* GetCorporaString(FilesListCorpora corpora) { + switch (corpora) { + case FilesListCorpora::DEFAULT: + return kCorporaDefault; + case FilesListCorpora::TEAM_DRIVE: + return kCorporaTeamDrive; + case FilesListCorpora::ALL_TEAM_DRIVES: + return kCorporaAllTeamDrives; + } + NOTREACHED(); + return kCorporaDefault; +} + } // namespace DriveApiUrlGenerator::DriveApiUrlGenerator( @@ -185,12 +203,21 @@ GURL DriveApiUrlGenerator::GetFilesListUrl(int max_results, const std::string& page_token, + FilesListCorpora corpora, + const std::string& team_drive_id, const std::string& q) const { GURL url = base_url_.Resolve(kDriveV2FilesUrl); if (enable_team_drives_) { url = net::AppendOrReplaceQueryParameter(url, kSupportsTeamDrives, "true"); - url = net::AppendOrReplaceQueryParameter(url, kIncludeTeamDriveItems, - "true"); + if (corpora != FilesListCorpora::DEFAULT) { + url = net::AppendOrReplaceQueryParameter(url, kIncludeTeamDriveItems, + "true"); + } + url = net::AppendOrReplaceQueryParameter(url, kCorpora, + GetCorporaString(corpora)); + if (!team_drive_id.empty()) + url = + net::AppendOrReplaceQueryParameter(url, kTeamDriveId, team_drive_id); } // maxResults is 100 by default. if (max_results != 100) { @@ -238,7 +265,7 @@ "true"); if (!team_drive_id.empty()) { url = - net::AppendOrReplaceQueryParameter(url, "teamDriveId", team_drive_id); + net::AppendOrReplaceQueryParameter(url, kTeamDriveId, team_drive_id); } } // includeDeleted is "true" by default.
diff --git a/google_apis/drive/drive_api_url_generator.h b/google_apis/drive/drive_api_url_generator.h index 08991274..9e6efc8 100644 --- a/google_apis/drive/drive_api_url_generator.h +++ b/google_apis/drive/drive_api_url_generator.h
@@ -15,6 +15,17 @@ namespace google_apis { +// This enum class is used to express a corpora parameter configuration for +// Files:list. +enum class FilesListCorpora { + // 'default': The user's subscribed items. + DEFAULT, + // 'teamDrives': A Team Drive. + TEAM_DRIVE, + // 'default,allTeamDrives': All Team Drives and the user's subscribed items. + ALL_TEAM_DRIVES +}; + // This class is used to generate URLs for communicating with drive api // servers for production, and a local server for testing. class DriveApiUrlGenerator { @@ -68,6 +79,8 @@ // Returns a URL to fetch file list. GURL GetFilesListUrl(int max_results, const std::string& page_token, + FilesListCorpora corpora, + const std::string& team_drive_id, const std::string& q) const; // Returns a URL to delete a resource with the given |file_id|.
diff --git a/google_apis/drive/drive_api_url_generator_unittest.cc b/google_apis/drive/drive_api_url_generator_unittest.cc index 43bc452..70be39b 100644 --- a/google_apis/drive/drive_api_url_generator_unittest.cc +++ b/google_apis/drive/drive_api_url_generator_unittest.cc
@@ -204,24 +204,39 @@ const std::string kV2FilesUrlPrefix = "https://www.example.com/drive/v2/files"; const std::string kV2FilesUrlPrefixWithTeamDrives = - "https://www.example.com/drive/v2/files?" - "supportsTeamDrives=true&includeTeamDriveItems=true"; + "https://www.example.com/drive/v2/files?supportsTeamDrives=true&" + "includeTeamDriveItems=true&corpora=default%2CallTeamDrives"; for (size_t i = 0; i < arraysize(kTestPatterns); ++i) { EXPECT_EQ(kV2FilesUrlPrefix + (kTestPatterns[i].expected_query.empty() ? "" : "?") + kTestPatterns[i].expected_query, - url_generator_.GetFilesListUrl(kTestPatterns[i].max_results, - kTestPatterns[i].page_token, - kTestPatterns[i].q).spec()); + url_generator_ + .GetFilesListUrl(kTestPatterns[i].max_results, + kTestPatterns[i].page_token, + FilesListCorpora::DEFAULT, std::string(), + kTestPatterns[i].q) + .spec()); EXPECT_EQ(kV2FilesUrlPrefixWithTeamDrives + (kTestPatterns[i].expected_query.empty() ? "" : "&") + kTestPatterns[i].expected_query, - team_drives_url_generator_.GetFilesListUrl( - kTestPatterns[i].max_results, - kTestPatterns[i].page_token, - kTestPatterns[i].q).spec()); + team_drives_url_generator_ + .GetFilesListUrl(kTestPatterns[i].max_results, + kTestPatterns[i].page_token, + FilesListCorpora::ALL_TEAM_DRIVES, + std::string(), kTestPatterns[i].q) + .spec()); } + + EXPECT_EQ( + "https://www.example.com/drive/v2/files?supportsTeamDrives=true&" + "includeTeamDriveItems=true&corpora=teamDrive&" + "teamDriveId=TheTeamDriveId&q=query", + team_drives_url_generator_ + .GetFilesListUrl(100, std::string() /* page_token */, + FilesListCorpora::TEAM_DRIVE, "TheTeamDriveId", + "query") + .spec()); } TEST_F(DriveApiUrlGeneratorTest, GetFilesDeleteUrl) {
diff --git a/google_apis/drive/files_list_request_runner.cc b/google_apis/drive/files_list_request_runner.cc index a7f29d6ea..3dde3d6c 100644 --- a/google_apis/drive/files_list_request_runner.cc +++ b/google_apis/drive/files_list_request_runner.cc
@@ -29,6 +29,8 @@ CancelCallback FilesListRequestRunner::CreateAndStartWithSizeBackoff( int max_results, + FilesListCorpora corpora, + const std::string& team_drive_id, const std::string& q, const std::string& fields, const FileListCallback& callback) { @@ -39,8 +41,9 @@ base::MakeUnique<drive::FilesListRequest>( request_sender_, url_generator_, base::Bind(&FilesListRequestRunner::OnCompleted, - weak_ptr_factory_.GetWeakPtr(), max_results, q, fields, - callback, base::Owned(cancel_callback))); + weak_ptr_factory_.GetWeakPtr(), max_results, corpora, + team_drive_id, q, fields, callback, + base::Owned(cancel_callback))); request->set_max_results(max_results); request->set_q(q); request->set_fields(fields); @@ -61,6 +64,8 @@ } void FilesListRequestRunner::OnCompleted(int max_results, + FilesListCorpora corpora, + const std::string& team_drive_id, const std::string& q, const std::string& fields, const FileListCallback& callback, @@ -74,7 +79,8 @@ "Drive.FilesListRequestRunner.ApiErrorCode", error); if (error == google_apis::DRIVE_RESPONSE_TOO_LARGE && max_results > 1) { - CreateAndStartWithSizeBackoff(max_results / 2, q, fields, callback); + CreateAndStartWithSizeBackoff(max_results / 2, corpora, team_drive_id, q, + fields, callback); return; }
diff --git a/google_apis/drive/files_list_request_runner.h b/google_apis/drive/files_list_request_runner.h index 788eb4d..a4993ceb 100644 --- a/google_apis/drive/files_list_request_runner.h +++ b/google_apis/drive/files_list_request_runner.h
@@ -31,6 +31,8 @@ // retry in case of DRIVE_RESPONSE_TOO_LARGE error code. CancelCallback CreateAndStartWithSizeBackoff( int max_results, + FilesListCorpora corpora, + const std::string& team_drive_id, const std::string& q, const std::string& fields, const FileListCallback& callback); @@ -49,6 +51,8 @@ // error. In case of DRIVE_RESPONSE_TOO_LARGE it will retry the request with // half of the requests. void OnCompleted(int max_results, + FilesListCorpora corpora, + const std::string& team_drive_id, const std::string& q, const std::string& fields, const FileListCallback& callback,
diff --git a/google_apis/drive/files_list_request_runner_unittest.cc b/google_apis/drive/files_list_request_runner_unittest.cc index 89e7f3a..926770e 100644 --- a/google_apis/drive/files_list_request_runner_unittest.cc +++ b/google_apis/drive/files_list_request_runner_unittest.cc
@@ -139,7 +139,7 @@ TEST_F(FilesListRequestRunnerTest, Success_NoBackoff) { SetFakeServerResponse(net::HTTP_OK, kSuccessResource); runner_->CreateAndStartWithSizeBackoff( - kMaxResults, kQuery, kFields, + kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields, base::Bind(&FilesListRequestRunnerTest::OnCompleted, base::Unretained(this))); @@ -161,7 +161,7 @@ SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR, kResponseTooLargeErrorResource); runner_->CreateAndStartWithSizeBackoff( - kMaxResults, kQuery, kFields, + kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields, base::Bind(&FilesListRequestRunnerTest::OnCompleted, base::Unretained(this))); { @@ -199,7 +199,7 @@ SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR, kResponseTooLargeErrorResource); runner_->CreateAndStartWithSizeBackoff( - kMaxResults, kQuery, kFields, + kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields, base::Bind(&FilesListRequestRunnerTest::OnCompleted, base::Unretained(this))); { @@ -255,7 +255,7 @@ SetFakeServerResponse(net::HTTP_INTERNAL_SERVER_ERROR, kQuotaExceededErrorResource); runner_->CreateAndStartWithSizeBackoff( - kMaxResults, kQuery, kFields, + kMaxResults, FilesListCorpora::DEFAULT, std::string(), kQuery, kFields, base::Bind(&FilesListRequestRunnerTest::OnCompleted, base::Unretained(this)));
diff --git a/services/preferences/README.md b/services/preferences/README.md new file mode 100644 index 0000000..7831ca2 --- /dev/null +++ b/services/preferences/README.md
@@ -0,0 +1,82 @@ +# Preference Service User Guide + +[TOC] + +## What is the Preference Service? + +Preferences, also known as "prefs", are key-value pairs stored by +Chrome. Examples include the settings in chrome://settings, all per-extension +metadata, the list of plugins and so on. Individual prefs are keyed by a string +and have a type. E.g., the "browser.enable_spellchecking" pref stores a boolean +indicating whether spell-checking is enabled. + +The prefs service persists prefs to disk and communicates updates to them +between services, including Chrome itself. There's one service instance per +profile and prefs are persisted on a pre-profile basis. + +## Using the service + +The service is used through a client library that offers clients fast and +synchronous access to prefs. To connect to the pref service and start reading +and writing prefs simply use the `ConnectToPrefService` factory function: + +``` cpp +#include "services/preferences/public/cpp/pref_service_factory.h" + +class MyService : public service_manager::Service { + void OnStart() { + auto* connector = context()->connector(); + auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>(); + // Register any preferences you intend to use in |pref_registry|. + prefs::ConnectToPrefService( + connector, std::move(pref_registry), {}, + base::Bind(&MyService::OnPrefServiceConnected, base::Unretained(this))); + } + + void OnPrefServiceConnected(std::unique_ptr<::PrefService> pref_service) { + // Use |pref_service|. + } +}; +``` + +The returned `PrefService` class predates the Pref Service and its behavior +hasn't changed (i.e. all existing documentation still applies). + +## Semantics + +Updates made on the `PrefService` object are reflected immediately in the +originating service and eventually in all other services. In other words, +updates are eventually consistent. + +## Registering your preferences + +Every pref should be owned by one service. The owning service provides the type +and default value for that pref. Owned prefs can be registered as public, +meaning other services can read and/or write them, or private (the default). Services +that want to access a pref not owned by them must still register those prefs as +"foreign" prefs. Registration happens through the `PrefRegistry` passed to +`ConnectToPrefService`. For example: + +**`//services/my_service/my_service.cc`** +``` cpp +void MyService::OnStart() { + auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>(); + pref_registry->RegisterIntegerPref(kKey, kInitialValue, PrefRegistry::PUBLIC); + prefs::ConnectToPrefService(...); +} +``` + +**`//services/other_service/other_service.cc`** +``` cpp +void OtherService::OnStart() { + auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>(); + pref_registry->RegisterForeignPref(kKey); + prefs::ConnectToPrefService(...); +} +``` + +## Design + +The design doc is here: + +https://docs.google.com/document/d/1JU8QUWxMEXWMqgkvFUumKSxr7Z-nfq0YvreSJTkMVmU/edit?usp=sharing
diff --git a/services/preferences/pref_service_factory_unittest.cc b/services/preferences/pref_service_factory_unittest.cc index 3fb34b7..02752863 100644 --- a/services/preferences/pref_service_factory_unittest.cc +++ b/services/preferences/pref_service_factory_unittest.cc
@@ -174,23 +174,12 @@ } private: - // Called when the PrefService has been initialized. - static void OnInit(const base::Closure& quit_closure, bool success) { - quit_closure.Run(); - } - // Called when the PrefService has been created. static void OnCreate(const base::Closure& quit_closure, std::unique_ptr<PrefService>* out, std::unique_ptr<PrefService> pref_service) { DCHECK(pref_service); *out = std::move(pref_service); - if ((*out)->GetInitializationStatus() == - PrefService::INITIALIZATION_STATUS_WAITING) { - (*out)->AddPrefInitObserver( - base::Bind(PrefServiceFactoryTest::OnInit, quit_closure)); - return; - } quit_closure.Run(); }
diff --git a/services/preferences/public/cpp/pref_service_factory.cc b/services/preferences/public/cpp/pref_service_factory.cc index eda3a20d..51d01de9 100644 --- a/services/preferences/public/cpp/pref_service_factory.cc +++ b/services/preferences/public/cpp/pref_service_factory.cc
@@ -57,6 +57,16 @@ return nullptr; } +void OnPrefServiceInit(std::unique_ptr<PrefService> pref_service, + ConnectCallback callback, + bool success) { + if (success) { + callback.Run(std::move(pref_service)); + } else { + callback.Run(nullptr); + } +} + void OnConnect( scoped_refptr<RefCountedInterfacePtr<mojom::PrefStoreConnector>> connector_ptr, @@ -102,9 +112,23 @@ managed_prefs.get(), supervised_user_prefs.get(), extension_prefs.get(), command_line_prefs.get(), user_pref_store.get(), recommended_prefs.get(), pref_registry->defaults().get(), pref_notifier); - callback.Run(base::MakeUnique<::PrefService>( + auto pref_service = base::MakeUnique<PrefService>( pref_notifier, pref_value_store, user_pref_store.get(), - pref_registry.get(), base::Bind(&DoNothingHandleReadError), true)); + pref_registry.get(), base::Bind(&DoNothingHandleReadError), true); + switch (pref_service->GetInitializationStatus()) { + case PrefService::INITIALIZATION_STATUS_WAITING: + pref_service->AddPrefInitObserver(base::Bind(&OnPrefServiceInit, + base::Passed(&pref_service), + base::Passed(&callback))); + break; + case PrefService::INITIALIZATION_STATUS_SUCCESS: + case PrefService::INITIALIZATION_STATUS_CREATED_NEW_PREF_STORE: + callback.Run(std::move(pref_service)); + break; + case PrefService::INITIALIZATION_STATUS_ERROR: + callback.Run(nullptr); + break; + } connector_ptr->reset(); } @@ -139,9 +163,9 @@ auto serialized_pref_registry = SerializePrefRegistry(*pref_registry); connector_ptr->get()->Connect( std::move(serialized_pref_registry), std::move(already_connected_types), - base::Bind(&OnConnect, connector_ptr, base::Passed(&pref_registry), - base::Passed(&local_layered_pref_stores), - base::Passed(&callback))); + base::BindOnce(&OnConnect, connector_ptr, std::move(pref_registry), + std::move(local_layered_pref_stores), + std::move(callback))); } } // namespace prefs
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js index fec4374..32544f0 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/invalid-service-name.js
@@ -1,12 +1,9 @@ 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gatt => { + return getHealthThermometerDevice() + .then(([device]) => { return assert_promise_rejects_with_message( - gatt.CALLS([ + device.gatt.CALLS([ getPrimaryService('wrong_name')| getPrimaryServices('wrong_name') ]),
diff --git a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js index 83580da7..e2e95c2e 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js +++ b/third_party/WebKit/LayoutTests/bluetooth/script-tests/server/no-permission-for-any-service.js
@@ -1,11 +1,8 @@ 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{name: 'Heart Rate Device'}]})) - .then(device => device.gatt.connect()) - .then(gattServer => assert_promise_rejects_with_message( - gattServer.CALLS([ + return getHealthThermometerDevice({acceptAllDevices: true}) + .then(([device]) => assert_promise_rejects_with_message( + device.gatt.CALLS([ getPrimaryService('heart_rate')| getPrimaryServices()| getPrimaryServices('heart_rate')[UUID]]), @@ -15,4 +12,3 @@ 'SecurityError'))); }, 'Request for present service without permission to access any service. ' + 'Reject with SecurityError.'); -</script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html index f0d82e1..a5fb002 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/connection-succeeds.html
@@ -2,13 +2,16 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> +<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => assert_true(gattServer.connected)); + return getDiscoveredHealthThermometerDevice() + .then(([device, fake_peripheral]) => { + return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) + .then(() => device.gatt.connect()) + .then(gatt => assert_true(gatt.connected)); + }); }, 'Device will connect'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html index 00b5c0a..60156c1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/garbage-collection-ran-during-success.html
@@ -2,16 +2,21 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> +<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('DisconnectingHealthThermometerAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['health_thermometer']}]})) - .then(device => { - device.gatt.connect(); + return getDiscoveredHealthThermometerDevice() + .then(([device, fake_peripheral]) => { + return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) + .then(() => { + // Don't return the promise and let |device| go out of scope + // so that it gets garbage collected. + device.gatt.connect(); + }); }) - .then(runGarbageCollection); + .then(runGarbageCollection) }, 'Garbage Collection ran during a connect call that succeeds. ' + 'Should not crash.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html b/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html index 1c7774f..d6d1a42 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/connect/get-same-gatt-server.html
@@ -2,16 +2,24 @@ <script src="../../../resources/testharness.js"></script> <script src="../../../resources/testharnessreport.js"></script> <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> +<script src="../../../resources/bluetooth/web-bluetooth-test.js"></script> +<script src="../../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => { - return Promise.all([device.gatt.connect(), device.gatt.connect()]) - }).then(gattServers => { - assert_equals(gattServers[0], gattServers[1]); - }); + return getDiscoveredHealthThermometerDevice() + .then(([device, fake_peripheral]) => { + return fake_peripheral + .setNextGATTConnectionResponse({code: HCI_SUCCESS}) + .then(() => device.gatt.connect()) + .then(gatt1 => { + // No second response is necessary because an ATT Bearer + // already exists from the first connection. + // See https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect + // step 5.1. + return device.gatt.connect().then(gatt2 => [gatt1, gatt2]); + }); + }) + .then(([gatt1, gatt2]) => assert_equals(gatt1, gatt2)); }, 'Multiple connects should return the same gatt object.'); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html b/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html index bbba6ddb..c6f391c 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/device-same-object.html
@@ -2,15 +2,18 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/bluetooth/bluetooth-helpers.js"></script> +<script src="../../resources/bluetooth/web-bluetooth-test.js"></script> +<script src="../../resources/mojo-helpers.js"></script> <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gattServer => { - assert_equals(gattServer.device, gattServer.device); + return getDiscoveredHealthThermometerDevice() + .then(([device, fake_peripheral]) => { + return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) + .then(() => device.gatt.connect()); + }) + .then(gatt => { + assert_equals(gatt.device, gatt.device); }); }, "[SameObject] test for BluetoothRemoteGATTServer's device."); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html index aaa69c8..591757d1 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-invalid-service-name.html
@@ -8,13 +8,10 @@ <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gatt => { + return getHealthThermometerDevice() + .then(([device]) => { return assert_promise_rejects_with_message( - gatt.getPrimaryService('wrong_name'), + device.gatt.getPrimaryService('wrong_name'), new DOMException( 'Failed to execute \'getPrimaryService\' on ' + '\'BluetoothRemoteGATTServer\': Invalid Service name: ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html index c04a98f..d02d25d 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html
@@ -8,18 +8,14 @@ <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{name: 'Heart Rate Device'}]})) - .then(device => device.gatt.connect()) - .then(gattServer => assert_promise_rejects_with_message( - gattServer.getPrimaryService('heart_rate'), + return getHealthThermometerDevice({acceptAllDevices: true}) + .then(([device]) => assert_promise_rejects_with_message( + device.gatt.getPrimaryService('heart_rate'), new DOMException('Origin is not allowed to access any service. Tip: ' + 'Add the service UUID to \'optionalServices\' in ' + 'requestDevice() options. https://goo.gl/HxfxSQ', 'SecurityError'))); }, 'Request for present service without permission to access any service. ' + 'Reject with SecurityError.'); -</script> </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html index 66c9a37..f8d010b 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.html
@@ -8,13 +8,10 @@ <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gatt => { + return getHealthThermometerDevice() + .then(([device]) => { return assert_promise_rejects_with_message( - gatt.getPrimaryServices('wrong_name'), + device.gatt.getPrimaryServices('wrong_name'), new DOMException( 'Failed to execute \'getPrimaryServices\' on ' + '\'BluetoothRemoteGATTServer\': Invalid Service name: ' +
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html index 12b0ef9..c80c983 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html
@@ -8,18 +8,14 @@ <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{name: 'Heart Rate Device'}]})) - .then(device => device.gatt.connect()) - .then(gattServer => assert_promise_rejects_with_message( - gattServer.getPrimaryServices('heart_rate'), + return getHealthThermometerDevice({acceptAllDevices: true}) + .then(([device]) => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices('heart_rate'), new DOMException('Origin is not allowed to access any service. Tip: ' + 'Add the service UUID to \'optionalServices\' in ' + 'requestDevice() options. https://goo.gl/HxfxSQ', 'SecurityError'))); }, 'Request for present service without permission to access any service. ' + 'Reject with SecurityError.'); -</script> </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html index 0b19a37..c771e477 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html +++ b/third_party/WebKit/LayoutTests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html
@@ -8,18 +8,14 @@ <script> 'use strict'; promise_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithKeyDown({ - filters: [{name: 'Heart Rate Device'}]})) - .then(device => device.gatt.connect()) - .then(gattServer => assert_promise_rejects_with_message( - gattServer.getPrimaryServices(), + return getHealthThermometerDevice({acceptAllDevices: true}) + .then(([device]) => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(), new DOMException('Origin is not allowed to access any service. Tip: ' + 'Add the service UUID to \'optionalServices\' in ' + 'requestDevice() options. https://goo.gl/HxfxSQ', 'SecurityError'))); }, 'Request for present service without permission to access any service. ' + 'Reject with SecurityError.'); -</script> </script>
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js index 862950d..aae8a9b 100644 --- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -1,5 +1,11 @@ 'use strict'; +// HCI Error Codes. Used for simulateGATT[Dis]ConnectionResponse. +// For a complete list of possible error codes see +// BT 4.2 Vol 2 Part D 1.3 List Of Error Codes. +const HCI_SUCCESS = 0x0000; +const HCI_CONNECTION_TIMEOUT = 0x0008; + // Bluetooth UUID constants: // Services: var blocklist_test_service_uuid = "611c954a-263b-4f4a-aab6-01ddb953f985"; @@ -416,6 +422,8 @@ }]; } +// Simulates a pre-connected device with |address|, |name| and +// |knownServiceUUIDs|. function setUpPreconnectedDevice({ address = '00:00:00:00:00:00', name = 'LE Device', knownServiceUUIDs = []}) { return navigator.bluetooth.test.simulateCentral({state: 'powered-on'}) @@ -426,6 +434,8 @@ })); } +// Returns an array containing two FakePeripherals corresponding +// to the simulated devices. function setUpHealthThermometerAndHeartRateDevices() { return navigator.bluetooth.test.simulateCentral({state: 'powered-on'}) .then(fake_central => Promise.all([ @@ -440,3 +450,35 @@ knownServiceUUIDs: ['generic_access', 'heart_rate'], })])); } + +// Returns a BluetoothDevice discovered using |options| and its +// corresponding FakePeripheral. +// The simulated device is called 'Health Thermometer' it has two known service +// UUIDs: 'generic_access' and 'health_thermometer'. The device has been +// connected to and its services have been discovered. +// TODO(crbug.com/719816): Add services, characteristics and descriptors, +// and discover all the attributes. +function getHealthThermometerDevice(options) { + return getDiscoveredHealthThermometerDevice(options) + .then(([device, fake_peripheral]) => { + return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}) + .then(() => device.gatt.connect()) + .then(gatt => [gatt.device, fake_peripheral]); + }); +} + +// Similar to getHealthThermometerDevice() except the device +// is not connected and thus its services have not been +// discovered. +function getDiscoveredHealthThermometerDevice( + options = {filters: [{services: ['health_thermometer']}]}) { + return setUpPreconnectedDevice({ + address: '09:09:09:09:09:09', + name: 'Health Thermometer', + knownServiceUUIDs: ['generic_access', 'health_thermometer'], + }) + .then(fake_peripheral => { + return requestDeviceWithKeyDown(options) + .then(device => [device, fake_peripheral]); + }); +}
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js index 450c27d..1f5e29de 100644 --- a/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/web-bluetooth-test.js
@@ -139,7 +139,7 @@ let peripheral = this.peripherals_.get(address); if (peripheral === undefined) { - peripheral = new FakePeripheral(address, this); + peripheral = new FakePeripheral(address, this.fake_central_ptr_); this.peripherals_.set(address, peripheral); } @@ -148,9 +148,22 @@ } class FakePeripheral { - constructor(address, fake_central) { + constructor(address, fake_central_ptr) { this.address = address; - this.fake_central_ = fake_central; + this.fake_central_ptr_ = fake_central_ptr; + } + + // Sets the next GATT Connection request response to |code|. |code| could be + // an HCI Error Code from BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a + // number outside that range returned by specific platforms e.g. Android + // returns 0x101 to signal a GATT failure + // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE + async setNextGATTConnectionResponse({code}) { + let {success} = + await this.fake_central_ptr_.setNextGATTConnectionResponse( + this.address, code); + + if (success !== true) throw 'Cannot set next response.'; } }
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp index 9cba88ca..01479869 100644 --- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
@@ -24,54 +24,34 @@ namespace blink { -// Retrieves the custom elements constructor -> name map, creating it -// if necessary. -static v8::Local<v8::Map> EnsureCustomElementRegistryMap( - ScriptState* script_state, - CustomElementRegistry* registry) { - CHECK(script_state->World().IsMainWorld()); - v8::Isolate* isolate = script_state->GetIsolate(); - - V8PrivateProperty::Symbol symbol = - V8PrivateProperty::GetCustomElementRegistryMap(isolate); - v8::Local<v8::Object> wrapper = ToV8(registry, script_state).As<v8::Object>(); - v8::Local<v8::Value> map = symbol.GetOrUndefined(wrapper); - if (map->IsUndefined()) { - map = v8::Map::New(isolate); - symbol.Set(wrapper, map); - } - return map.As<v8::Map>(); -} - ScriptCustomElementDefinition* ScriptCustomElementDefinition::ForConstructor( ScriptState* script_state, CustomElementRegistry* registry, const v8::Local<v8::Value>& constructor) { - v8::Local<v8::Map> map = - EnsureCustomElementRegistryMap(script_state, registry); - v8::Local<v8::Value> id_value = - map->Get(script_state->GetContext(), constructor).ToLocalChecked(); + auto private_id = + script_state->PerContextData()->GetPrivateCustomElementDefinitionId(); + v8::Local<v8::Value> id_value; + if (!constructor.As<v8::Object>() + ->GetPrivate(script_state->GetContext(), private_id) + .ToLocal(&id_value)) + return nullptr; if (!id_value->IsUint32()) return nullptr; uint32_t id = id_value.As<v8::Uint32>()->Value(); - // This downcast is safe because only - // ScriptCustomElementDefinitions have an ID associated with a V8 - // constructor in the map; see - // ScriptCustomElementDefinition::create. This relies on three - // things: + // This downcast is safe because only ScriptCustomElementDefinitions + // have an ID associated with them. This relies on three things: // - // 1. Only ScriptCustomElementDefinition adds entries to the map. - // Audit the use of private properties in general and how the - // map is handled--it should never be leaked to script. + // 1. Only ScriptCustomElementDefinition::Create sets the private + // property on a constructor. // // 2. CustomElementRegistry adds ScriptCustomElementDefinitions - // assigned an ID to the lis tof definitions without fail. + // assigned an ID to the list of definitions without fail. // // 3. The relationship between the CustomElementRegistry and its - // map is never mixed up; this is guaranteed by the bindings - // system which provides a stable wrapper, and the map hangs - // off the wrapper. + // private property is never mixed up; this is guaranteed by the + // bindings system because the registry is associated with its + // context. // // At a meta-level, this downcast is safe because there is // currently only one implementation of CustomElementDefinition in @@ -98,12 +78,14 @@ disconnected_callback, adopted_callback, attribute_changed_callback, std::move(observed_attributes)); - // Add a constructor -> ID mapping to the registry. + // Tag the JavaScript constructor object with its ID. v8::Local<v8::Value> id_value = - v8::Integer::New(script_state->GetIsolate(), id); - v8::Local<v8::Map> map = - EnsureCustomElementRegistryMap(script_state, registry); - map->Set(script_state->GetContext(), constructor, id_value).ToLocalChecked(); + v8::Integer::NewFromUnsigned(script_state->GetIsolate(), id); + auto private_id = + script_state->PerContextData()->GetPrivateCustomElementDefinitionId(); + CHECK( + constructor->SetPrivate(script_state->GetContext(), private_id, id_value) + .ToChecked()); return definition; }
diff --git a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp index b9517bb7..7a8d0ca 100644 --- a/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/V8Initializer.cpp
@@ -76,7 +76,7 @@ int memory_usage_mb = Platform::Current()->ActualMemoryUsageMB(); DVLOG(1) << "V8 error: " << message << " (" << location << "). Current memory usage: " << memory_usage_mb << " MB"; - IMMEDIATE_CRASH(); + LOG(FATAL); } static void ReportOOMErrorInMainThread(const char* location, bool is_js_heap) { @@ -485,7 +485,7 @@ const char* message) { // FIXME: We temporarily deal with V8 internal error situations such as // out-of-memory by crashing the worker. - IMMEDIATE_CRASH(); + LOG(FATAL); } static void MessageHandlerInWorker(v8::Local<v8::Message> message,
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h index c1eea48..e558f76 100644 --- a/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h +++ b/third_party/WebKit/Source/core/css/resolver/StyleResolverState.h
@@ -202,8 +202,10 @@ font_builder_.DidChangeWritingMode(); } void SetTextOrientation(ETextOrientation text_orientation) { - if (style_->SetTextOrientation(text_orientation)) + if (style_->GetTextOrientation() != text_orientation) { + style_->SetTextOrientation(text_orientation); font_builder_.DidChangeTextOrientation(); + } } void SetHasDirAutoAttribute(bool value) { has_dir_auto_attribute_ = value; }
diff --git a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp index b2387b53..05214d0 100644 --- a/third_party/WebKit/Source/core/dom/DOMTokenList.cpp +++ b/third_party/WebKit/Source/core/dom/DOMTokenList.cpp
@@ -93,7 +93,7 @@ // https://dom.spec.whatwg.org/#dom-domtokenlist-contains bool DOMTokenList::contains(const AtomicString& token) const { - return tokens_.Contains(token); + return token_set_.Contains(token); } void DOMTokenList::Add(const AtomicString& token) { @@ -194,22 +194,22 @@ bool found_old_token = false; bool found_new_token = false; bool did_update = false; - for (size_t i = 0; i < tokens_.size(); ++i) { - const AtomicString& existing_token = tokens_[i]; + for (size_t i = 0; i < token_set_.size(); ++i) { + const AtomicString& existing_token = token_set_[i]; if (found_old_token) { if (existing_token == new_token) { - tokens_.Remove(i); + token_set_.Remove(i); break; } } else if (found_new_token) { if (existing_token == token) { - tokens_.Remove(i); + token_set_.Remove(i); did_update = true; break; } } else if (existing_token == token) { found_old_token = true; - tokens_.ReplaceAt(i, new_token); + token_set_.ReplaceAt(i, new_token); did_update = true; } else if (existing_token == new_token) { found_new_token = true; @@ -222,7 +222,7 @@ if (!did_update) return; - UpdateWithTokenSet(tokens_); + UpdateWithTokenSet(token_set_); } bool DOMTokenList::supports(const AtomicString& token, @@ -234,25 +234,26 @@ void DOMTokenList::AddTokens(const Vector<String>& tokens) { // 2. For each token in tokens, append token to context object’s token set. for (const auto& token : tokens) - tokens_.Add(AtomicString(token)); + token_set_.Add(AtomicString(token)); // 3. Run the update steps. - UpdateWithTokenSet(tokens_); + UpdateWithTokenSet(token_set_); } // https://dom.spec.whatwg.org/#dom-domtokenlist-remove void DOMTokenList::RemoveTokens(const Vector<String>& tokens) { // 2. For each token in tokens, remove token from context object’s token set. for (const auto& token : tokens) - tokens_.Remove(AtomicString(token)); + token_set_.Remove(AtomicString(token)); // 3. Run the update steps. - UpdateWithTokenSet(tokens_); + UpdateWithTokenSet(token_set_); } // https://dom.spec.whatwg.org/#concept-ordered-set-serializer // The ordered set serializer takes a set and returns the concatenation of the // strings in set, separated from each other by U+0020, if set is non-empty, and // the empty string otherwise. -AtomicString DOMTokenList::SerializeSet(const SpaceSplitString& token_set) { +AtomicString DOMTokenList::SerializeTokenSet( + const SpaceSplitString& token_set) { size_t size = token_set.size(); if (size == 0) return g_empty_atom; @@ -270,7 +271,7 @@ // https://dom.spec.whatwg.org/#concept-dtl-update void DOMTokenList::UpdateWithTokenSet(const SpaceSplitString& token_set) { AutoReset<bool> updating(&is_in_update_step_, true); - setValue(SerializeSet(token_set)); + setValue(SerializeTokenSet(token_set)); } void DOMTokenList::setValue(const AtomicString& value) { @@ -283,13 +284,13 @@ if (is_in_update_step_) return; if (old_value != new_value) - tokens_.Set(new_value); + token_set_.Set(new_value); } const AtomicString DOMTokenList::item(unsigned index) const { if (index >= length()) return AtomicString(); - return tokens_[index]; + return token_set_[index]; } } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/DOMTokenList.h b/third_party/WebKit/Source/core/dom/DOMTokenList.h index 5f2db853..d0fd3d93 100644 --- a/third_party/WebKit/Source/core/dom/DOMTokenList.h +++ b/third_party/WebKit/Source/core/dom/DOMTokenList.h
@@ -50,7 +50,7 @@ virtual ~DOMTokenList() {} DECLARE_VIRTUAL_TRACE(); - unsigned length() const { return tokens_.size(); } + unsigned length() const { return token_set_.size(); } const AtomicString item(unsigned index) const; bool contains(const AtomicString&) const; void add(const Vector<String>&, ExceptionState&); @@ -70,7 +70,7 @@ void DidUpdateAttributeValue(const AtomicString& old_value, const AtomicString& new_value); - const SpaceSplitString& Tokens() const { return tokens_; } + const SpaceSplitString& TokenSet() const { return token_set_; } // Add() and Remove() have DCHECK for syntax of the specified token. void Add(const AtomicString&); void Remove(const AtomicString&); @@ -86,9 +86,9 @@ void AddTokens(const Vector<String>&); void RemoveTokens(const Vector<String>&); void UpdateWithTokenSet(const SpaceSplitString&); - static AtomicString SerializeSet(const SpaceSplitString&); + static AtomicString SerializeTokenSet(const SpaceSplitString&); - SpaceSplitString tokens_; + SpaceSplitString token_set_; AtomicString value_; const Member<Element> element_; const QualifiedName attribute_name_;
diff --git a/third_party/WebKit/Source/core/dom/Modulator.h b/third_party/WebKit/Source/core/dom/Modulator.h index 9c53af3a..8d9f266 100644 --- a/third_party/WebKit/Source/core/dom/Modulator.h +++ b/third_party/WebKit/Source/core/dom/Modulator.h
@@ -111,7 +111,7 @@ virtual ScriptValue InstantiateModule(ScriptModule) = 0; - virtual ScriptValue GetInstantiationError(const ModuleScript*) = 0; + virtual ScriptValue GetError(const ModuleScript*) = 0; virtual Vector<String> ModuleRequestsFromScriptModule(ScriptModule) = 0;
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp index 878ea9f5..9a132542 100644 --- a/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp +++ b/third_party/WebKit/Source/core/dom/ModulatorImpl.cpp
@@ -149,12 +149,10 @@ return script_module.Instantiate(script_state_.Get()); } -ScriptValue ModulatorImpl::GetInstantiationError( - const ModuleScript* module_script) { +ScriptValue ModulatorImpl::GetError(const ModuleScript* module_script) { ScriptState::Scope scope(script_state_.Get()); - return ScriptValue(script_state_.Get(), - module_script->CreateInstantiationErrorInternal( - script_state_->GetIsolate())); + return ScriptValue(script_state_.Get(), module_script->CreateErrorInternal( + script_state_->GetIsolate())); } Vector<String> ModulatorImpl::ModuleRequestsFromScriptModule( @@ -188,13 +186,11 @@ // 3. "If s's instantiation state is "errored", then report the exception // given by s's instantiation error for s and abort these steps." - ModuleInstantiationState instantiationState = - module_script->InstantiationState(); + ModuleInstantiationState instantiationState = module_script->State(); if (instantiationState == ModuleInstantiationState::kErrored) { v8::Isolate* isolate = script_state_->GetIsolate(); ScriptModule::ReportException( - script_state_.Get(), - module_script->CreateInstantiationErrorInternal(isolate), + script_state_.Get(), module_script->CreateErrorInternal(isolate), module_script->BaseURL().GetString(), module_script->StartPosition()); return; }
diff --git a/third_party/WebKit/Source/core/dom/ModulatorImpl.h b/third_party/WebKit/Source/core/dom/ModulatorImpl.h index e0af185..35013d1 100644 --- a/third_party/WebKit/Source/core/dom/ModulatorImpl.h +++ b/third_party/WebKit/Source/core/dom/ModulatorImpl.h
@@ -65,7 +65,7 @@ AccessControlStatus, const TextPosition&) override; ScriptValue InstantiateModule(ScriptModule) override; - ScriptValue GetInstantiationError(const ModuleScript*) override; + ScriptValue GetError(const ModuleScript*) override; Vector<String> ModuleRequestsFromScriptModule(ScriptModule) override; void ExecuteModule(const ModuleScript*) override;
diff --git a/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp index b29ebec4..1492bfc 100644 --- a/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp +++ b/third_party/WebKit/Source/core/dom/ModuleMapTest.cpp
@@ -184,7 +184,7 @@ 1); EXPECT_TRUE(client->WasNotifyFinished()); EXPECT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kUninstantiated); // Secondary request @@ -203,7 +203,7 @@ << "registerModuleScript sholudn't be called in secondary request."; EXPECT_TRUE(client2->WasNotifyFinished()); EXPECT_TRUE(client2->GetModuleScript()); - EXPECT_EQ(client2->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client2->GetModuleScript()->State(), ModuleInstantiationState::kUninstantiated); } @@ -240,11 +240,11 @@ EXPECT_TRUE(client->WasNotifyFinished()); EXPECT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kUninstantiated); EXPECT_TRUE(client2->WasNotifyFinished()); EXPECT_TRUE(client2->GetModuleScript()); - EXPECT_EQ(client2->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client2->GetModuleScript()->State(), ModuleInstantiationState::kUninstantiated); }
diff --git a/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp b/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp index f0184b1..5675e938 100644 --- a/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp +++ b/third_party/WebKit/Source/core/dom/ModulePendingScript.cpp
@@ -24,7 +24,7 @@ void ModulePendingScriptTreeClient::NotifyModuleTreeLoadFinished( ModuleScript* module_script) { - DCHECK(!(module_script && module_script->InstantiationState() == + DCHECK(!(module_script && module_script->State() == ModuleInstantiationState::kUninstantiated)); DCHECK(!finished_); finished_ = true;
diff --git a/third_party/WebKit/Source/core/dom/ModuleScript.cpp b/third_party/WebKit/Source/core/dom/ModuleScript.cpp index fd65ecc..3f1139d 100644 --- a/third_party/WebKit/Source/core/dom/ModuleScript.cpp +++ b/third_party/WebKit/Source/core/dom/ModuleScript.cpp
@@ -38,6 +38,19 @@ parser_state, credentials_mode, start_position); } +ModuleScript* ModuleScript::CreateForTest( + Modulator* modulator, + ScriptModule record, + const KURL& base_url, + const String& nonce, + ParserDisposition parser_state, + WebURLRequest::FetchCredentialsMode credentials_mode) { + String dummy_source_text = ""; + return CreateInternal(dummy_source_text, modulator, record, base_url, nonce, + parser_state, credentials_mode, + TextPosition::MinimumPosition()); +} + ModuleScript* ModuleScript::CreateInternal( const String& source_text, Modulator* modulator, @@ -67,19 +80,6 @@ return module_script; } -ModuleScript* ModuleScript::CreateForTest( - Modulator* modulator, - ScriptModule record, - const KURL& base_url, - const String& nonce, - ParserDisposition parser_state, - WebURLRequest::FetchCredentialsMode credentials_mode) { - String dummy_source_text = ""; - return CreateInternal(dummy_source_text, modulator, record, base_url, nonce, - parser_state, credentials_mode, - TextPosition::MinimumPosition()); -} - ModuleScript::ModuleScript(Modulator* settings_object, ScriptModule record, const KURL& base_url, @@ -91,7 +91,7 @@ : settings_object_(settings_object), record_(this), base_url_(base_url), - instantiation_error_(this), + error_(this), nonce_(nonce), parser_state_(parser_state), credentials_mode_(credentials_mode), @@ -118,23 +118,33 @@ return ScriptModule(isolate, record_.NewLocal(isolate)); } -void ModuleScript::SetInstantiationErrorAndClearRecord(ScriptValue error) { - // Implements Step 7.1 of: - // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure +void ModuleScript::SetErrorAndClearRecord(ScriptValue error) { + // https://html.spec.whatwg.org/multipage/webappapis.html#error-a-module-script + // Step 1. Assert: script's state is not "errored". + DCHECK_NE(state_, ModuleInstantiationState::kErrored); - // "set script's instantiation state to "errored", ..." - DCHECK_EQ(instantiation_state_, ModuleInstantiationState::kUninstantiated); - instantiation_state_ = ModuleInstantiationState::kErrored; + // Step 2. If script's module record is set, then: + if (!record_.IsEmpty()) { + // Step 2.1. Set script module record's [[HostDefined]] field to undefined. + // TODO(kouhei): Implement this step. + // if (ScriptModuleResolver* resolver = + // modulator_->GetScriptModuleResolver()) + // resolver->UnregisterModuleScript(this); + NOTIMPLEMENTED(); - // "its instantiation error to instantiationStatus.[[Value]], and ..." + // Step 2.2. Set script's module record to null. + record_.Clear(); + } + + // Step 3. Set script's state to "errored". + state_ = ModuleInstantiationState::kErrored; + + // Step 4. Set script's error to error. DCHECK(!error.IsEmpty()); { ScriptState::Scope scope(error.GetScriptState()); - instantiation_error_.Set(error.GetIsolate(), error.V8Value()); + error_.Set(error.GetIsolate(), error.V8Value()); } - - // "its module record to null." - record_.Clear(); } void ModuleScript::SetInstantiationSuccess() { @@ -142,8 +152,8 @@ // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure // "set script's instantiation state to "instantiated"." - DCHECK_EQ(instantiation_state_, ModuleInstantiationState::kUninstantiated); - instantiation_state_ = ModuleInstantiationState::kInstantiated; + DCHECK_EQ(state_, ModuleInstantiationState::kUninstantiated); + state_ = ModuleInstantiationState::kInstantiated; } DEFINE_TRACE(ModuleScript) { @@ -154,7 +164,7 @@ // TODO(mlippautz): Support TraceWrappers(const // TraceWrapperV8Reference<v8::Module>&) to remove the cast. visitor->TraceWrappers(record_.Cast<v8::Value>()); - visitor->TraceWrappers(instantiation_error_); + visitor->TraceWrappers(error_); } bool ModuleScript::IsEmpty() const {
diff --git a/third_party/WebKit/Source/core/dom/ModuleScript.h b/third_party/WebKit/Source/core/dom/ModuleScript.h index 389e1e75..b0d5081 100644 --- a/third_party/WebKit/Source/core/dom/ModuleScript.h +++ b/third_party/WebKit/Source/core/dom/ModuleScript.h
@@ -20,7 +20,7 @@ namespace blink { -// https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-instantiation-state +// https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-state enum class ModuleInstantiationState { kUninstantiated, kErrored, @@ -56,19 +56,17 @@ ScriptModule Record() const; const KURL& BaseURL() const { return base_url_; } - ModuleInstantiationState InstantiationState() const { - return instantiation_state_; - } + ModuleInstantiationState State() const { return state_; } - // Implements Step 7.1 of: - // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure - void SetInstantiationErrorAndClearRecord(ScriptValue error); + // https://html.spec.whatwg.org/multipage/webappapis.html#error-a-module-script + void SetErrorAndClearRecord(ScriptValue error); + // Implements Step 7.2 of: // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure void SetInstantiationSuccess(); - v8::Local<v8::Value> CreateInstantiationError(v8::Isolate* isolate) const { - return instantiation_error_.NewLocal(isolate); + v8::Local<v8::Value> CreateError(v8::Isolate* isolate) const { + return error_.NewLocal(isolate); } ParserDisposition ParserState() const { return parser_state_; } @@ -110,11 +108,10 @@ friend class ModulatorImpl; friend class ModuleTreeLinkerTestModulator; - // Access this func only via ModulatorImpl::GetInstantiationError(), + // Access this func only via ModulatorImpl::GetError(), // or via Modulator mocks for unit tests. - v8::Local<v8::Value> CreateInstantiationErrorInternal( - v8::Isolate* isolate) const { - return instantiation_error_.NewLocal(isolate); + v8::Local<v8::Value> CreateErrorInternal(v8::Isolate* isolate) const { + return error_.NewLocal(isolate); } // https://html.spec.whatwg.org/multipage/webappapis.html#settings-object @@ -127,18 +124,17 @@ const KURL base_url_; // https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-instantiation-state - ModuleInstantiationState instantiation_state_ = - ModuleInstantiationState::kUninstantiated; + ModuleInstantiationState state_ = ModuleInstantiationState::kUninstantiated; - // https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-instantiation-error + // https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-error // - // |instantiation_error_| is TraceWrappers()ed and kept alive via the path of + // |error_| is TraceWrappers()ed and kept alive via the path of // v8::Context -> PerContextData -> Modulator/ModulatorImpl - // -> ModuleMap -> ModuleMap::Entry -> ModuleScript -> instantiation_error_. + // -> ModuleMap -> ModuleMap::Entry -> ModuleScript -> error_. // All the classes/references on the path above should be // TraceWrapperBase/TraceWrapperMember<>/etc., // but other references to those classes can be normal Member<>. - TraceWrapperV8Reference<v8::Value> instantiation_error_; + TraceWrapperV8Reference<v8::Value> error_; // https://html.spec.whatwg.org/multipage/webappapis.html#concept-module-script-nonce const String nonce_;
diff --git a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImpl.cpp b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImpl.cpp index 4366cf0..058afd3 100644 --- a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImpl.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImpl.cpp
@@ -66,9 +66,8 @@ // Step 5. If resolved module script's instantiation state is "errored", then // throw resolved module script's instantiation error. - if (module_script->InstantiationState() == - ModuleInstantiationState::kErrored) { - ScriptValue error = modulator_->GetInstantiationError(module_script); + if (module_script->State() == ModuleInstantiationState::kErrored) { + ScriptValue error = modulator_->GetError(module_script); exception_state.RethrowV8Exception(error.V8Value()); return ScriptModule(); }
diff --git a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp index e3fdc20..749d594 100644 --- a/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp +++ b/third_party/WebKit/Source/core/dom/ScriptModuleResolverImplTest.cpp
@@ -46,11 +46,10 @@ ModuleScript* GetFetchedModuleScript(const KURL&) override; - ScriptValue GetInstantiationError(const ModuleScript* module_script) { + ScriptValue GetError(const ModuleScript* module_script) { ScriptState::Scope scope(script_state_.Get()); - return ScriptValue( - script_state_.Get(), - module_script->CreateInstantiationError(script_state_->GetIsolate())); + return ScriptValue(script_state_.Get(), + module_script->CreateError(script_state_->GetIsolate())); } RefPtr<ScriptState> script_state_; @@ -101,7 +100,7 @@ EXPECT_EQ(ModuleInstantiationState::kErrored, state); v8::Local<v8::Value> error = V8ThrowException::CreateError(scope.GetIsolate(), "hoge"); - module_script->SetInstantiationErrorAndClearRecord( + module_script->SetErrorAndClearRecord( ScriptValue(scope.GetScriptState(), error)); } return module_script;
diff --git a/third_party/WebKit/Source/core/dom/Text.cpp b/third_party/WebKit/Source/core/dom/Text.cpp index 1b9a0dad0..776feb3 100644 --- a/third_party/WebKit/Source/core/dom/Text.cpp +++ b/third_party/WebKit/Source/core/dom/Text.cpp
@@ -176,8 +176,8 @@ if (!n->IsTextNode()) continue; const String& data = ToText(n)->data(); - if (std::numeric_limits<unsigned>::max() - data.length() < result_length) - IMMEDIATE_CRASH(); + CHECK_GE(std::numeric_limits<unsigned>::max() - data.length(), + result_length); result_length += data.length(); } StringBuilder result;
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp index 1fd0e41d..d4656e6e 100644 --- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp +++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
@@ -450,8 +450,13 @@ LayoutText* layout_object, int text_start_offset, int text_end_offset) { - text_state_->EmitText(text_node, layout_object, text_start_offset, - text_end_offset); + const String& string = behavior_.EmitsOriginalText() + ? layout_object->OriginalText() + : layout_object->GetText(); + text_state_->EmitText(text_node, + text_start_offset + layout_object->TextStartOffset(), + text_end_offset + layout_object->TextStartOffset(), + string, text_start_offset, text_end_offset); ResetCollapsedWhiteSpaceFixup(); }
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp index 6971b1f..060b538 100644 --- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp +++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.cpp
@@ -28,7 +28,7 @@ #include "core/editing/iterators/TextIteratorTextState.h" #include "core/editing/iterators/TextIteratorBehavior.h" -#include "core/layout/LayoutText.h" +#include "platform/wtf/text/StringBuilder.h" namespace blink { @@ -141,15 +141,17 @@ last_character_ = c; } -// TODO(xiaochengh): Remove the dependency on LayoutText, so that the class can -// also be used by Layout NG. void TextIteratorTextState::EmitText(Node* text_node, - LayoutText* layout_object, + int position_start_offset, + int position_end_offset, + const String& string, int text_start_offset, int text_end_offset) { DCHECK(text_node); - text_ = behavior_.EmitsOriginalText() ? layout_object->OriginalText() - : layout_object->GetText(); + text_ = string; + + // TODO(xiaochengh): Hoist the conversion to TextIteratorTextNodeHandler, so + // that we can remove |behavior_| from TextIteratorTextState. if (behavior_.EmitsSpaceForNbsp()) text_.Replace(kNoBreakSpaceCharacter, kSpaceCharacter); @@ -162,8 +164,8 @@ position_node_ = text_node; position_offset_base_node_ = nullptr; - position_start_offset_ = text_start_offset + layout_object->TextStartOffset(); - position_end_offset_ = text_end_offset + layout_object->TextStartOffset(); + position_start_offset_ = position_start_offset; + position_end_offset_ = position_end_offset; single_character_buffer_ = 0; text_start_offset_ = text_start_offset; text_length_ = text_end_offset - text_start_offset;
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h index 64dbf2f..1be6394 100644 --- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h +++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextState.h
@@ -35,7 +35,6 @@ namespace blink { -class LayoutText; class TextIteratorBehavior; class CORE_EXPORT TextIteratorTextState @@ -60,8 +59,10 @@ Node* offset_base_node, int text_start_offset, int text_end_offset); - void EmitText(Node* text_node, - LayoutText* layout_object, + void EmitText(Node*, + int position_start_offset, + int position_end_offset, + const String&, int text_start_offset, int text_end_offset); void EmitAltText(Node*);
diff --git a/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp b/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp index 2bbce29..0a9e723 100644 --- a/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp
@@ -128,7 +128,7 @@ sandbox_->DidUpdateAttributeValue(params.old_value, value); String invalid_tokens; SetSandboxFlags(value.IsNull() ? kSandboxNone - : ParseSandboxPolicy(sandbox_->Tokens(), + : ParseSandboxPolicy(sandbox_->TokenSet(), invalid_tokens)); if (!invalid_tokens.IsNull()) { GetDocument().AddConsoleMessage(ConsoleMessage::Create(
diff --git a/third_party/WebKit/Source/core/html/HTMLIFrameElementAllow.cpp b/third_party/WebKit/Source/core/html/HTMLIFrameElementAllow.cpp index 0e43dc3..37ec3f8 100644 --- a/third_party/WebKit/Source/core/html/HTMLIFrameElementAllow.cpp +++ b/third_party/WebKit/Source/core/html/HTMLIFrameElementAllow.cpp
@@ -21,18 +21,19 @@ Vector<WebFeaturePolicyFeature> feature_names; unsigned num_token_errors = 0; StringBuilder token_errors; - const SpaceSplitString& tokens = this->Tokens(); + const SpaceSplitString& token_set = this->TokenSet(); // Collects a list of valid feature names. const FeatureNameMap& feature_name_map = GetDefaultFeatureNameMap(); - for (size_t i = 0; i < tokens.size(); ++i) { - if (!feature_name_map.Contains(tokens[i])) { + for (size_t i = 0; i < token_set.size(); ++i) { + const AtomicString& token = token_set[i]; + if (!feature_name_map.Contains(token)) { token_errors.Append(token_errors.IsEmpty() ? "'" : ", '"); - token_errors.Append(tokens[i]); + token_errors.Append(token); token_errors.Append("'"); ++num_token_errors; } else { - feature_names.push_back(feature_name_map.at(tokens[i])); + feature_names.push_back(feature_name_map.at(token)); } }
diff --git a/third_party/WebKit/Source/core/html/media/HTMLMediaElementControlsList.cpp b/third_party/WebKit/Source/core/html/media/HTMLMediaElementControlsList.cpp index d1fdd44..028488a 100644 --- a/third_party/WebKit/Source/core/html/media/HTMLMediaElementControlsList.cpp +++ b/third_party/WebKit/Source/core/html/media/HTMLMediaElementControlsList.cpp
@@ -34,15 +34,15 @@ } bool HTMLMediaElementControlsList::ShouldHideDownload() const { - return Tokens().Contains(kNoDownload); + return contains(kNoDownload); } bool HTMLMediaElementControlsList::ShouldHideFullscreen() const { - return Tokens().Contains(kNoFullscreen); + return contains(kNoFullscreen); } bool HTMLMediaElementControlsList::ShouldHideRemotePlayback() const { - return Tokens().Contains(kNoRemotePlayback); + return contains(kNoRemotePlayback); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableCell.h b/third_party/WebKit/Source/core/layout/LayoutTableCell.h index b9bc03b..10a380d 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableCell.h +++ b/third_party/WebKit/Source/core/layout/LayoutTableCell.h
@@ -103,9 +103,7 @@ void ColSpanOrRowSpanChanged(); void SetAbsoluteColumnIndex(unsigned column) { - if (UNLIKELY(column > kMaxColumnIndex)) - IMMEDIATE_CRASH(); - + CHECK_LE(column, kMaxColumnIndex); absolute_column_index_ = column; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.h b/third_party/WebKit/Source/core/layout/LayoutTableRow.h index e9f841f..894db7c 100644 --- a/third_party/WebKit/Source/core/layout/LayoutTableRow.h +++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
@@ -85,9 +85,7 @@ } void SetRowIndex(unsigned row_index) { - if (UNLIKELY(row_index > kMaxRowIndex)) - IMMEDIATE_CRASH(); - + CHECK_LE(row_index, kMaxRowIndex); row_index_ = row_index; }
diff --git a/third_party/WebKit/Source/core/layout/LayoutText.cpp b/third_party/WebKit/Source/core/layout/LayoutText.cpp index 8753bc1..80f0ce2 100644 --- a/third_party/WebKit/Source/core/layout/LayoutText.cpp +++ b/third_party/WebKit/Source/core/layout/LayoutText.cpp
@@ -109,9 +109,7 @@ unsigned length = string->length(); const StringImpl& input = *string->Impl(); - if (length >= std::numeric_limits<unsigned>::max()) - IMMEDIATE_CRASH(); - + CHECK_LT(length, std::numeric_limits<unsigned>::max()); StringBuffer<UChar> string_with_previous(length + 1); string_with_previous[0] = previous == kNoBreakSpaceCharacter ? kSpaceCharacter : previous;
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp index 15466a3..92ea292 100644 --- a/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp +++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleScriptLoaderTest.cpp
@@ -132,7 +132,7 @@ EXPECT_TRUE(client->WasNotifyFinished()) << "ModuleScriptLoader should finish synchronously."; ASSERT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kUninstantiated); }
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp index fec4cbe..ea773dc 100644 --- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp +++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinker.cpp
@@ -390,10 +390,9 @@ ScriptValue error; // Step 6. If result's instantiation state is "errored",... - if (module_script_->InstantiationState() == - ModuleInstantiationState::kErrored) { + if (module_script_->State() == ModuleInstantiationState::kErrored) { // ... Set instantiationStatus to record.ModuleDeclarationInstantiation(). - error = modulator_->GetInstantiationError(module_script_); + error = modulator_->GetError(module_script_); DCHECK(!error.IsEmpty()); } else { // Step 7. Otherwise: @@ -419,7 +418,7 @@ // Step 8.1.3. Set script's instantiation state to "errored". // Step 8.1.4. Set script's instantiation error to // instantiationStatus.[[Value]]. - descendant->SetInstantiationErrorAndClearRecord(error); + descendant->SetErrorAndClearRecord(error); } else { // Step 8.2. Otherwise, set script's instantiation state to // "instantiated". @@ -518,8 +517,7 @@ // instantiation state is "uninstantiated". HeapHashSet<Member<ModuleScript>> uninstantiated_set; for (const auto& script : inclusive_descendants) { - if (script->InstantiationState() == - ModuleInstantiationState::kUninstantiated) + if (script->State() == ModuleInstantiationState::kUninstantiated) uninstantiated_set.insert(script); } return uninstantiated_set;
diff --git a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp index d5fb8c1..fcf2142 100644 --- a/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp +++ b/third_party/WebKit/Source/core/loader/modulescript/ModuleTreeLinkerTest.cpp
@@ -91,12 +91,12 @@ if (state == ModuleInstantiationState::kErrored) { v8::Local<v8::Value> error = V8ThrowException::CreateError( script_state_->GetIsolate(), "Instantiation failure."); - module_script->SetInstantiationErrorAndClearRecord( + module_script->SetErrorAndClearRecord( ScriptValue(script_state_.Get(), error)); } EXPECT_EQ(url, pending_request_url_); - EXPECT_EQ(state, module_script->InstantiationState()); + EXPECT_EQ(state, module_script->State()); EXPECT_TRUE(pending_client_); pending_client_->NotifyModuleLoadFinished(module_script); pending_client_.Clear(); @@ -189,12 +189,10 @@ return ScriptValue(); } - ScriptValue GetInstantiationError( - const ModuleScript* module_script) override { + ScriptValue GetError(const ModuleScript* module_script) override { ScriptState::Scope scope(script_state_.Get()); - return ScriptValue(script_state_.Get(), - module_script->CreateInstantiationErrorInternal( - script_state_->GetIsolate())); + return ScriptValue(script_state_.Get(), module_script->CreateErrorInternal( + script_state_->GetIsolate())); } Vector<String> ModuleRequestsFromScriptModule( @@ -266,7 +264,7 @@ url, {}, ModuleInstantiationState::kUninstantiated); EXPECT_TRUE(client->WasNotifyFinished()); ASSERT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kInstantiated); } @@ -295,7 +293,7 @@ EXPECT_TRUE(client->WasNotifyFinished()); ASSERT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kErrored); } @@ -321,7 +319,7 @@ EXPECT_TRUE(client->WasNotifyFinished()); ASSERT_TRUE(client->GetModuleScript()); EXPECT_EQ(ModuleInstantiationState::kErrored, - client->GetModuleScript()->InstantiationState()); + client->GetModuleScript()->State()); } TEST_F(ModuleTreeLinkerTest, FetchTreeWithSingleDependency) { @@ -354,7 +352,7 @@ EXPECT_TRUE(client->WasNotifyFinished()); ASSERT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kInstantiated); } @@ -405,7 +403,7 @@ EXPECT_TRUE(client->WasNotifyFinished()); ASSERT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kInstantiated); } @@ -501,7 +499,7 @@ EXPECT_TRUE(client->WasNotifyFinished()); ASSERT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kInstantiated); } @@ -529,7 +527,7 @@ EXPECT_TRUE(client->WasNotifyFinished()); ASSERT_TRUE(client->GetModuleScript()); - EXPECT_EQ(client->GetModuleScript()->InstantiationState(), + EXPECT_EQ(client->GetModuleScript()->State(), ModuleInstantiationState::kInstantiated); }
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.cpp b/third_party/WebKit/Source/core/style/ComputedStyle.cpp index f8f5725d..dc0ba2a 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.cpp +++ b/third_party/WebKit/Source/core/style/ComputedStyle.cpp
@@ -911,18 +911,18 @@ void ComputedStyle::AddCursor(StyleImage* image, bool hot_spot_specified, const IntPoint& hot_spot) { - if (!rare_inherited_data_.Access()->cursor_data_) - rare_inherited_data_.Access()->cursor_data_ = new CursorList; - rare_inherited_data_.Access()->cursor_data_->push_back( + if (!CursorDataInternal()) + SetCursorDataInternal(new CursorList); + MutableCursorDataInternal()->push_back( CursorData(image, hot_spot_specified, hot_spot)); } void ComputedStyle::SetCursorList(CursorList* other) { - rare_inherited_data_.Access()->cursor_data_ = other; + SetCursorDataInternal(other); } void ComputedStyle::SetQuotes(RefPtr<QuotesData> q) { - rare_inherited_data_.Access()->quotes_ = std::move(q); + SetQuotesInternal(q); } bool ComputedStyle::QuotesDataEquivalent(const ComputedStyle& other) const { @@ -930,8 +930,8 @@ } void ComputedStyle::ClearCursorList() { - if (rare_inherited_data_->cursor_data_) - rare_inherited_data_.Access()->cursor_data_ = nullptr; + if (CursorDataInternal()) + SetCursorDataInternal(nullptr); } static bool HasPropertyThatCreatesStackingContext( @@ -1207,7 +1207,7 @@ } void ComputedStyle::SetTextShadow(RefPtr<ShadowList> s) { - rare_inherited_data_.Access()->text_shadow_ = std::move(s); + SetTextShadowInternal(s); } bool ComputedStyle::TextShadowDataEquivalent(const ComputedStyle& other) const { @@ -1239,11 +1239,10 @@ } StyleImage* ComputedStyle::ListStyleImage() const { - return rare_inherited_data_->list_style_image_.Get(); + return ListStyleImageInternal(); } void ComputedStyle::SetListStyleImage(StyleImage* v) { - if (rare_inherited_data_->list_style_image_ != v) - rare_inherited_data_.Access()->list_style_image_ = v; + SetListStyleImageInternal(v); } Color ComputedStyle::GetColor() const { @@ -1407,8 +1406,7 @@ } const AtomicString& ComputedStyle::HyphenString() const { - const AtomicString& hyphenation_string = - rare_inherited_data_.Get()->hyphenation_string_; + const AtomicString& hyphenation_string = HyphenationString(); if (!hyphenation_string.IsNull()) return hyphenation_string; @@ -1530,7 +1528,7 @@ TextDecoration ComputedStyle::TextDecorationsInEffect() const { if (HasSimpleUnderlineInternal()) return TextDecoration::kUnderline; - if (!rare_inherited_data_->applied_text_decorations_) + if (!AppliedTextDecorationsInternal()) return TextDecoration::kNone; TextDecoration decorations = TextDecoration::kNone; @@ -1557,16 +1555,16 @@ VisitedDependentColor(CSSPropertyTextDecorationColor)); return underline; } - if (!rare_inherited_data_->applied_text_decorations_) { + if (!AppliedTextDecorationsInternal()) { DEFINE_STATIC_LOCAL(Vector<AppliedTextDecoration>, empty, ()); return empty; } - return rare_inherited_data_->applied_text_decorations_->GetVector(); + return AppliedTextDecorationsInternal()->GetVector(); } StyleInheritedVariables* ComputedStyle::InheritedVariables() const { - return rare_inherited_data_->variables_.Get(); + return VariablesInternal().Get(); } StyleNonInheritedVariables* ComputedStyle::NonInheritedVariables() const { @@ -1574,8 +1572,7 @@ } StyleInheritedVariables& ComputedStyle::MutableInheritedVariables() { - RefPtr<StyleInheritedVariables>& variables = - rare_inherited_data_.Access()->variables_; + RefPtr<StyleInheritedVariables>& variables = MutableVariablesInternal(); if (!variables) variables = StyleInheritedVariables::Create(); else if (!variables->HasOneRef()) @@ -1807,7 +1804,7 @@ void ComputedStyle::AddAppliedTextDecoration( const AppliedTextDecoration& decoration) { RefPtr<AppliedTextDecorationList>& list = - rare_inherited_data_.Access()->applied_text_decorations_; + MutableAppliedTextDecorationsInternal(); if (!list) list = AppliedTextDecorationList::Create(); @@ -1819,7 +1816,7 @@ void ComputedStyle::OverrideTextDecorationColors(Color override_color) { RefPtr<AppliedTextDecorationList>& list = - rare_inherited_data_.Access()->applied_text_decorations_; + MutableAppliedTextDecorationsInternal(); DCHECK(list); if (!list->HasOneRef()) list = list->Copy(); @@ -1832,8 +1829,7 @@ const Color& parent_text_decoration_color, bool override_existing_colors) { if (GetTextDecoration() == TextDecoration::kNone && - !HasSimpleUnderlineInternal() && - !rare_inherited_data_->applied_text_decorations_) + !HasSimpleUnderlineInternal() && !AppliedTextDecorationsInternal()) return; // If there are any color changes or decorations set by this element, stop @@ -1848,8 +1844,7 @@ TextDecoration::kUnderline, kTextDecorationStyleSolid, parent_text_decoration_color)); } - if (override_existing_colors && - rare_inherited_data_->applied_text_decorations_) + if (override_existing_colors && AppliedTextDecorationsInternal()) OverrideTextDecorationColors(current_text_decoration_color); if (GetTextDecoration() == TextDecoration::kNone) return; @@ -1861,7 +1856,7 @@ bool is_simple_underline = decoration_lines == TextDecoration::kUnderline && decoration_style == kTextDecorationStyleSolid && TextDecorationColor().IsCurrentColor(); - if (is_simple_underline && !rare_inherited_data_->applied_text_decorations_) { + if (is_simple_underline && !AppliedTextDecorationsInternal()) { SetHasSimpleUnderlineInternal(true); return; } @@ -1873,17 +1868,17 @@ void ComputedStyle::ClearAppliedTextDecorations() { SetHasSimpleUnderlineInternal(false); - if (rare_inherited_data_->applied_text_decorations_) - rare_inherited_data_.Access()->applied_text_decorations_ = nullptr; + if (AppliedTextDecorationsInternal()) + SetAppliedTextDecorationsInternal(nullptr); } void ComputedStyle::RestoreParentTextDecorations( const ComputedStyle& parent_style) { SetHasSimpleUnderlineInternal(parent_style.HasSimpleUnderlineInternal()); - if (rare_inherited_data_->applied_text_decorations_ != - parent_style.rare_inherited_data_->applied_text_decorations_) { - rare_inherited_data_.Access()->applied_text_decorations_ = - parent_style.rare_inherited_data_->applied_text_decorations_; + if (AppliedTextDecorationsInternal() != + parent_style.AppliedTextDecorationsInternal()) { + SetAppliedTextDecorationsInternal( + parent_style.AppliedTextDecorationsInternal()); } } @@ -2207,8 +2202,7 @@ } TextEmphasisMark ComputedStyle::GetTextEmphasisMark() const { - TextEmphasisMark mark = - static_cast<TextEmphasisMark>(rare_inherited_data_->text_emphasis_mark_); + TextEmphasisMark mark = TextEmphasisMarkInternal(); if (mark != TextEmphasisMark::kAuto) return mark;
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index b772b0a..7d6c296 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -1005,10 +1005,10 @@ } RespectImageOrientationEnum RespectImageOrientation() const { return static_cast<RespectImageOrientationEnum>( - rare_inherited_data_->respect_image_orientation_); + RespectImageOrientationInternal()); } void SetRespectImageOrientation(RespectImageOrientationEnum v) { - SET_VAR(rare_inherited_data_, respect_image_orientation_, v); + SetRespectImageOrientationInternal(v); } // isolation @@ -1468,12 +1468,10 @@ return TextUnderlinePosition::kAuto; } TextUnderlinePosition GetTextUnderlinePosition() const { - return static_cast<TextUnderlinePosition>( - rare_inherited_data_->text_underline_position_); + return TextUnderlinePositionInternal(); } void SetTextUnderlinePosition(TextUnderlinePosition v) { - SET_VAR(rare_inherited_data_, text_underline_position_, - static_cast<unsigned>(v)); + SetTextUnderlinePositionInternal(v); } // text-decoration-skip @@ -1481,12 +1479,10 @@ return TextDecorationSkip::kObjects; } TextDecorationSkip GetTextDecorationSkip() const { - return static_cast<TextDecorationSkip>( - rare_inherited_data_->text_decoration_skip_); + return TextDecorationSkipInternal(); } void SetTextDecorationSkip(TextDecorationSkip v) { - SET_VAR(rare_inherited_data_, text_decoration_skip_, - static_cast<unsigned>(v)); + SetTextDecorationSkipInternal(v); } // text-overflow @@ -1534,7 +1530,7 @@ return rare_non_inherited_data_->will_change_->scroll_position_; } bool SubtreeWillChangeContents() const { - return rare_inherited_data_->subtree_will_change_contents_; + return SubtreeWillChangeContentsInternal(); } void SetWillChangeProperties(const Vector<CSSPropertyID>& properties) { SET_NESTED_VAR(rare_non_inherited_data_, will_change_, properties_, @@ -1547,7 +1543,7 @@ SET_NESTED_VAR(rare_non_inherited_data_, will_change_, scroll_position_, b); } void SetSubtreeWillChangeContents(bool b) { - SET_VAR(rare_inherited_data_, subtree_will_change_contents_, b); + SetSubtreeWillChangeContentsInternal(b); } // z-index @@ -1565,7 +1561,7 @@ // zoom static float InitialZoom() { return 1.0f; } float Zoom() const { return ZoomInternal(); } - float EffectiveZoom() const { return rare_inherited_data_->effective_zoom_; } + float EffectiveZoom() const { return EffectiveZoomInternal(); } bool SetZoom(float); bool SetEffectiveZoom(float); @@ -1654,28 +1650,19 @@ // quotes static QuotesData* InitialQuotes() { return 0; } - QuotesData* Quotes() const { return rare_inherited_data_->quotes_.Get(); } + QuotesData* Quotes() const { return QuotesInternal().Get(); } void SetQuotes(RefPtr<QuotesData>); bool QuotesDataEquivalent(const ComputedStyle&) const; // text-justify static TextJustify InitialTextJustify() { return kTextJustifyAuto; } - TextJustify GetTextJustify() const { - return static_cast<TextJustify>(rare_inherited_data_->text_justify_); - } - void SetTextJustify(TextJustify v) { - SET_VAR(rare_inherited_data_, text_justify_, v); - } - - // text-orientation (aka -webkit-text-orientation, -epub-text-orientation) - bool SetTextOrientation(ETextOrientation); + TextJustify GetTextJustify() const { return TextJustifyInternal(); } + void SetTextJustify(TextJustify v) { SetTextJustifyInternal(v); } // text-shadow static ShadowList* InitialTextShadow() { return 0; } - ShadowList* TextShadow() const { - return rare_inherited_data_->text_shadow_.Get(); - } + ShadowList* TextShadow() const { return TextShadowInternal().Get(); } void SetTextShadow(RefPtr<ShadowList>); bool TextShadowDataEquivalent(const ComputedStyle&) const; @@ -1686,16 +1673,14 @@ } TextEmphasisMark GetTextEmphasisMark() const; void SetTextEmphasisMark(TextEmphasisMark mark) { - SET_VAR(rare_inherited_data_, text_emphasis_mark_, - static_cast<unsigned>(mark)); + SetTextEmphasisMarkInternal(mark); } const AtomicString& TextEmphasisMarkString() const; // -webkit-text-emphasis-color (aka -epub-text-emphasis-color) void SetTextEmphasisColor(const StyleColor& color) { - SET_VAR(rare_inherited_data_, text_emphasis_color_, color.Resolve(Color())); - SET_VAR(rare_inherited_data_, text_emphasis_color_is_current_color_, - color.IsCurrentColor()); + SetTextEmphasisColorInternal(color.Resolve(Color())); + SetTextEmphasisColorIsCurrentColorInternal(color.IsCurrentColor()); } // -webkit-line-clamp @@ -1709,16 +1694,14 @@ // -webkit-text-fill-color void SetTextFillColor(const StyleColor& color) { - SET_VAR(rare_inherited_data_, text_fill_color_, color.Resolve(Color())); - SET_VAR(rare_inherited_data_, text_fill_color_is_current_color_, - color.IsCurrentColor()); + SetTextFillColorInternal(color.Resolve(Color())); + SetTextFillColorIsCurrentColorInternal(color.IsCurrentColor()); } // -webkit-text-stroke-color void SetTextStrokeColor(const StyleColor& color) { - SET_VAR(rare_inherited_data_, text_stroke_color_, color.Resolve(Color())); - SET_VAR(rare_inherited_data_, text_stroke_color_is_current_color_, - color.IsCurrentColor()); + SetTextStrokeColorInternal(color.Resolve(Color())); + SetTextStrokeColorIsCurrentColorInternal(color.IsCurrentColor()); } // -webkit-user-drag @@ -1732,10 +1715,9 @@ // caret-color void SetCaretColor(const StyleAutoColor& color) { - SET_VAR(rare_inherited_data_, caret_color_, color.Resolve(Color())); - SET_VAR(rare_inherited_data_, caret_color_is_current_color_, - color.IsCurrentColor()); - SET_VAR(rare_inherited_data_, caret_color_is_auto_, color.IsAutoColor()); + SetCaretColorInternal(color.Resolve(Color())); + SetCaretColorIsCurrentColorInternal(color.IsCurrentColor()); + SetCaretColorIsAutoInternal(color.IsAutoColor()); } // Font properties. @@ -2026,10 +2008,10 @@ void SetTextAutosizingMultiplier(float); bool SelfOrAncestorHasDirAutoAttribute() const { - return rare_inherited_data_->self_or_ancestor_has_dir_auto_attribute_; + return SelfOrAncestorHasDirAutoAttributeInternal(); } void SetSelfOrAncestorHasDirAutoAttribute(bool v) { - SET_VAR(rare_inherited_data_, self_or_ancestor_has_dir_auto_attribute_, v); + SetSelfOrAncestorHasDirAutoAttributeInternal(v); } // Animation flags. @@ -2970,9 +2952,7 @@ bool HasContent() const { return GetContentData(); } // Cursor utility functions. - CursorList* Cursors() const { - return rare_inherited_data_->cursor_data_.Get(); - } + CursorList* Cursors() const { return CursorDataInternal().Get(); } void AddCursor(StyleImage*, bool hot_spot_specified, const IntPoint& hot_spot = IntPoint()); @@ -3310,33 +3290,22 @@ SET_VAR(rare_non_inherited_data_, visited_link_text_decoration_color_, v); } void SetVisitedLinkTextEmphasisColor(const StyleColor& color) { - SET_VAR(rare_inherited_data_, visited_link_text_emphasis_color_, - color.Resolve(Color())); - SET_VAR(rare_inherited_data_, - visited_link_text_emphasis_color_is_current_color_, - color.IsCurrentColor()); + SetVisitedLinkTextEmphasisColorInternal(color.Resolve(Color())); + SetVisitedLinkTextEmphasisColorIsCurrentColorInternal( + color.IsCurrentColor()); } void SetVisitedLinkTextFillColor(const StyleColor& color) { - SET_VAR(rare_inherited_data_, visited_link_text_fill_color_, - color.Resolve(Color())); - SET_VAR(rare_inherited_data_, - visited_link_text_fill_color_is_current_color_, - color.IsCurrentColor()); + SetVisitedLinkTextFillColorInternal(color.Resolve(Color())); + SetVisitedLinkTextFillColorIsCurrentColorInternal(color.IsCurrentColor()); } void SetVisitedLinkTextStrokeColor(const StyleColor& color) { - SET_VAR(rare_inherited_data_, visited_link_text_stroke_color_, - color.Resolve(Color())); - SET_VAR(rare_inherited_data_, - visited_link_text_stroke_color_is_current_color_, - color.IsCurrentColor()); + SetVisitedLinkTextStrokeColorInternal(color.Resolve(Color())); + SetVisitedLinkTextStrokeColorIsCurrentColorInternal(color.IsCurrentColor()); } void SetVisitedLinkCaretColor(const StyleAutoColor& color) { - SET_VAR(rare_inherited_data_, visited_link_caret_color_, - color.Resolve(Color())); - SET_VAR(rare_inherited_data_, visited_link_caret_color_is_current_color_, - color.IsCurrentColor()); - SET_VAR(rare_inherited_data_, visited_link_caret_color_is_auto_, - color.IsAutoColor()); + SetVisitedLinkCaretColorInternal(color.Resolve(Color())); + SetVisitedLinkCaretColorIsCurrentColorInternal(color.IsCurrentColor()); + SetVisitedLinkCaretColorIsAutoInternal(color.IsAutoColor()); } static bool IsDisplayBlockContainer(EDisplay display) { @@ -3403,11 +3372,11 @@ StyleColor BackgroundColor() const { return BackgroundColorInternal(); } StyleAutoColor CaretColor() const { - if (rare_inherited_data_->caret_color_is_current_color_) + if (CaretColorIsCurrentColorInternal()) return StyleAutoColor::CurrentColor(); - if (rare_inherited_data_->caret_color_is_auto_) + if (CaretColorIsAutoInternal()) return StyleAutoColor::AutoColor(); - return StyleAutoColor(rare_inherited_data_->caret_color_); + return StyleAutoColor(CaretColorInternal()); } Color GetColor() const; StyleColor ColumnRuleColor() const { @@ -3417,26 +3386,26 @@ return rare_non_inherited_data_->outline_.GetColor(); } StyleColor TextEmphasisColor() const { - return rare_inherited_data_->text_emphasis_color_is_current_color_ + return TextEmphasisColorIsCurrentColorInternal() ? StyleColor::CurrentColor() - : StyleColor(rare_inherited_data_->text_emphasis_color_); + : StyleColor(TextEmphasisColorInternal()); } StyleColor TextFillColor() const { - return rare_inherited_data_->text_fill_color_is_current_color_ + return TextFillColorIsCurrentColorInternal() ? StyleColor::CurrentColor() - : StyleColor(rare_inherited_data_->text_fill_color_); + : StyleColor(TextFillColorInternal()); } StyleColor TextStrokeColor() const { - return rare_inherited_data_->text_stroke_color_is_current_color_ + return TextStrokeColorIsCurrentColorInternal() ? StyleColor::CurrentColor() - : StyleColor(rare_inherited_data_->text_stroke_color_); + : StyleColor(TextStrokeColorInternal()); } StyleAutoColor VisitedLinkCaretColor() const { - if (rare_inherited_data_->visited_link_caret_color_is_current_color_) + if (VisitedLinkCaretColorIsCurrentColorInternal()) return StyleAutoColor::CurrentColor(); - if (rare_inherited_data_->visited_link_caret_color_is_auto_) + if (VisitedLinkCaretColorIsAutoInternal()) return StyleAutoColor::AutoColor(); - return StyleAutoColor(rare_inherited_data_->visited_link_caret_color_); + return StyleAutoColor(VisitedLinkCaretColorInternal()); } StyleColor VisitedLinkBackgroundColor() const { return rare_non_inherited_data_->visited_link_background_color_; @@ -3467,24 +3436,19 @@ return rare_non_inherited_data_->visited_link_text_decoration_color_; } StyleColor VisitedLinkTextEmphasisColor() const { - return rare_inherited_data_ - ->visited_link_text_emphasis_color_is_current_color_ + return VisitedLinkTextEmphasisColorIsCurrentColorInternal() ? StyleColor::CurrentColor() - : StyleColor( - rare_inherited_data_->visited_link_text_emphasis_color_); + : StyleColor(VisitedLinkTextEmphasisColorInternal()); } StyleColor VisitedLinkTextFillColor() const { - return rare_inherited_data_->visited_link_text_fill_color_is_current_color_ + return VisitedLinkTextFillColorIsCurrentColorInternal() ? StyleColor::CurrentColor() - : StyleColor( - rare_inherited_data_->visited_link_text_fill_color_); + : StyleColor(VisitedLinkTextFillColorInternal()); } StyleColor VisitedLinkTextStrokeColor() const { - return rare_inherited_data_ - ->visited_link_text_stroke_color_is_current_color_ + return VisitedLinkTextStrokeColorIsCurrentColorInternal() ? StyleColor::CurrentColor() - : StyleColor( - rare_inherited_data_->visited_link_text_stroke_color_); + : StyleColor(VisitedLinkTextStrokeColorInternal()); } StyleColor DecorationColorIncludingFallback(bool visited_link) const; @@ -3573,10 +3537,9 @@ // Clamp the effective zoom value to a smaller (but hopeful still large // enough) range, to avoid overflow in derived computations. float clamped_effective_zoom = clampTo<float>(f, 1e-6, 1e6); - if (compareEqual(rare_inherited_data_->effective_zoom_, - clamped_effective_zoom)) + if (compareEqual(EffectiveZoomInternal(), clamped_effective_zoom)) return false; - rare_inherited_data_.Access()->effective_zoom_ = clamped_effective_zoom; + SetEffectiveZoomInternal(clamped_effective_zoom); return true; } @@ -3588,17 +3551,6 @@ return true; } -inline bool ComputedStyle::SetTextOrientation( - ETextOrientation text_orientation) { - if (compareEqual(rare_inherited_data_->text_orientation_, - static_cast<unsigned>(text_orientation))) - return false; - - rare_inherited_data_.Access()->text_orientation_ = - static_cast<unsigned>(text_orientation); - return true; -} - inline bool ComputedStyle::HasAnyPublicPseudoStyles() const { return PseudoBitsInternal() != kPseudoIdNone; }
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.cpp b/third_party/WebKit/Source/core/testing/DummyModulator.cpp index d5c46fde..4cfd94f5 100644 --- a/third_party/WebKit/Source/core/testing/DummyModulator.cpp +++ b/third_party/WebKit/Source/core/testing/DummyModulator.cpp
@@ -113,7 +113,7 @@ return ScriptValue(); } -ScriptValue DummyModulator::GetInstantiationError(const ModuleScript*) { +ScriptValue DummyModulator::GetError(const ModuleScript*) { NOTREACHED(); return ScriptValue(); }
diff --git a/third_party/WebKit/Source/core/testing/DummyModulator.h b/third_party/WebKit/Source/core/testing/DummyModulator.h index e22cb37..f9f4b6c 100644 --- a/third_party/WebKit/Source/core/testing/DummyModulator.h +++ b/third_party/WebKit/Source/core/testing/DummyModulator.h
@@ -57,7 +57,7 @@ AccessControlStatus, const TextPosition&) override; ScriptValue InstantiateModule(ScriptModule) override; - ScriptValue GetInstantiationError(const ModuleScript*) override; + ScriptValue GetError(const ModuleScript*) override; Vector<String> ModuleRequestsFromScriptModule(ScriptModule) override; void ExecuteModule(const ModuleScript*) override;
diff --git a/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp b/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp index d60272e..b610c52 100644 --- a/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp +++ b/third_party/WebKit/Source/core/xml/XSLTProcessorLibxslt.cpp
@@ -344,17 +344,14 @@ xsltSecurityPrefsPtr security_prefs = xsltNewSecurityPrefs(); // Read permissions are checked by docLoaderFunc. - if (0 != xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_WRITE_FILE, - xsltSecurityForbid)) - IMMEDIATE_CRASH(); - if (0 != xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_CREATE_DIRECTORY, - xsltSecurityForbid)) - IMMEDIATE_CRASH(); - if (0 != xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_WRITE_NETWORK, - xsltSecurityForbid)) - IMMEDIATE_CRASH(); - if (0 != xsltSetCtxtSecurityPrefs(security_prefs, transform_context)) - IMMEDIATE_CRASH(); + CHECK_EQ(0, xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_WRITE_FILE, + xsltSecurityForbid)); + CHECK_EQ(0, + xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_CREATE_DIRECTORY, + xsltSecurityForbid)); + CHECK_EQ(0, xsltSetSecurityPrefs(security_prefs, XSLT_SECPREF_WRITE_NETWORK, + xsltSecurityForbid)); + CHECK_EQ(0, xsltSetCtxtSecurityPrefs(security_prefs, transform_context)); // <http://bugs.webkit.org/show_bug.cgi?id=16077>: XSLT processor // <xsl:sort> algorithm only compares by code point.
diff --git a/third_party/WebKit/Source/modules/app_banner/BeforeInstallPromptEvent.cpp b/third_party/WebKit/Source/modules/app_banner/BeforeInstallPromptEvent.cpp index 096767a..47d459e 100644 --- a/third_party/WebKit/Source/modules/app_banner/BeforeInstallPromptEvent.cpp +++ b/third_party/WebKit/Source/modules/app_banner/BeforeInstallPromptEvent.cpp
@@ -8,6 +8,7 @@ #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" #include "core/dom/ExecutionContext.h" +#include "core/dom/UserGestureIndicator.h" #include "core/frame/UseCounter.h" #include "modules/app_banner/BeforeInstallPromptEventInit.h" @@ -79,7 +80,8 @@ UseCounter::kBeforeInstallPromptEventPrompt); prompt_called_ = true; - banner_service_->DisplayAppBanner(); + banner_service_->DisplayAppBanner( + UserGestureIndicator::ProcessingUserGesture()); return ScriptPromise::CastUndefined(script_state); }
diff --git a/third_party/WebKit/Source/platform/bindings/V8PerContextData.h b/third_party/WebKit/Source/platform/bindings/V8PerContextData.h index e6f2981..8e016e2 100644 --- a/third_party/WebKit/Source/platform/bindings/V8PerContextData.h +++ b/third_party/WebKit/Source/platform/bindings/V8PerContextData.h
@@ -101,6 +101,20 @@ void AddCustomElementBinding(std::unique_ptr<V0CustomElementBinding>); + // Gets a Private to store custom element definition IDs on a + // constructor that has been registered as a custom element in this + // context. This private has to be per-context because the same + // constructor could be simultaneously registered as a custom + // element in many contexts and they each need to give it a unique + // identifier. + v8::Local<v8::Private> GetPrivateCustomElementDefinitionId() { + if (UNLIKELY(private_custom_element_definition_id_.IsEmpty())) { + private_custom_element_definition_id_.Set(isolate_, + v8::Private::New(isolate_)); + } + return private_custom_element_definition_id_.NewLocal(isolate_); + } + V8DOMActivityLogger* ActivityLogger() const { return activity_logger_; } void SetActivityLogger(V8DOMActivityLogger* activity_logger) { activity_logger_ = activity_logger; @@ -138,6 +152,8 @@ ScopedPersistent<v8::Context> context_; ScopedPersistent<v8::Value> error_prototype_; + ScopedPersistent<v8::Private> private_custom_element_definition_id_; + typedef Vector<std::unique_ptr<V0CustomElementBinding>> V0CustomElementBindingList; V0CustomElementBindingList custom_element_bindings_;
diff --git a/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h b/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h index 2129c9c1..7136a10 100644 --- a/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h +++ b/third_party/WebKit/Source/platform/bindings/V8PrivateProperty.h
@@ -27,7 +27,6 @@ X(CustomElement, Document) \ X(CustomElement, IsInterfacePrototypeObject) \ X(CustomElement, NamespaceURI) \ - X(CustomElement, RegistryMap) \ X(CustomElement, TagName) \ X(CustomElement, Type) \ X(CustomElementLifecycle, AttachedCallback) \
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp index 1f1931d8..521ba090 100644 --- a/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp +++ b/third_party/WebKit/Source/platform/graphics/GraphicsLayer.cpp
@@ -387,15 +387,13 @@ void GraphicsLayer::RegisterContentsLayer(WebLayer* layer) { if (!g_registered_layer_set) g_registered_layer_set = new HashSet<int>; - if (g_registered_layer_set->Contains(layer->Id())) - IMMEDIATE_CRASH(); + CHECK(!g_registered_layer_set->Contains(layer->Id())); g_registered_layer_set->insert(layer->Id()); } void GraphicsLayer::UnregisterContentsLayer(WebLayer* layer) { DCHECK(g_registered_layer_set); - if (!g_registered_layer_set->Contains(layer->Id())) - IMMEDIATE_CRASH(); + CHECK(g_registered_layer_set->Contains(layer->Id())); g_registered_layer_set->erase(layer->Id()); } @@ -403,8 +401,7 @@ bool children_changed = false; if (layer) { DCHECK(g_registered_layer_set); - if (!g_registered_layer_set->Contains(layer->Id())) - IMMEDIATE_CRASH(); + CHECK(g_registered_layer_set->Contains(layer->Id())); if (contents_layer_id_ != layer->Id()) { SetupContentsLayer(layer); children_changed = true;
diff --git a/third_party/WebKit/Source/platform/mac/BlockExceptions.mm b/third_party/WebKit/Source/platform/mac/BlockExceptions.mm index 6ae8c89..b1b06e7 100644 --- a/third_party/WebKit/Source/platform/mac/BlockExceptions.mm +++ b/third_party/WebKit/Source/platform/mac/BlockExceptions.mm
@@ -33,7 +33,7 @@ << [[exception description] UTF8String]; // This function is marked as NO_RETURN_DUE_TO_ASSERT, but NOTREACHED() and // DCHECK(false) are not recognized as NO_RETURN. - IMMEDIATE_CRASH(); + LOG(FATAL); #else NSLog(@"*** WebKit discarding exception: <%@> %@", [exception name], [exception reason]);
diff --git a/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp b/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp index abaa2a7521..3093f7c 100644 --- a/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp +++ b/third_party/WebKit/Source/platform/wtf/AssertionsTest.cpp
@@ -27,9 +27,6 @@ SECURITY_CHECK(true); EXPECT_DEATH_IF_SUPPORTED(SECURITY_CHECK(false), ""); - - EXPECT_DEATH_IF_SUPPORTED(IMMEDIATE_CRASH(), ""); - EXPECT_DEATH_IF_SUPPORTED(IMMEDIATE_CRASH(), ""); }; #if !LOG_DISABLED
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h b/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h index f1582d9..cad2797 100644 --- a/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h +++ b/third_party/WebKit/Source/platform/wtf/ThreadSpecific.h
@@ -125,14 +125,12 @@ inline void ThreadSpecificKeyCreate(ThreadSpecificKey* key, void (*destructor)(void*)) { int error = pthread_key_create(key, destructor); - if (error) - IMMEDIATE_CRASH(); + CHECK(!error); } inline void ThreadSpecificKeyDelete(ThreadSpecificKey key) { int error = pthread_key_delete(key); - if (error) - IMMEDIATE_CRASH(); + CHECK(!error); } inline void ThreadSpecificSet(ThreadSpecificKey key, void* value) { @@ -146,8 +144,7 @@ template <typename T> inline ThreadSpecific<T>::ThreadSpecific() { int error = pthread_key_create(&key_, Destroy); - if (error) - IMMEDIATE_CRASH(); + CHECK(!error); } template <typename T> @@ -191,12 +188,10 @@ template <typename T> inline ThreadSpecific<T>::ThreadSpecific() : index_(-1) { DWORD tls_key = TlsAlloc(); - if (tls_key == TLS_OUT_OF_INDEXES) - IMMEDIATE_CRASH(); + CHECK_NE(tls_key, TLS_OUT_OF_INDEXES); index_ = InterlockedIncrement(&TlsKeyCount()) - 1; - if (index_ >= kMaxTlsKeySize) - IMMEDIATE_CRASH(); + CHECK_LE(index_, kMaxTlsKeySize); TlsKeys()[index_] = tls_key; }
diff --git a/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp b/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp index b54917ec..5f12896 100644 --- a/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp +++ b/third_party/WebKit/Source/platform/wtf/ThreadSpecificWin.cpp
@@ -52,8 +52,7 @@ PlatformThreadSpecificKey(void (*destructor)(void*)) : destructor_(destructor) { tls_key_ = TlsAlloc(); - if (tls_key_ == TLS_OUT_OF_INDEXES) - IMMEDIATE_CRASH(); + CHECK_NE(tls_key_, TLS_OUT_OF_INDEXES); } ~PlatformThreadSpecificKey() { TlsFree(tls_key_); }
diff --git a/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp b/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp index 10def1fa..aeba8335 100644 --- a/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp +++ b/third_party/WebKit/Source/platform/wtf/text/StringImpl.cpp
@@ -650,8 +650,7 @@ else return LowerUnicode(); - if (length_ > static_cast<unsigned>(numeric_limits<int32_t>::max())) - IMMEDIATE_CRASH(); + CHECK_LE(length_, static_cast<unsigned>(numeric_limits<int32_t>::max())); int length = length_; RefPtr<StringImpl> upconverted = UpconvertedString(); @@ -676,8 +675,7 @@ else return UpperUnicode(); - if (length_ > static_cast<unsigned>(numeric_limits<int32_t>::max())) - IMMEDIATE_CRASH(); + CHECK_LE(length_, static_cast<unsigned>(numeric_limits<int32_t>::max())); int length = length_; RefPtr<StringImpl> upconverted = UpconvertedString();
diff --git a/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp b/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp index 55f0ce5..315f451 100644 --- a/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp +++ b/third_party/WebKit/Source/platform/wtf/text/TextCodecUTF8.cpp
@@ -463,8 +463,7 @@ // (3x). // Non-BMP characters take two UTF-16 code units and can take up to 4 bytes // (2x). - if (length > std::numeric_limits<size_t>::max() / 3) - IMMEDIATE_CRASH(); + CHECK_LE(length, std::numeric_limits<size_t>::max() / 3); Vector<uint8_t> bytes(length * 3); size_t i = 0;
diff --git a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp index 6a3e3e1..5a6fa555 100644 --- a/third_party/WebKit/Source/web/WebPagePopupImpl.cpp +++ b/third_party/WebKit/Source/web/WebPagePopupImpl.cpp
@@ -599,8 +599,7 @@ // WebPagePopup ---------------------------------------------------------------- WebPagePopup* WebPagePopup::Create(WebWidgetClient* client) { - if (!client) - IMMEDIATE_CRASH(); + CHECK(client); // A WebPagePopupImpl instance usually has two references. // - One owned by the instance itself. It represents the visible widget. // - One owned by a WebViewBase. It's released when the WebViewBase ask the
diff --git a/third_party/WebKit/public/platform/modules/app_banner/app_banner.mojom b/third_party/WebKit/public/platform/modules/app_banner/app_banner.mojom index b0fd835..c2cd2c3b 100644 --- a/third_party/WebKit/public/platform/modules/app_banner/app_banner.mojom +++ b/third_party/WebKit/public/platform/modules/app_banner/app_banner.mojom
@@ -24,5 +24,5 @@ interface AppBannerService { // The renderer asks the browser to display a previously offered app banner. - DisplayAppBanner(); + DisplayAppBanner(bool user_gesture); };
diff --git a/ui/file_manager/file_manager/background/js/file_operation_util.js b/ui/file_manager/file_manager/background/js/file_operation_util.js index 19ba98c..73bb726 100644 --- a/ui/file_manager/file_manager/background/js/file_operation_util.js +++ b/ui/file_manager/file_manager/background/js/file_operation_util.js
@@ -684,6 +684,13 @@ fileOperationUtil.Task.prototype; /** + * Number of consecutive errors to stop CopyTask. + * @const {number} + * @private + */ +fileOperationUtil.CopyTask.CONSECUTIVE_ERROR_LIMIT_ = 100; + +/** * Initializes the CopyTask. * @param {function()} callback Called when the initialize is completed. */ @@ -800,6 +807,11 @@ this.updateProgressRateLimiter_ = new AsyncUtil.RateLimiter(progressCallback); + // Number of consecutive errors. Increases while failing and resets to zero + // when one of them succeeds. + var errorCount = 0; + var lastError; + AsyncUtil.forEach( this.sourceEntries, function(callback, entry, index) { @@ -830,16 +842,29 @@ // Update current source index and processing bytes. this.processingSourceIndex_ = index + 1; this.processedBytes = this.calcProcessedBytes_(); + errorCount = 0; callback(); }.bind(this), function(error) { // Finishes off delayed updates if necessary. this.updateProgressRateLimiter_.runImmediately(); - errorCallback(error); + // Update current source index and processing bytes. + this.processingSourceIndex_ = index + 1; + this.processedBytes = this.calcProcessedBytes_(); + errorCount++; + lastError = error; + if (errorCount < + fileOperationUtil.CopyTask.CONSECUTIVE_ERROR_LIMIT_) { + callback(); + } else { + errorCallback(error); + } }.bind(this)); }, function() { - if (this.deleteAfterCopy) { + if (lastError) { + errorCallback(lastError); + } else if (this.deleteAfterCopy) { deleteOriginals(); } else { successCallback();