diff --git a/.gn b/.gn index 7e694df..f63ba60 100644 --- a/.gn +++ b/.gn
@@ -81,7 +81,6 @@ "//chrome/services/ipp_parser:*", # 1 error "//chrome/services/removable_storage_writer:*", # 1 error "//chrome/services/util_win:*", # 1 error - "//chrome/test/media_router:*", # 5 errors "//chrome/test:*", # 2682 errors "//clank/third_party/gvr_shim:*", # 1 error
diff --git a/DEPS b/DEPS index 445b106..ae1d505 100644 --- a/DEPS +++ b/DEPS
@@ -199,7 +199,7 @@ # 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': '32d68537a88cb1c03407b22cdb47dbaf7169d3ab', + 'skia_revision': '756995baea509d0edddaac763789ddd5b2166321', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -211,11 +211,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'a8b962b78978def21ccccc8db00581e810fa4354', + 'angle_revision': '46d3f02acfab42376ebad0138cfc842c3d19e1a4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'b9e179f1f239bd1da8fffbd997a41095345d1f6a', + 'swiftshader_revision': '7b2f938954180e8945f776d3e202f6a2bda1aaf9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -234,7 +234,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling googletest # and whatever else without interference from each other. - 'googletest_revision': '4fe018038f87675c083d0cfb6a6b57c274fb1753', + 'googletest_revision': '1b0cdaae57c046c87fb99cb4f69c312a7e794adb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -250,7 +250,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'c6345ca36de9d396b4dbef2aeab73a5a838c46b6', + 'freetype_revision': 'f88c00e45a2f503f8a62bb9cc963ece5c46fc7d5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -274,7 +274,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'e61dbc5cf5aa541bf217fd08773eaf9cc5951f52', + 'devtools_frontend_revision': '24a9cfc3d4439e8a881b408bf405ef5d88b4cfe1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -314,7 +314,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'a84acc4fcca80d80c379e3b02d8dc0f7b102ba9d', + 'dawn_revision': 'fac169113df7dad1b55092ab099eabb25e723719', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -353,7 +353,7 @@ 'ukey2_revision': '0275885d8e6038c39b8a8ca55e75d1d4d1727f47', # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'tint_revision': 'e6e704145b31c1a247a97c8c740ab2bec6206af8', + 'tint_revision': '8144af91b4f901b5083b168c6600f4b0f3947d80', # TODO(crbug.com/941824): The values below need to be kept in sync # between //DEPS and //buildtools/DEPS, so if you're updating one, @@ -893,7 +893,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b631a88c6eebea0ef602b2fa551527914bf18c2f', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1c3c9391196663425a3b597cfde81e08213e4725', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1266,7 +1266,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '1bd38fed1b9ecdf531f9bc4ff73d809e3965da1b', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '7f2db542af0fae7d4f406a316ab088554bb33fde', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1485,7 +1485,7 @@ 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '995c0b84414466d77d52011e5b572cbe213b770a', - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@cbab637962d0eea7a3d27dab75c6e1a8c77ba16a', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@5f87855f34ce9c2eddf7fabb0a0e7df3b7ba350a', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '6c656df63da5995a932aafd45b32af1974e497d9', @@ -1590,7 +1590,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3da30cd29fe373845a62373e8f590a61811d90cc', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@18e4d8661753d464fb9f1a1641d413526e271bbc', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 6d9bfd58..de183423 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -767,9 +767,6 @@ '|device/bluetooth/chromeos/'\ '|ui/webui/resources/cr_components/chromeos/bluetooth*' }, - 'chromeos_calculator': { - 'filepath': 'chrome/common/extensions/docs/examples/apps/calculator/', - }, 'chromeos_cellular': { 'filepath': 'chrome/browser/resources/chromeos/cellular_setup/|'\ 'chrome/browser/ui/webui/chromeos/cellular_setup/|'\ @@ -2394,7 +2391,6 @@ 'chromeos_attestation': ['dkrahn+watch@chromium.org'], 'chromeos_bluetooth': ['hansberry+watch-bluetooth@chromium.org', 'vecore+watch-bluetooth@google.com'], - 'chromeos_calculator': ['dharcourt@chromium.org'], 'chromeos_cellular': ['azeemarshad+watch-cellular@chromium.org', 'benchan+watch-cellular@chromium.org', 'ejcaruso+watch-cellular@chromium.org', @@ -2483,6 +2479,7 @@ 'odejesush+watch@chromium.org'], 'devtools': ['devtools-reviews@chromium.org'], 'diagnostics_ui': ['baileyberro+diagnostics-watch@chromium.org', + 'gavinwill+diagnostics-watch@chromium.org', 'joonbug+diagnostics-watch@chromium.org', 'michaelcheco+diagnostics-watch@google.com', 'zentaro+diagnostics-watch@chromium.org'],
diff --git a/android_webview/browser/gfx/hardware_renderer_single_thread.cc b/android_webview/browser/gfx/hardware_renderer_single_thread.cc index 620320d..931765c2 100644 --- a/android_webview/browser/gfx/hardware_renderer_single_thread.cc +++ b/android_webview/browser/gfx/hardware_renderer_single_thread.cc
@@ -119,7 +119,8 @@ CopyOutputRequestQueue requests; requests.swap(child_frame_->copy_requests); for (auto& copy_request : requests) { - support_->RequestCopyOfOutput(child_id_, std::move(copy_request)); + support_->RequestCopyOfOutput( + {child_id_, viz::SubtreeCaptureId(), std::move(copy_request)}); } gfx::Rect clip(params.clip_left, params.clip_top,
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index 07f5fa2..c28adf8 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -79,6 +79,8 @@ + "OS support. May crash if enabled on unsupported device."), Flag.baseFeature(VizFeatures.VIZ_FOR_WEBVIEW, "Enables Viz for WebView."), Flag.baseFeature( + VizFeatures.WEBVIEW_VULKAN_INTERMEDIATE_BUFFER, "For debugging vulkan"), + Flag.baseFeature( GpuFeatures.USE_GLES2_FOR_OOP_R, "Force Skia context to use es2 only."), Flag.baseFeature(AwFeatures.WEBVIEW_CONNECTIONLESS_SAFE_BROWSING, "Uses GooglePlayService's 'connectionless' APIs for Safe Browsing "
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java index 2047c48..e8b793f 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/HeapProfilingTest.java
@@ -6,6 +6,8 @@ import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.MULTI_PROCESS; +import android.os.Build.VERSION_CODES; + import androidx.test.filters.MediumTest; import org.junit.Assert; @@ -15,6 +17,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.components.heap_profiling.multi_process.HeapProfilingTestShim; /** @@ -31,10 +34,13 @@ @Test @MediumTest + // clang-format off + @DisableIf.Build(sdk_is_less_than = VERSION_CODES.M, + message = "http://crbug.com/1163744") @CommandLineFlags.Add({"memlog=browser", "memlog-stack-mode=native-include-thread-names", "memlog-sampling-rate=1"}) - public void - testModeBrowser() { + public void testModeBrowser() { + // clang-format on HeapProfilingTestShim shim = new HeapProfilingTestShim(); Assert.assertTrue( shim.runTestForMode("browser", false, "native-include-thread-names", false, false));
diff --git a/ash/accelerometer/accelerometer_file_reader.cc b/ash/accelerometer/accelerometer_file_reader.cc index c5a16257..7c47c13 100644 --- a/ash/accelerometer/accelerometer_file_reader.cc +++ b/ash/accelerometer/accelerometer_file_reader.cc
@@ -604,7 +604,7 @@ } // Read resulting sample from /dev/cros-ec-accel. - scoped_refptr<AccelerometerUpdate> update = new AccelerometerUpdate(); + AccelerometerUpdate update; for (auto reading_data : configuration_.reading_data) { int reading_size = reading_data.sources.size() * kSizeOfReading; DCHECK_GT(reading_size, 0); @@ -628,13 +628,13 @@ for (AccelerometerSource source : reading_data.sources) { DCHECK(configuration_.has[source]); int16_t* values = reinterpret_cast<int16_t*>(reading); - update->Set(source, - values[configuration_.index[source][0]] * - configuration_.scale[source][0], - values[configuration_.index[source][1]] * - configuration_.scale[source][1], - values[configuration_.index[source][2]] * - configuration_.scale[source][2]); + update.Set(source, + values[configuration_.index[source][0]] * + configuration_.scale[source][0], + values[configuration_.index[source][1]] * + configuration_.scale[source][1], + values[configuration_.index[source][2]] * + configuration_.scale[source][2]); } } @@ -645,9 +645,8 @@ } void AccelerometerFileReader::NotifyObserversWithUpdate( - scoped_refptr<AccelerometerUpdate> update) { + const AccelerometerUpdate& update) { DCHECK(base::CurrentUIThread::IsSet()); - DCHECK(update); if (!emit_events_) return;
diff --git a/ash/accelerometer/accelerometer_file_reader.h b/ash/accelerometer/accelerometer_file_reader.h index 3eaf89f..9400055 100644 --- a/ash/accelerometer/accelerometer_file_reader.h +++ b/ash/accelerometer/accelerometer_file_reader.h
@@ -133,7 +133,7 @@ // Attempts to read the accelerometer data in |task_runner_|. Upon a success, // converts the raw reading to an AccelerometerUpdate and notifies observers. void ReadSample(); - void NotifyObserversWithUpdate(scoped_refptr<AccelerometerUpdate> update); + void NotifyObserversWithUpdate(const AccelerometerUpdate& update); bool emit_events_ = true;
diff --git a/ash/accelerometer/accelerometer_provider_mojo.cc b/ash/accelerometer/accelerometer_provider_mojo.cc index 1296b4c..371fe425 100644 --- a/ash/accelerometer/accelerometer_provider_mojo.cc +++ b/ash/accelerometer/accelerometer_provider_mojo.cc
@@ -29,8 +29,7 @@ } // namespace -AccelerometerProviderMojo::AccelerometerProviderMojo() - : update_(new AccelerometerUpdate()) {} +AccelerometerProviderMojo::AccelerometerProviderMojo() = default; void AccelerometerProviderMojo::PrepareAndInitialize() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -507,12 +506,12 @@ if (!emit_events_) return; - update_->Set(accelerometers_[iio_device_id].location.value(), sample[0], - sample[1], sample[2]); + update_.Set(accelerometers_[iio_device_id].location.value(), sample[0], + sample[1], sample[2]); if (need_two_accelerometers && - (!update_->has(ACCELEROMETER_SOURCE_SCREEN) || - !update_->has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD))) { + (!update_.has(ACCELEROMETER_SOURCE_SCREEN) || + !update_.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD))) { // Wait for the other accel to be updated. return; } @@ -520,7 +519,7 @@ for (auto& observer : observers_) observer.OnAccelerometerUpdated(update_); - update_ = new AccelerometerUpdate(); + update_.Reset(); one_time_read_ = false; if (accelerometer_read_on_)
diff --git a/ash/accelerometer/accelerometer_provider_mojo.h b/ash/accelerometer/accelerometer_provider_mojo.h index ef067d65..5184d66 100644 --- a/ash/accelerometer/accelerometer_provider_mojo.h +++ b/ash/accelerometer/accelerometer_provider_mojo.h
@@ -16,7 +16,6 @@ #include "ash/accelerometer/accelerometer_samples_observer.h" #include "ash/ash_export.h" #include "ash/public/cpp/tablet_mode_observer.h" -#include "base/memory/ref_counted.h" #include "base/observer_list.h" #include "base/optional.h" #include "base/sequence_checker.h" @@ -164,7 +163,7 @@ base::ObserverList<AccelerometerReader::Observer>::Unchecked observers_; // The last seen accelerometer data. - scoped_refptr<AccelerometerUpdate> update_; + AccelerometerUpdate update_; SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/ash/accelerometer/accelerometer_provider_mojo_unittest.cc b/ash/accelerometer/accelerometer_provider_mojo_unittest.cc index 066682b..58ac3b4 100644 --- a/ash/accelerometer/accelerometer_provider_mojo_unittest.cc +++ b/ash/accelerometer/accelerometer_provider_mojo_unittest.cc
@@ -32,25 +32,21 @@ class FakeObserver : public AccelerometerReader::Observer { public: - void OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) override { - if (!update.get()) - return; - + void OnAccelerometerUpdated(const AccelerometerUpdate& update) override { for (uint32_t index = 0; index < ACCELEROMETER_SOURCE_COUNT; ++index) { auto source = static_cast<AccelerometerSource>(index); - if (!update->has(source)) + if (!update.has(source)) continue; - EXPECT_EQ(update->get(source).x, kFakeSampleData[0] * kFakeScaleValue); - EXPECT_EQ(update->get(source).y, kFakeSampleData[1] * kFakeScaleValue); - EXPECT_EQ(update->get(source).z, kFakeSampleData[2] * kFakeScaleValue); + EXPECT_EQ(update.get(source).x, kFakeSampleData[0] * kFakeScaleValue); + EXPECT_EQ(update.get(source).y, kFakeSampleData[1] * kFakeScaleValue); + EXPECT_EQ(update.get(source).z, kFakeSampleData[2] * kFakeScaleValue); } update_ = update; } - scoped_refptr<const AccelerometerUpdate> update_; + AccelerometerUpdate update_; }; class AccelerometerProviderMojoTest : public ::testing::Test { @@ -147,11 +143,8 @@ EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::SUCCESS); - EXPECT_TRUE(observer_.update_.get()); - EXPECT_TRUE(observer_.update_->has(ACCELEROMETER_SOURCE_SCREEN)); - EXPECT_FALSE(observer_.update_->has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); - - observer_.update_.reset(); + EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); + EXPECT_FALSE(observer_.update_.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); } TEST_F(AccelerometerProviderMojoTest, GetSamplesWithNoLidAngle) { @@ -168,11 +161,10 @@ EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::SUCCESS); - EXPECT_TRUE(observer_.update_.get()); - EXPECT_TRUE(observer_.update_->has(ACCELEROMETER_SOURCE_SCREEN)); - EXPECT_TRUE(observer_.update_->has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); + EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); + EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); - observer_.update_.reset(); + observer_.update_.Reset(); // Simulate a disconnection of the accelerometer's mojo channel in IIO // Service. @@ -202,22 +194,20 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(provider_->GetInitializationStateForTesting(), State::SUCCESS); - EXPECT_TRUE(observer_.update_.get()); - EXPECT_TRUE(observer_.update_->has(ACCELEROMETER_SOURCE_SCREEN)); - EXPECT_FALSE(observer_.update_->has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); + EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); + EXPECT_FALSE(observer_.update_.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); - observer_.update_.reset(); + observer_.update_.Reset(); provider_->TriggerRead(); // Wait until samples are received. base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(observer_.update_.get()); - EXPECT_TRUE(observer_.update_->has(ACCELEROMETER_SOURCE_SCREEN)); - EXPECT_FALSE(observer_.update_->has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); + EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); + EXPECT_FALSE(observer_.update_.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); - observer_.update_.reset(); + observer_.update_.Reset(); // Simulate a disconnection of IIO Service. sensor_hal_server_->GetSensorService()->OnServiceDisconnect(); @@ -232,9 +222,8 @@ // Wait until samples are received. base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(observer_.update_.get()); - EXPECT_TRUE(observer_.update_->has(ACCELEROMETER_SOURCE_SCREEN)); - EXPECT_FALSE(observer_.update_->has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); + EXPECT_TRUE(observer_.update_.has(ACCELEROMETER_SOURCE_SCREEN)); + EXPECT_FALSE(observer_.update_.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD)); } } // namespace
diff --git a/ash/accelerometer/accelerometer_reader.h b/ash/accelerometer/accelerometer_reader.h index bfcdb7f7..e039cb70 100644 --- a/ash/accelerometer/accelerometer_reader.h +++ b/ash/accelerometer/accelerometer_reader.h
@@ -39,8 +39,7 @@ // An interface to receive data from the AccelerometerReader. class Observer { public: - virtual void OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) = 0; + virtual void OnAccelerometerUpdated(const AccelerometerUpdate& update) = 0; protected: virtual ~Observer() {}
diff --git a/ash/accelerometer/accelerometer_types.cc b/ash/accelerometer/accelerometer_types.cc index 4f3bc267..e8880f8c 100644 --- a/ash/accelerometer/accelerometer_types.cc +++ b/ash/accelerometer/accelerometer_types.cc
@@ -22,6 +22,25 @@ AccelerometerUpdate::AccelerometerUpdate() = default; +AccelerometerUpdate::AccelerometerUpdate(const AccelerometerUpdate& update) { + *this = update; +} + +AccelerometerUpdate& AccelerometerUpdate::operator=( + const AccelerometerUpdate& update) { + if (this == &update) + return *this; + + for (int i = 0; i < ACCELEROMETER_SOURCE_COUNT; ++i) { + data_[i].present = update.data_[i].present; + data_[i].x = update.data_[i].x; + data_[i].y = update.data_[i].y; + data_[i].z = update.data_[i].z; + } + + return *this; +} + AccelerometerUpdate::~AccelerometerUpdate() = default; gfx::Vector3dF AccelerometerUpdate::GetVector( @@ -30,6 +49,16 @@ return gfx::Vector3dF(reading.x, reading.y, reading.z); } +void AccelerometerUpdate::Set(AccelerometerSource source, + float x, + float y, + float z) { + data_[source].present = true; + data_[source].x = x; + data_[source].y = y; + data_[source].z = z; +} + bool AccelerometerUpdate::IsReadingStable(AccelerometerSource source) const { if (!has(source)) return false; @@ -38,4 +67,13 @@ kDeviationFromGravityThreshold; } +void AccelerometerUpdate::Reset() { + for (int i = 0; i < ACCELEROMETER_SOURCE_COUNT; ++i) { + data_[i].present = false; + data_[i].x = 0; + data_[i].y = 0; + data_[i].z = 0; + } +} + } // namespace ash
diff --git a/ash/accelerometer/accelerometer_types.h b/ash/accelerometer/accelerometer_types.h index 3de5619a..e988147 100644 --- a/ash/accelerometer/accelerometer_types.h +++ b/ash/accelerometer/accelerometer_types.h
@@ -7,7 +7,6 @@ #include "ash/ash_export.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" namespace gfx { class Vector3dF; @@ -49,12 +48,12 @@ // An accelerometer update contains the last known value for each of the // accelerometers present on the device. -class ASH_EXPORT AccelerometerUpdate - : public base::RefCountedThreadSafe<AccelerometerUpdate> { +class ASH_EXPORT AccelerometerUpdate { public: AccelerometerUpdate(); - AccelerometerUpdate(const AccelerometerUpdate&) = delete; - AccelerometerUpdate& operator=(const AccelerometerUpdate&) = delete; + AccelerometerUpdate(const AccelerometerUpdate& update); + AccelerometerUpdate& operator=(const AccelerometerUpdate& update); + ~AccelerometerUpdate(); // Returns true if |source| has a valid value in this update. bool has(AccelerometerSource source) const { return data_[source].present; } @@ -67,25 +66,17 @@ // Returns the last known value for |source| as a vector. gfx::Vector3dF GetVector(AccelerometerSource source) const; - void Set(AccelerometerSource source, float x, float y, float z) { - data_[source].present = true; - data_[source].x = x; - data_[source].y = y; - data_[source].z = z; - } + void Set(AccelerometerSource source, float x, float y, float z); // A reading is considered stable if its deviation from gravity is small. This // returns false if the deviation is too high, or if |source| is not present // in the update. bool IsReadingStable(AccelerometerSource source) const; + void Reset(); + protected: AccelerometerReading data_[ACCELEROMETER_SOURCE_COUNT]; - - private: - friend class base::RefCountedThreadSafe<AccelerometerUpdate>; - - virtual ~AccelerometerUpdate(); }; } // namespace ash
diff --git a/ash/ambient/ui/ambient_assistant_container_view.cc b/ash/ambient/ui/ambient_assistant_container_view.cc index 3f2ae1e6..d05bd18 100644 --- a/ash/ambient/ui/ambient_assistant_container_view.cc +++ b/ash/ambient/ui/ambient_assistant_container_view.cc
@@ -25,6 +25,7 @@ #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace ash { @@ -58,10 +59,6 @@ AssistantUiController::Get()->GetModel()->RemoveObserver(this); } -const char* AmbientAssistantContainerView::GetClassName() const { - return "AmbientAssistantContainerView"; -} - void AmbientAssistantContainerView::OnAssistantControllerDestroying() { AssistantUiController::Get()->GetModel()->RemoveObserver(this); assistant_controller_observer_.Remove(AssistantController::Get()); @@ -146,4 +143,6 @@ avatar_view_->SetClipPath(circular_mask); } +BEGIN_METADATA(AmbientAssistantContainerView, views::View) +END_METADATA } // namespace ash
diff --git a/ash/ambient/ui/ambient_assistant_container_view.h b/ash/ambient/ui/ambient_assistant_container_view.h index 3c9678b..39be75f 100644 --- a/ash/ambient/ui/ambient_assistant_container_view.h +++ b/ash/ambient/ui/ambient_assistant_container_view.h
@@ -27,12 +27,11 @@ public AssistantControllerObserver, public AssistantUiModelObserver { public: + METADATA_HEADER(AmbientAssistantContainerView); + AmbientAssistantContainerView(); ~AmbientAssistantContainerView() override; - // views::View: - const char* GetClassName() const override; - // AssistantControllerObserver: void OnAssistantControllerDestroying() override; @@ -58,7 +57,6 @@ ScopedObserver<AssistantController, AssistantControllerObserver> assistant_controller_observer_{this}; - DISALLOW_COPY_AND_ASSIGN(AmbientAssistantContainerView); }; } // namespace ash
diff --git a/ash/ambient/ui/ambient_assistant_dialog_plate.cc b/ash/ambient/ui/ambient_assistant_dialog_plate.cc index 0040471..a952621 100644 --- a/ash/ambient/ui/ambient_assistant_dialog_plate.cc +++ b/ash/ambient/ui/ambient_assistant_dialog_plate.cc
@@ -17,6 +17,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/views/layout/box_layout.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace ash { @@ -35,10 +36,6 @@ AssistantInteractionController::Get()->GetModel()->RemoveObserver(this); } -const char* AmbientAssistantDialogPlate::GetClassName() const { - return "AmbientAssistantDialogPlate"; -} - void AmbientAssistantDialogPlate::OnButtonPressed(AssistantButtonId button_id) { delegate_->OnDialogPlateButtonPressed(button_id); } @@ -75,4 +72,7 @@ voice_query_view_ = AddChildView(std::make_unique<AssistantQueryView>()); } +BEGIN_METADATA(AmbientAssistantDialogPlate, views::View) +END_METADATA + } // namespace ash
diff --git a/ash/ambient/ui/ambient_assistant_dialog_plate.h b/ash/ambient/ui/ambient_assistant_dialog_plate.h index 93d56b5d..c7132b9 100644 --- a/ash/ambient/ui/ambient_assistant_dialog_plate.h +++ b/ash/ambient/ui/ambient_assistant_dialog_plate.h
@@ -24,12 +24,11 @@ public AssistantControllerObserver, public AssistantInteractionModelObserver { public: + METADATA_HEADER(AmbientAssistantDialogPlate); + explicit AmbientAssistantDialogPlate(AssistantViewDelegate* delegate); ~AmbientAssistantDialogPlate() override; - // views::View: - const char* GetClassName() const override; - // AssistantButtonListener: void OnButtonPressed(AssistantButtonId button_id) override; @@ -52,7 +51,6 @@ ScopedObserver<AssistantController, AssistantControllerObserver> assistant_controller_observer_{this}; - DISALLOW_COPY_AND_ASSIGN(AmbientAssistantDialogPlate); }; } // namespace ash
diff --git a/ash/ambient/ui/ambient_container_view.cc b/ash/ambient/ui/ambient_container_view.cc index 1c86c14..6e80f17 100644 --- a/ash/ambient/ui/ambient_container_view.cc +++ b/ash/ambient/ui/ambient_container_view.cc
@@ -17,6 +17,7 @@ #include "chromeos/services/assistant/public/cpp/features.h" #include "ui/aura/window.h" #include "ui/views/background.h" +#include "ui/views/metadata/metadata_impl_macros.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -39,10 +40,6 @@ AmbientContainerView::~AmbientContainerView() = default; -const char* AmbientContainerView::GetClassName() const { - return "AmbientContainerView"; -} - gfx::Size AmbientContainerView::CalculatePreferredSize() const { // TODO(b/139953389): Handle multiple displays. return GetWidget()->GetNativeWindow()->GetRootWindow()->bounds().size(); @@ -87,4 +84,7 @@ gfx::Rect(0, 0, preferred_width, preferred_height)); } +BEGIN_METADATA(AmbientContainerView, views::View) +END_METADATA + } // namespace ash
diff --git a/ash/ambient/ui/ambient_container_view.h b/ash/ambient/ui/ambient_container_view.h index bfb5aef0..8748190 100644 --- a/ash/ambient/ui/ambient_container_view.h +++ b/ash/ambient/ui/ambient_container_view.h
@@ -21,11 +21,11 @@ // weather info. class ASH_EXPORT AmbientContainerView : public views::View { public: + METADATA_HEADER(AmbientContainerView); + explicit AmbientContainerView(AmbientViewDelegate* delegate); ~AmbientContainerView() override; - // views::View: - const char* GetClassName() const override; gfx::Size CalculatePreferredSize() const override; void Layout() override; @@ -46,7 +46,6 @@ PhotoView* photo_view_ = nullptr; AmbientAssistantContainerView* ambient_assistant_container_view_ = nullptr; - DISALLOW_COPY_AND_ASSIGN(AmbientContainerView); }; } // namespace ash
diff --git a/ash/assistant/ui/base/assistant_button.cc b/ash/assistant/ui/base/assistant_button.cc index 884825b..e62991c0 100644 --- a/ash/assistant/ui/base/assistant_button.cc +++ b/ash/assistant/ui/base/assistant_button.cc
@@ -14,6 +14,7 @@ #include "ui/views/animation/flood_fill_ink_drop_ripple.h" #include "ui/views/animation/ink_drop_impl.h" #include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace ash { @@ -87,10 +88,6 @@ return button; } -const char* AssistantButton::GetClassName() const { - return "AssistantButton"; -} - void AssistantButton::OnBoundsChanged(const gfx::Rect& previous_bounds) { // Note that the current assumption is that button bounds are square. DCHECK_EQ(width(), height()); @@ -127,4 +124,7 @@ listener_->OnButtonPressed(id_); } +BEGIN_METADATA(AssistantButton, views::ImageButton) +END_METADATA + } // namespace ash
diff --git a/ash/assistant/ui/base/assistant_button.h b/ash/assistant/ui/base/assistant_button.h index 79ee32cf..f4bdd7a6 100644 --- a/ash/assistant/ui/base/assistant_button.h +++ b/ash/assistant/ui/base/assistant_button.h
@@ -13,6 +13,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/color_palette.h" #include "ui/views/controls/button/image_button.h" +#include "ui/views/metadata/metadata_header_macros.h" namespace gfx { struct VectorIcon; @@ -30,6 +31,8 @@ class COMPONENT_EXPORT(ASSISTANT_UI) AssistantButton : public views::ImageButton { public: + METADATA_HEADER(AssistantButton); + // Initialization parameters for customizing the Assistant button. struct InitParams { InitParams(); @@ -68,8 +71,6 @@ AssistantButtonId GetAssistantButtonId() const { return id_; } - // views::Button: - const char* GetClassName() const override; void OnBoundsChanged(const gfx::Rect& previous_bounds) override; std::unique_ptr<views::InkDrop> CreateInkDrop() override; std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
diff --git a/ash/assistant/ui/dialog_plate/mic_view.cc b/ash/assistant/ui/dialog_plate/mic_view.cc index 1a20578..689a84be 100644 --- a/ash/assistant/ui/dialog_plate/mic_view.cc +++ b/ash/assistant/ui/dialog_plate/mic_view.cc
@@ -13,6 +13,7 @@ #include "ash/public/cpp/assistant/controller/assistant_ui_controller.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace ash { @@ -41,10 +42,6 @@ AssistantInteractionController::Get()->GetModel()->RemoveObserver(this); } -const char* MicView::GetClassName() const { - return "MicView"; -} - gfx::Size MicView::CalculatePreferredSize() const { return gfx::Size(kPreferredSizeDip, GetHeightForWidth(kPreferredSizeDip)); } @@ -127,4 +124,7 @@ logo_view_->SetState(mic_state, animate); } +BEGIN_METADATA(MicView, AssistantButton) +END_METADATA + } // namespace ash
diff --git a/ash/assistant/ui/dialog_plate/mic_view.h b/ash/assistant/ui/dialog_plate/mic_view.h index 8f85c0e98..5712645b 100644 --- a/ash/assistant/ui/dialog_plate/mic_view.h +++ b/ash/assistant/ui/dialog_plate/mic_view.h
@@ -12,6 +12,7 @@ #include "base/component_export.h" #include "base/macros.h" #include "base/scoped_observer.h" +#include "ui/views/metadata/metadata_header_macros.h" namespace ash { @@ -24,12 +25,14 @@ public AssistantControllerObserver, public AssistantInteractionModelObserver { public: + METADATA_HEADER(MicView); + MicView(AssistantButtonListener* listener, AssistantButtonId button_id); + MicView(const MicView&) = delete; + MicView& operator=(const MicView&) = delete; ~MicView() override; - // AssistantButton: - const char* GetClassName() const override; gfx::Size CalculatePreferredSize() const override; int GetHeightForWidth(int width) const override; @@ -57,8 +60,6 @@ ScopedObserver<AssistantController, AssistantControllerObserver> assistant_controller_observer_{this}; - - DISALLOW_COPY_AND_ASSIGN(MicView); }; } // namespace ash
diff --git a/ash/assistant/ui/logo_view/logo_view_impl.cc b/ash/assistant/ui/logo_view/logo_view_impl.cc index 181ab59d..f2d50ce 100644 --- a/ash/assistant/ui/logo_view/logo_view_impl.cc +++ b/ash/assistant/ui/logo_view/logo_view_impl.cc
@@ -16,6 +16,7 @@ #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/vector2d.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace ash { @@ -46,10 +47,6 @@ state_animator_.StopAnimator(); } -const char* LogoViewImpl::GetClassName() const { - return "LogoViewImpl"; -} - void LogoViewImpl::SetState(LogoView::State state, bool animate) { StateModel::State animator_state; switch (state) { @@ -224,4 +221,7 @@ state_animator_.StopAnimator(); } +BEGIN_METADATA(LogoViewImpl, LogoView) +END_METADATA + } // namespace ash
diff --git a/ash/assistant/ui/logo_view/logo_view_impl.h b/ash/assistant/ui/logo_view/logo_view_impl.h index 1cf434f9..48f324d7 100644 --- a/ash/assistant/ui/logo_view/logo_view_impl.h +++ b/ash/assistant/ui/logo_view/logo_view_impl.h
@@ -18,6 +18,7 @@ #include "chromeos/assistant/internal/logo_view/state_model.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/compositor/compositor_animation_observer.h" +#include "ui/views/metadata/metadata_header_macros.h" namespace chromeos { namespace assistant { @@ -47,16 +48,18 @@ public chromeos::assistant::StateAnimatorTimerDelegate, public ui::CompositorAnimationObserver { public: + METADATA_HEADER(LogoViewImpl); + using Dot = chromeos::assistant::Dot; using Logo = chromeos::assistant::Logo; using StateAnimator = chromeos::assistant::StateAnimator; using StateModel = chromeos::assistant::StateModel; LogoViewImpl(); + LogoViewImpl(const LogoViewImpl&) = delete; + LogoViewImpl& operator=(const LogoViewImpl&) = delete; ~LogoViewImpl() override; - // LogoView: - const char* GetClassName() const override; void SetState(State state, bool animate) override; void SetSpeechLevel(float speech_level) override; @@ -98,8 +101,6 @@ chromeos::assistant::SoundLevelInputValueProvider sound_level_input_value_provider_; - - DISALLOW_COPY_AND_ASSIGN(LogoViewImpl); }; } // namespace ash
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index dd637720..ea45c251 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -425,7 +425,6 @@ void CaptureModeController::OnRecordingEnded(bool success) { delegate_->StopObservingRestrictedContent(); - window_frame_sink_.reset(); // If |success| is false, then recording has been force-terminated due to a // failure on the service side, or a disconnection to it. We need to terminate @@ -579,12 +578,9 @@ audio_stream_factory.InitWithNewPipeAndPassReceiver()); } - auto frame_sink_id = capture_params.window->GetFrameSinkId(); - if (!frame_sink_id.is_valid()) { - window_frame_sink_ = capture_params.window->CreateLayerTreeFrameSink(); - frame_sink_id = capture_params.window->GetFrameSinkId(); - DCHECK(frame_sink_id.is_valid()); - } + const auto frame_sink_id = + capture_params.window->GetRootWindow()->GetFrameSinkId(); + const auto bounds = capture_params.bounds; switch (source_) { case CaptureModeSource::kFullscreen: @@ -594,11 +590,18 @@ break; case CaptureModeSource::kWindow: - // TODO(crbug.com/1143930): Window recording doesn't produce any frames at - // the moment. + // Non-root window are not capturable by the |FrameSinkVideoCapturer| + // unless its layer tree is identified by a |viz::SubtreeCaptureId|. + // The |VideoRecordingWatcher| that we create while recording is in + // progress creates a request to mark that window as capturable. + // See https://crbug.com/1143930 for more details. + DCHECK(!capture_params.window->IsRootWindow()); + DCHECK(capture_params.window->subtree_capture_id().is_valid()); + recording_service_remote_->RecordWindow( std::move(client), std::move(video_capturer), - std::move(audio_stream_factory), frame_sink_id, bounds.size(), + std::move(audio_stream_factory), frame_sink_id, + capture_params.window->subtree_capture_id(), bounds.size(), capture_params.window->GetRootWindow() ->GetBoundsInRootWindow() .size());
diff --git a/ash/capture_mode/capture_mode_controller.h b/ash/capture_mode/capture_mode_controller.h index 80f84c9..02b45bd1 100644 --- a/ash/capture_mode/capture_mode_controller.h +++ b/ash/capture_mode/capture_mode_controller.h
@@ -33,10 +33,6 @@ class SequencedTaskRunner; } // namespace base -namespace cc { -class LayerTreeFrameSink; -} // namespace cc - namespace ash { class CaptureModeSession; @@ -283,12 +279,6 @@ // If set, it will be called when either an image or video file is saved. base::OnceCallback<void(const base::FilePath&)> on_file_saved_callback_; - // Recording non-root windows require sending their FrameSinkIds to the - // recording service. Those windows won't have a valid ID unless we create - // LayerTreeFrameSinks for them. This remains alive while the window is being - // recorded. - std::unique_ptr<cc::LayerTreeFrameSink> window_frame_sink_; - // Timers used to schedule recording of the number of screenshots taken. base::RepeatingTimer num_screenshots_taken_in_last_day_scheduler_; base::RepeatingTimer num_screenshots_taken_in_last_week_scheduler_;
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc index b302b367..194f61e 100644 --- a/ash/capture_mode/capture_mode_unittests.cc +++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -1481,6 +1481,25 @@ kTabletHistogram, CaptureModeEntryType::kAccelTakePartialScreenshot, 2); } +TEST_F(CaptureModeTest, WindowRecordingCaptureId) { + auto window = CreateTestWindow(gfx::Rect(200, 200)); + StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo); + + auto* event_generator = GetEventGenerator(); + event_generator->MoveMouseToCenterOf(window.get()); + auto* controller = CaptureModeController::Get(); + controller->StartVideoRecordingImmediatelyForTesting(); + EXPECT_TRUE(controller->is_recording_in_progress()); + + // The window should have a valid capture ID. + EXPECT_TRUE(window->subtree_capture_id().is_valid()); + + // Once recording ends, the window should no longer be marked as capturable. + controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton); + EXPECT_FALSE(controller->is_recording_in_progress()); + EXPECT_FALSE(window->subtree_capture_id().is_valid()); +} + TEST_F(CaptureModeTest, ClosingWindowBeingRecorded) { auto window = CreateTestWindow(gfx::Rect(200, 200)); StartCaptureSession(CaptureModeSource::kWindow, CaptureModeType::kVideo); @@ -1491,6 +1510,9 @@ controller->StartVideoRecordingImmediatelyForTesting(); EXPECT_TRUE(controller->is_recording_in_progress()); + // The window should have a valid capture ID. + EXPECT_TRUE(window->subtree_capture_id().is_valid()); + // Closing the window being recorded should end video recording. base::HistogramTester histogram_tester; window.reset(); @@ -1939,6 +1961,7 @@ // mode when capturing a window. Regression test for https://crbug.com/1152938. TEST_F(CaptureModeTest, TabletTouchCaptureLabelWidgetWindowMode) { TabletModeControllerTestApi tablet_mode_controller_test_api; + tablet_mode_controller_test_api.DetachAllMice(); tablet_mode_controller_test_api.EnterTabletMode(); // Enter capture window mode.
diff --git a/ash/capture_mode/test_capture_mode_delegate.cc b/ash/capture_mode/test_capture_mode_delegate.cc index 22fed2e..4d606e5 100644 --- a/ash/capture_mode/test_capture_mode_delegate.cc +++ b/ash/capture_mode/test_capture_mode_delegate.cc
@@ -41,6 +41,7 @@ mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer, mojo::PendingRemote<audio::mojom::StreamFactory> audio_stream_factory, const viz::FrameSinkId& frame_sink_id, + const viz::SubtreeCaptureId& subtree_capture_id, const gfx::Size& initial_window_size, const gfx::Size& max_window_size) override { remote_client_.Bind(std::move(client));
diff --git a/ash/capture_mode/video_recording_watcher.cc b/ash/capture_mode/video_recording_watcher.cc index af56308f..c5d55bd 100644 --- a/ash/capture_mode/video_recording_watcher.cc +++ b/ash/capture_mode/video_recording_watcher.cc
@@ -22,6 +22,11 @@ DCHECK(window_being_recorded_); DCHECK(controller_->is_recording_in_progress()); + if (!window_being_recorded_->IsRootWindow()) { + non_root_window_capture_request_ = + window_being_recorded_->MakeWindowCapturable(); + } + window_being_recorded_->AddObserver(this); }
diff --git a/ash/capture_mode/video_recording_watcher.h b/ash/capture_mode/video_recording_watcher.h index 0130d6b..792d771 100644 --- a/ash/capture_mode/video_recording_watcher.h +++ b/ash/capture_mode/video_recording_watcher.h
@@ -5,6 +5,7 @@ #ifndef ASH_CAPTURE_MODE_VIDEO_RECORDING_WATCHER_H_ #define ASH_CAPTURE_MODE_VIDEO_RECORDING_WATCHER_H_ +#include "ui/aura/scoped_window_capture_request.h" #include "ui/aura/window_observer.h" namespace ash { @@ -34,6 +35,10 @@ private: CaptureModeController* const controller_; aura::Window* const window_being_recorded_; + + // If |window_being_recorded_| is not a root window, we must make a request to + // make it capturable by the |FrameSinkVideoCapturer|. + aura::ScopedWindowCaptureRequest non_root_window_capture_request_; }; } // namespace ash
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index 3350edb6..155c1b9b 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc
@@ -3548,21 +3548,18 @@ void SetUp() override { DisplayManagerTest::SetUp(); - portrait_primary->Set(ACCELEROMETER_SOURCE_SCREEN, -base::kMeanGravityFloat, - 0.f, 0.f); - portrait_secondary->Set(ACCELEROMETER_SOURCE_SCREEN, - base::kMeanGravityFloat, 0.f, 0.f); - landscape_primary->Set(ACCELEROMETER_SOURCE_SCREEN, 0, - -base::kMeanGravityFloat, 0.f); + portrait_primary.Set(ACCELEROMETER_SOURCE_SCREEN, -base::kMeanGravityFloat, + 0.f, 0.f); + portrait_secondary.Set(ACCELEROMETER_SOURCE_SCREEN, base::kMeanGravityFloat, + 0.f, 0.f); + landscape_primary.Set(ACCELEROMETER_SOURCE_SCREEN, 0, + -base::kMeanGravityFloat, 0.f); } protected: - scoped_refptr<AccelerometerUpdate> portrait_primary = - new AccelerometerUpdate(); - scoped_refptr<AccelerometerUpdate> portrait_secondary = - new AccelerometerUpdate(); - scoped_refptr<AccelerometerUpdate> landscape_primary = - new AccelerometerUpdate(); + AccelerometerUpdate portrait_primary; + AccelerometerUpdate portrait_secondary; + AccelerometerUpdate landscape_primary; private: DISALLOW_COPY_AND_ASSIGN(DisplayManagerOrientationTest);
diff --git a/ash/display/display_prefs_unittest.cc b/ash/display/display_prefs_unittest.cc index 531ab65..7f6b293 100644 --- a/ash/display/display_prefs_unittest.cc +++ b/ash/display/display_prefs_unittest.cc
@@ -25,7 +25,6 @@ #include "base/command_line.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" #include "base/numerics/math_constants.h" #include "base/strings/string_number_conversions.h" #include "base/test/scoped_feature_list.h" @@ -842,18 +841,18 @@ display::Display::RotationSource::USER); // Open up 270 degrees to trigger tablet mode - scoped_refptr<AccelerometerUpdate> update(new AccelerometerUpdate()); - update->Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, 0.0f, 0.0f, - -base::kMeanGravityFloat); - update->Set(ACCELEROMETER_SOURCE_SCREEN, 0.0f, base::kMeanGravityFloat, 0.0f); + AccelerometerUpdate update; + update.Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, 0.0f, 0.0f, + -base::kMeanGravityFloat); + update.Set(ACCELEROMETER_SOURCE_SCREEN, 0.0f, base::kMeanGravityFloat, 0.0f); TabletModeController* controller = Shell::Get()->tablet_mode_controller(); controller->OnAccelerometerUpdated(update); EXPECT_TRUE(controller->InTabletMode()); // Trigger 90 degree rotation - update->Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, base::kMeanGravityFloat, - 0.0f, 0.0f); - update->Set(ACCELEROMETER_SOURCE_SCREEN, base::kMeanGravityFloat, 0.0f, 0.0f); + update.Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, base::kMeanGravityFloat, + 0.0f, 0.0f); + update.Set(ACCELEROMETER_SOURCE_SCREEN, base::kMeanGravityFloat, 0.0f, 0.0f); controller->OnAccelerometerUpdated(update); shell->screen_orientation_controller()->OnAccelerometerUpdated(update); EXPECT_EQ(display::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); @@ -990,10 +989,10 @@ EXPECT_EQ(display::Display::ROTATE_0, before_tablet_mode_rotation); // Open up 270 degrees to trigger tablet mode - scoped_refptr<AccelerometerUpdate> update(new AccelerometerUpdate()); - update->Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, 0.0f, 0.0f, - -base::kMeanGravityFloat); - update->Set(ACCELEROMETER_SOURCE_SCREEN, 0.0f, base::kMeanGravityFloat, 0.0f); + AccelerometerUpdate update; + update.Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, 0.0f, 0.0f, + -base::kMeanGravityFloat); + update.Set(ACCELEROMETER_SOURCE_SCREEN, 0.0f, base::kMeanGravityFloat, 0.0f); TabletModeController* tablet_mode_controller = Shell::Get()->tablet_mode_controller(); tablet_mode_controller->OnAccelerometerUpdated(update);
diff --git a/ash/display/screen_orientation_controller.cc b/ash/display/screen_orientation_controller.cc index a3d6560..809baaa7 100644 --- a/ash/display/screen_orientation_controller.cc +++ b/ash/display/screen_orientation_controller.cc
@@ -393,18 +393,18 @@ } void ScreenOrientationController::OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) { + const AccelerometerUpdate& update) { if (!IsAutoRotationAllowed()) return; if (rotation_locked_ && !CanRotateInLockedState()) return; - if (!update->has(ACCELEROMETER_SOURCE_SCREEN)) + if (!update.has(ACCELEROMETER_SOURCE_SCREEN)) return; // Ignore the reading if it appears unstable. The reading is considered // unstable if it deviates too much from gravity - if (update->IsReadingStable(ACCELEROMETER_SOURCE_SCREEN)) - HandleScreenRotation(update->get(ACCELEROMETER_SOURCE_SCREEN)); + if (update.IsReadingStable(ACCELEROMETER_SOURCE_SCREEN)) + HandleScreenRotation(update.get(ACCELEROMETER_SOURCE_SCREEN)); } void ScreenOrientationController::OnDisplayConfigurationChanged() {
diff --git a/ash/display/screen_orientation_controller.h b/ash/display/screen_orientation_controller.h index f680987..00d613f 100644 --- a/ash/display/screen_orientation_controller.h +++ b/ash/display/screen_orientation_controller.h
@@ -152,8 +152,7 @@ void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; // AccelerometerReader::Observer: - void OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) override; + void OnAccelerometerUpdated(const AccelerometerUpdate& update) override; // WindowTreeHostManager::Observer: void OnDisplayConfigurationChanged() override;
diff --git a/ash/display/screen_orientation_controller_unittest.cc b/ash/display/screen_orientation_controller_unittest.cc index bd8925b5..1b3e18d 100644 --- a/ash/display/screen_orientation_controller_unittest.cc +++ b/ash/display/screen_orientation_controller_unittest.cc
@@ -79,8 +79,8 @@ } void TriggerLidUpdate(const gfx::Vector3dF& lid) { - scoped_refptr<AccelerometerUpdate> update(new AccelerometerUpdate()); - update->Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z()); + AccelerometerUpdate update; + update.Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z()); Shell::Get()->screen_orientation_controller()->OnAccelerometerUpdated(update); }
diff --git a/ash/fast_ink/view_tree_host_root_view.cc b/ash/fast_ink/view_tree_host_root_view.cc index 9bb359c8..a982ca9 100644 --- a/ash/fast_ink/view_tree_host_root_view.cc +++ b/ash/fast_ink/view_tree_host_root_view.cc
@@ -366,6 +366,14 @@ } } +bool ViewTreeHostRootView::GetIsOverlayCandidate() { + return is_overlay_candidate_; +} + +void ViewTreeHostRootView::SetIsOverlayCandidate(bool is_overlay_candidate) { + is_overlay_candidate_ = is_overlay_candidate; +} + void ViewTreeHostRootView::UpdateSurface(const gfx::Rect& damage_rect, std::unique_ptr<Resource> resource) { damage_rect_.Union(damage_rect); @@ -435,7 +443,7 @@ transferable_resource.size = buffer_size_; transferable_resource.mailbox_holder = gpu::MailboxHolder( resource->mailbox, resource->sync_token, GL_TEXTURE_2D); - transferable_resource.is_overlay_candidate = true; + transferable_resource.is_overlay_candidate = is_overlay_candidate_; gfx::Transform buffer_to_target_transform; bool rv = rotate_transform_.GetInverse(&buffer_to_target_transform);
diff --git a/ash/fast_ink/view_tree_host_root_view.h b/ash/fast_ink/view_tree_host_root_view.h index 010455c..6ab9ad3 100644 --- a/ash/fast_ink/view_tree_host_root_view.h +++ b/ash/fast_ink/view_tree_host_root_view.h
@@ -41,6 +41,9 @@ void SchedulePaintInRect(const gfx::Rect& rect); + bool GetIsOverlayCandidate(); + void SetIsOverlayCandidate(bool is_overlay_candidate); + private: struct Resource; class LayerTreeViewTreeFrameSinkHolder; @@ -71,6 +74,9 @@ gfx::Rect damaged_paint_rect_; bool pending_paint_ = false; + // overlay candidate in submitted frame data. + bool is_overlay_candidate_ = true; + // The resource to be submitted. std::unique_ptr<Resource> pending_resource_;
diff --git a/ash/hud_display/hud_display.cc b/ash/hud_display/hud_display.cc index 75582ce..1608a8c5 100644 --- a/ash/hud_display/hud_display.cc +++ b/ash/hud_display/hud_display.cc
@@ -25,6 +25,7 @@ #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/metadata/metadata_impl_macros.h" +#include "ui/views/widget/native_widget.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -44,6 +45,9 @@ views::Widget* g_hud_widget = nullptr; +// True if HUD should be initialized as overlay. +bool g_hud_overlay_mode = true; + // ClientView that return HTNOWHERE by default. A child view can receive event // by setting kHitTestComponentKey property to HTCLIENT. class HTClientView : public views::ClientView { @@ -124,6 +128,8 @@ kHUDViewDefaultHeight + 2 * kGridLineWidth); auto* widget = CreateViewTreeHostWidget(std::move(params)); widget->GetLayer()->SetName("HUDDisplayView"); + static_cast<ViewTreeHostRootView*>(widget->GetRootView()) + ->SetIsOverlayCandidate(g_hud_overlay_mode); widget->Show(); g_hud_widget = widget; @@ -174,7 +180,7 @@ data->SetLayoutManager(std::make_unique<views::FillLayout>()); graphs_container_ = data->AddChildView(std::make_unique<GraphsContainerView>()); - settings_view_ = data->AddChildView(std::make_unique<HUDSettingsView>()); + settings_view_ = data->AddChildView(std::make_unique<HUDSettingsView>(this)); settings_view_->SetVisible(false); // CPU display is active by default. @@ -191,6 +197,17 @@ graphs_container_->SetVisible(!settings_view_->GetVisible()); } +bool HUDDisplayView::IsOverlay() { + return static_cast<ViewTreeHostRootView*>(GetWidget()->GetRootView()) + ->GetIsOverlayCandidate(); +} + +void HUDDisplayView::ToggleOverlay() { + g_hud_overlay_mode = !g_hud_overlay_mode; + static_cast<ViewTreeHostRootView*>(GetWidget()->GetRootView()) + ->SetIsOverlayCandidate(g_hud_overlay_mode); +} + int HUDDisplayView::NonClientHitTest(const gfx::Point& point) { const View* view = GetEventHandlerForPoint(point); if (!view)
diff --git a/ash/hud_display/hud_display.h b/ash/hud_display/hud_display.h index c4723b9..8dc3f3f 100644 --- a/ash/hud_display/hud_display.h +++ b/ash/hud_display/hud_display.h
@@ -43,6 +43,12 @@ // Callback from SettingsButton. void OnSettingsToggle(); + // Returns true if HUD is in overlay mode. + bool IsOverlay(); + + // Changes HUD overlay flag. + void ToggleOverlay(); + private: HUDHeaderView* header_view_ = nullptr; // not owned GraphsContainerView* graphs_container_ = nullptr; // not owned
diff --git a/ash/hud_display/hud_settings_view.cc b/ash/hud_display/hud_settings_view.cc index 3835445..f7e66f4 100644 --- a/ash/hud_display/hud_settings_view.cc +++ b/ash/hud_display/hud_settings_view.cc
@@ -4,6 +4,7 @@ #include "ash/hud_display/hud_settings_view.h" +#include "ash/hud_display/hud_display.h" #include "ash/hud_display/hud_properties.h" #include "ash/shell.h" #include "base/bind.h" @@ -117,8 +118,10 @@ public: METADATA_HEADER(SettingsCheckbox); - explicit SettingsCheckbox(const base::string16& label) - : views::Checkbox(label, views::Button::PressedCallback()) {} + SettingsCheckbox(const base::string16& label, const base::string16& tooltip) + : views::Checkbox(label, views::Button::PressedCallback()) { + SetTooltipText(tooltip); + } SettingsCheckbox(const SettingsCheckbox& other) = delete; SettingsCheckbox operator=(const SettingsCheckbox& other) = delete; @@ -337,7 +340,7 @@ BEGIN_METADATA(HUDSettingsView, views::View) END_METADATA -HUDSettingsView::HUDSettingsView() { +HUDSettingsView::HUDSettingsView(HUDDisplayView* hud_display) { SetVisible(false); // We want AnimationSpeedControl to be stretched horizontally so we turn @@ -362,10 +365,10 @@ auto add_checkbox = [](HUDSettingsView* self, views::View* container, - const base::string16& text, + const base::string16& text, const base::string16& tooltip, base::RepeatingCallback<void(views::Checkbox*)> callback) { - views::Checkbox* checkbox = - container->AddChildView(std::make_unique<SettingsCheckbox>(text)); + views::Checkbox* checkbox = container->AddChildView( + std::make_unique<SettingsCheckbox>(text, tooltip)); checkbox->SetCallback( base::BindRepeating(std::move(callback), checkbox)); checkbox->SetEnabledTextColors(kHUDDefaultColor); @@ -374,33 +377,58 @@ }; checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>( - add_checkbox(this, checkbox_container, - base::ASCIIToUTF16("Tint composited content"), - GetVisDebugHandleClickCallback( - &viz::DebugRendererSettings::tint_composited_content)), + add_checkbox( + this, checkbox_container, + base::ASCIIToUTF16("Tint composited content"), + base::ASCIIToUTF16( + "Equivalent to --tint-composited-content command-line option."), + GetVisDebugHandleClickCallback( + &viz::DebugRendererSettings::tint_composited_content)), GetVisDebugUpdateStateCallback( &viz::DebugRendererSettings::tint_composited_content))); checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>( - add_checkbox(this, checkbox_container, - base::ASCIIToUTF16("Show overdraw feedback"), - GetVisDebugHandleClickCallback( - &viz::DebugRendererSettings::show_overdraw_feedback)), + add_checkbox( + this, checkbox_container, + base::ASCIIToUTF16("Show overdraw feedback"), + base::ASCIIToUTF16( + "Equivalent to --show-overdraw-feedback command-line option."), + GetVisDebugHandleClickCallback( + &viz::DebugRendererSettings::show_overdraw_feedback)), GetVisDebugUpdateStateCallback( &viz::DebugRendererSettings::show_overdraw_feedback))); checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>( - add_checkbox(this, checkbox_container, - base::ASCIIToUTF16("Show aggregated damage"), - GetVisDebugHandleClickCallback( - &viz::DebugRendererSettings::show_aggregated_damage)), + add_checkbox( + this, checkbox_container, + base::ASCIIToUTF16("Show aggregated damage"), + base::ASCIIToUTF16( + "Equivalent to --show-aggregated-damage command-line option."), + GetVisDebugHandleClickCallback( + &viz::DebugRendererSettings::show_aggregated_damage)), GetVisDebugUpdateStateCallback( &viz::DebugRendererSettings::show_aggregated_damage))); checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>( - add_checkbox(this, checkbox_container, - base::ASCIIToUTF16("Show paint rect."), - GetCCDebugHandleClickCallback( - &cc::LayerTreeDebugState::show_paint_rects)), + add_checkbox( + this, checkbox_container, base::ASCIIToUTF16("Show paint rect."), + base::ASCIIToUTF16( + "Equivalent to --ui-show-paint-rects command-line option."), + GetCCDebugHandleClickCallback( + &cc::LayerTreeDebugState::show_paint_rects)), GetCCDebugUpdateStateCallback( &cc::LayerTreeDebugState::show_paint_rects))); + checkbox_handlers_.push_back(std::make_unique<HUDCheckboxHandler>( + add_checkbox(this, checkbox_container, + base::ASCIIToUTF16("HUD is overlay."), + base::ASCIIToUTF16("Flips HUD overlay mode flag."), + base::BindRepeating( + [](HUDDisplayView* hud_display, views::Checkbox*) { + hud_display->ToggleOverlay(); + }, + base::Unretained(hud_display))), + base::BindRepeating( + [](HUDDisplayView* hud_display, views::Checkbox* checkbox) { + checkbox->SetChecked(hud_display->IsOverlay()); + }, + base::Unretained(hud_display)))); AddChildView(std::make_unique<AnimationSpeedControl>()); }
diff --git a/ash/hud_display/hud_settings_view.h b/ash/hud_display/hud_settings_view.h index 9408a50..35739ec 100644 --- a/ash/hud_display/hud_settings_view.h +++ b/ash/hud_display/hud_settings_view.h
@@ -15,12 +15,13 @@ namespace hud_display { class HUDCheckboxHandler; +class HUDDisplayView; class HUDSettingsView : public views::View { public: METADATA_HEADER(HUDSettingsView); - HUDSettingsView(); + explicit HUDSettingsView(HUDDisplayView* hud_display); ~HUDSettingsView() override; HUDSettingsView(const HUDSettingsView&) = delete;
diff --git a/ash/login/ui/arrow_button_view.cc b/ash/login/ui/arrow_button_view.cc index b9e4352..3f590e58 100644 --- a/ash/login/ui/arrow_button_view.cc +++ b/ash/login/ui/arrow_button_view.cc
@@ -19,6 +19,7 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/skia_util.h" #include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace ash { namespace { @@ -104,10 +105,6 @@ node_data->SetNameExplicitlyEmpty(); } -const char* ArrowButtonView::GetClassName() const { - return "ArrowButtonView"; -} - void ArrowButtonView::SetBackgroundColor(SkColor color) { background_color_ = color; SchedulePaint(); @@ -149,4 +146,7 @@ owner_->SchedulePaint(); } +BEGIN_METADATA(ArrowButtonView, LoginButton) +END_METADATA + } // namespace ash
diff --git a/ash/login/ui/arrow_button_view.h b/ash/login/ui/arrow_button_view.h index 574de0b..2af8873 100644 --- a/ash/login/ui/arrow_button_view.h +++ b/ash/login/ui/arrow_button_view.h
@@ -10,6 +10,7 @@ #include "ash/login/ui/login_button.h" #include "ui/gfx/animation/animation_delegate.h" #include "ui/views/controls/image_view.h" +#include "ui/views/metadata/metadata_header_macros.h" namespace gfx { class MultiAnimation; @@ -22,13 +23,16 @@ // view. class ArrowButtonView : public LoginButton { public: + METADATA_HEADER(ArrowButtonView); + ArrowButtonView(PressedCallback callback, int size); + ArrowButtonView(const ArrowButtonView&) = delete; + ArrowButtonView& operator=(const ArrowButtonView&) = delete; ~ArrowButtonView() override; // views::Button: void PaintButtonContents(gfx::Canvas* canvas) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - const char* GetClassName() const override; // Set background color of the button. void SetBackgroundColor(SkColor color); @@ -59,8 +63,6 @@ SkColor background_color_; LoadingAnimationDelegate loading_animation_delegate_{this}; std::unique_ptr<gfx::MultiAnimation> loading_animation_; - - DISALLOW_COPY_AND_ASSIGN(ArrowButtonView); }; } // namespace ash
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc index ab0931cf..769d3b0f 100644 --- a/ash/public/cpp/ash_features.cc +++ b/ash/public/cpp/ash_features.cc
@@ -29,9 +29,6 @@ const base::Feature kDarkLightMode{"DarkLightMode", base::FEATURE_DISABLED_BY_DEFAULT}; -const base::Feature kDesksRestore{"DesksRestore", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kDisplayAlignAssist{"DisplayAlignAssist", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -233,10 +230,6 @@ return base::FeatureList::IsEnabled(kPipRoundedCorners); } -bool IsDesksRestoreEnabled() { - return base::FeatureList::IsEnabled(kDesksRestore); -} - bool IsSeparateNetworkIconsEnabled() { return base::FeatureList::IsEnabled(kSeparateNetworkIcons); }
diff --git a/ash/public/cpp/ash_features.h b/ash/public/cpp/ash_features.h index eae7324..d7ab211 100644 --- a/ash/public/cpp/ash_features.h +++ b/ash/public/cpp/ash_features.h
@@ -128,10 +128,6 @@ // Enables suppression of Displays notifications other than resolution change. ASH_PUBLIC_EXPORT extern const base::Feature kReduceDisplayNotifications; -// Enables desks restoring, including an active desk and windows belonging to -// them. -ASH_PUBLIC_EXPORT extern const base::Feature kDesksRestore; - // Enables displaying separate network icons for different networks types. // https://crbug.com/902409 ASH_PUBLIC_EXPORT extern const base::Feature kSeparateNetworkIcons; @@ -212,8 +208,6 @@ ASH_PUBLIC_EXPORT bool IsDarkLightModeEnabled(); -ASH_PUBLIC_EXPORT bool IsDesksRestoreEnabled(); - ASH_PUBLIC_EXPORT bool IsEnhancedDeskAnimations(); ASH_PUBLIC_EXPORT bool IsFullRestoreEnabled();
diff --git a/ash/public/cpp/autotest_desks_api.h b/ash/public/cpp/autotest_desks_api.h index 1303b1f..6579f9b 100644 --- a/ash/public/cpp/autotest_desks_api.h +++ b/ash/public/cpp/autotest_desks_api.h
@@ -7,6 +7,7 @@ #include "ash/ash_export.h" #include "base/callback_forward.h" +#include "ui/aura/window.h" namespace ash { @@ -42,6 +43,9 @@ // true otherwise. bool ActivateAdjacentDesksToTargetIndex(int index, base::OnceClosure on_complete); + + // Check whether a window belongs to a desk at |desk_index| or not. + bool IsWindowInDesk(aura::Window* window, int desk_index); }; } // namespace ash
diff --git a/ash/public/cpp/holding_space/holding_space_metrics.cc b/ash/public/cpp/holding_space/holding_space_metrics.cc index 8e93139..50e2572f 100644 --- a/ash/public/cpp/holding_space/holding_space_metrics.cc +++ b/ash/public/cpp/holding_space/holding_space_metrics.cc
@@ -71,6 +71,10 @@ base::UmaHistogramEnumeration("HoldingSpace.Downloads.Action.All", action); } +void RecordFilesAppChipAction(FilesAppChipAction action) { + base::UmaHistogramEnumeration("HoldingSpace.FilesAppChip.Action.All", action); +} + void RecordItemAction(const std::vector<const HoldingSpaceItem*>& items, ItemAction action) { for (const HoldingSpaceItem* item : items) {
diff --git a/ash/public/cpp/holding_space/holding_space_metrics.h b/ash/public/cpp/holding_space/holding_space_metrics.h index 78400646..ac03c54 100644 --- a/ash/public/cpp/holding_space/holding_space_metrics.h +++ b/ash/public/cpp/holding_space/holding_space_metrics.h
@@ -20,8 +20,8 @@ namespace holding_space_metrics { // Enumeration of actions that can be taken on the holding space pod in the -// shelf. Note that these values are persisted to histograms so existing values -// should remain unchanged and new values should be added to the end. +// shelf. These values are persisted to logs. Entries should not be renumbered +// and numeric values should never be reused. enum class PodAction { // kClick (Deprecated) = 0, kShowBubble = 1, @@ -38,8 +38,8 @@ ASH_PUBLIC_EXPORT void RecordPodAction(PodAction action); // Enumeration of actions that can be taken on the holding space downloads -// button. Note that these values are persisted to histograms so existing -// values should remain unchanged and new values should be added to the end. +// button. These values are persisted to logs. Entries should not be renumbered +// and numeric values should never be reused. enum class DownloadsAction { kClick = 0, kMaxValue = kClick, @@ -48,9 +48,20 @@ // Records the specified `action` taken on the holding space downloads header. ASH_PUBLIC_EXPORT void RecordDownloadsAction(DownloadsAction action); -// Enumeration of actions that can be taken on holding space items. Note that -// these values are persisted to histograms so existing values should remain -// unchanged and new values should be added to the end. +// Enumeration of actions that can be taken on the holding space Files app chip. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class FilesAppChipAction { + kClick = 0, + kMaxValue = kClick, +}; + +// Records the specified `action` taken on the holding space Files app chip. +ASH_PUBLIC_EXPORT void RecordFilesAppChipAction(FilesAppChipAction action); + +// Enumeration of actions that can be taken on holding space items. These values +// are persisted to logs. Entries should not be renumbered and numeric values +// should never be reused. enum class ItemAction { kCopy = 0, kDrag = 1,
diff --git a/ash/services/recording/public/mojom/recording_service.mojom b/ash/services/recording/public/mojom/recording_service.mojom index f53cbea..8ec490d 100644 --- a/ash/services/recording/public/mojom/recording_service.mojom +++ b/ash/services/recording/public/mojom/recording_service.mojom
@@ -8,6 +8,7 @@ import "services/audio/public/mojom/stream_factory.mojom"; import "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom"; import "services/viz/public/mojom/compositing/frame_sink_id.mojom"; +import "services/viz/public/mojom/compositing/subtree_capture_id.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; // Defines the interface for the recording service client (e.g. ash), which @@ -30,7 +31,7 @@ // Defines the interface of the recording service which is implemented by // |recording::RecordingService| and runs in its own utility process. It is -// launched by the process on which the |RecordingServiceClient| resides, and is +// launched by the Ash on which the |RecordingServiceClient| resides, and is // used to perform audio/video recording of the whole screen, a partial region // of it, or an individual window. The service captures, encodes, and muxes the // audio and video frames, and sends the WebM muxed video chunks to the client. @@ -55,7 +56,14 @@ viz.mojom.FrameSinkId frame_sink_id, gfx.mojom.Size video_size); - // Starts a recording of a window which has the given |frame_sink_id|. + // Starts a recording of a window. If this window has a valid |frame_sink_id|, + // and submits its own compositor frames independently, then + // |subtree_capture_id| can be default-constructed and won't be used. + // Otherwise, for windows that don't submit compositor frames (e.g. non-root + // windows), the given |frame_sink_id| must be of the root window they're + // descendant from, and they must be made capturable by tagging the with a + // valid |subtree_capture_id| before calling this (see + // aura::Window::MakeWindowCapturable()). // |initial_video_size| and |max_video_size| specify a range of acceptable // capture resolutions in DIPs. The resolution of the output will adapt // dynamically as the window being recorded gets resized by the end user (e.g. @@ -68,6 +76,7 @@ pending_remote<viz.mojom.FrameSinkVideoCapturer> video_capturer, pending_remote<audio.mojom.StreamFactory>? audio_stream_factory, viz.mojom.FrameSinkId frame_sink_id, + viz.mojom.SubtreeCaptureId subtree_capture_id, gfx.mojom.Size initial_video_size, gfx.mojom.Size max_video_size);
diff --git a/ash/services/recording/recording_service.cc b/ash/services/recording/recording_service.cc index 907d5e7ce..62082cd 100644 --- a/ash/services/recording/recording_service.cc +++ b/ash/services/recording/recording_service.cc
@@ -96,6 +96,7 @@ mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer, mojo::PendingRemote<audio::mojom::StreamFactory> audio_stream_factory, const viz::FrameSinkId& frame_sink_id, + const viz::SubtreeCaptureId& subtree_capture_id, const gfx::Size& initial_video_size, const gfx::Size& max_video_size) { DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_); @@ -105,7 +106,8 @@ StartNewRecording(std::move(client), std::move(video_capturer), std::move(audio_stream_factory), VideoCaptureParams::CreateForWindowCapture( - frame_sink_id, initial_video_size, max_video_size)); + frame_sink_id, subtree_capture_id, initial_video_size, + max_video_size)); } void RecordingService::RecordRegion(
diff --git a/ash/services/recording/recording_service.h b/ash/services/recording/recording_service.h index 79f8dc6e7..d529b19f 100644 --- a/ash/services/recording/recording_service.h +++ b/ash/services/recording/recording_service.h
@@ -53,6 +53,7 @@ mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer, mojo::PendingRemote<audio::mojom::StreamFactory> audio_stream_factory, const viz::FrameSinkId& frame_sink_id, + const viz::SubtreeCaptureId& subtree_capture_id, const gfx::Size& initial_video_size, const gfx::Size& max_video_size) override; void RecordRegion(
diff --git a/ash/services/recording/video_capture_params.cc b/ash/services/recording/video_capture_params.cc index e3c52d6..cb9ba0b 100644 --- a/ash/services/recording/video_capture_params.cc +++ b/ash/services/recording/video_capture_params.cc
@@ -7,6 +7,7 @@ #include "ash/services/recording/recording_service_constants.h" #include "base/check.h" #include "base/time/time.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "media/base/video_types.h" #include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h" #include "ui/gfx/geometry/rect.h" @@ -23,7 +24,8 @@ public: FullscreenCaptureParams(viz::FrameSinkId frame_sink_id, const gfx::Size& video_size) - : VideoCaptureParams(frame_sink_id), video_size_(video_size) {} + : VideoCaptureParams(frame_sink_id, viz::SubtreeCaptureId()), + video_size_(video_size) {} FullscreenCaptureParams(const FullscreenCaptureParams&) = delete; FullscreenCaptureParams& operator=(const FullscreenCaptureParams&) = delete; ~FullscreenCaptureParams() override = default; @@ -49,9 +51,10 @@ class WindowCaptureParams : public VideoCaptureParams { public: WindowCaptureParams(viz::FrameSinkId frame_sink_id, + viz::SubtreeCaptureId subtree_capture_id, const gfx::Size& initial_video_size, const gfx::Size& max_video_size) - : VideoCaptureParams(frame_sink_id), + : VideoCaptureParams(frame_sink_id, subtree_capture_id), initial_video_size_(initial_video_size), max_video_size_(max_video_size) {} WindowCaptureParams(const WindowCaptureParams&) = delete; @@ -82,7 +85,7 @@ RegionCaptureParams(viz::FrameSinkId frame_sink_id, const gfx::Size& full_capture_size, const gfx::Rect& crop_region) - : VideoCaptureParams(frame_sink_id), + : VideoCaptureParams(frame_sink_id, viz::SubtreeCaptureId()), full_capture_size_(full_capture_size), crop_region_(crop_region) {} RegionCaptureParams(const RegionCaptureParams&) = delete; @@ -125,10 +128,11 @@ // static std::unique_ptr<VideoCaptureParams> VideoCaptureParams::CreateForWindowCapture( viz::FrameSinkId frame_sink_id, + viz::SubtreeCaptureId subtree_capture_id, const gfx::Size& initial_video_size, const gfx::Size& max_video_size) { return std::make_unique<WindowCaptureParams>( - frame_sink_id, initial_video_size, max_video_size); + frame_sink_id, subtree_capture_id, initial_video_size, max_video_size); } // static @@ -149,7 +153,7 @@ // TODO(afakhry): Discuss with //media/ team the implications of color space // conversions. capturer->SetFormat(media::PIXEL_FORMAT_I420, kColorSpace); - capturer->ChangeTarget(frame_sink_id_); + capturer->ChangeTarget(frame_sink_id_, subtree_capture_id_); } gfx::Rect VideoCaptureParams::GetVideoFrameVisibleRect( @@ -157,8 +161,9 @@ return original_frame_visible_rect; } -VideoCaptureParams::VideoCaptureParams(viz::FrameSinkId frame_sink_id) - : frame_sink_id_(frame_sink_id) { +VideoCaptureParams::VideoCaptureParams(viz::FrameSinkId frame_sink_id, + viz::SubtreeCaptureId subtree_capture_id) + : frame_sink_id_(frame_sink_id), subtree_capture_id_(subtree_capture_id) { DCHECK(frame_sink_id_.is_valid()); }
diff --git a/ash/services/recording/video_capture_params.h b/ash/services/recording/video_capture_params.h index 0559b61..3726f345 100644 --- a/ash/services/recording/video_capture_params.h +++ b/ash/services/recording/video_capture_params.h
@@ -8,6 +8,7 @@ #include <memory> #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom-forward.h" @@ -35,14 +36,19 @@ viz::FrameSinkId frame_sink_id, const gfx::Size& video_size); - // Returns a capture params instance for a recording of a window which has - // the given |frame_sink_id| and its initial size is given as + // Returns a capture params instance for a recording of a window. The given + //|frame_sink_id| is either of that window (if it submits compositor frames + // independently), or of the root window it descends from (if it doesn't + // submit its compositor frames). In the latter case, the window must be + // identifiable by a valid |subtree_capture_id| (created by calling + // aura::window::MakeWindowCapturable() before recording starts). // |initial_video_size| and |max_video_size| specify a range of acceptable // capture resolutions in DIPs. The resolution of the output will adapt // dynamically as the window being recorded gets resized by the end user (e.g. // resized, maximized, fullscreened, ... etc.). |frame_sink_id| must be valid. static std::unique_ptr<VideoCaptureParams> CreateForWindowCapture( viz::FrameSinkId frame_sink_id, + viz::SubtreeCaptureId subtree_capture_id, const gfx::Size& initial_video_size, const gfx::Size& max_video_size); @@ -73,9 +79,11 @@ virtual gfx::Size GetCaptureSize() const = 0; protected: - explicit VideoCaptureParams(viz::FrameSinkId frame_sink_id); + explicit VideoCaptureParams(viz::FrameSinkId frame_sink_id, + viz::SubtreeCaptureId subtree_capture_id); const viz::FrameSinkId frame_sink_id_; + const viz::SubtreeCaptureId subtree_capture_id_; }; } // namespace recording
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h index 906b82d..63479ca 100644 --- a/ash/shell_delegate.h +++ b/ash/shell_delegate.h
@@ -111,6 +111,9 @@ virtual media_session::MediaSessionService* GetMediaSessionService(); virtual void OpenKeyboardShortcutHelpPage() const {} + + // Returns if window browser sessions are restoring. + virtual bool IsSessionRestoreInProgress() const = 0; }; } // namespace ash
diff --git a/ash/system/holding_space/holding_space_tray_unittest.cc b/ash/system/holding_space/holding_space_tray_unittest.cc index bc8a0f5..a07debaf 100644 --- a/ash/system/holding_space/holding_space_tray_unittest.cc +++ b/ash/system/holding_space/holding_space_tray_unittest.cc
@@ -13,6 +13,7 @@ #include "ash/public/cpp/holding_space/holding_space_controller.h" #include "ash/public/cpp/holding_space/holding_space_image.h" #include "ash/public/cpp/holding_space/holding_space_item.h" +#include "ash/public/cpp/holding_space/holding_space_metrics.h" #include "ash/public/cpp/holding_space/holding_space_model.h" #include "ash/public/cpp/holding_space/holding_space_prefs.h" #include "ash/public/cpp/holding_space/holding_space_test_api.h" @@ -21,6 +22,7 @@ #include "base/files/file_path.h" #include "base/strings/strcat.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/gfx/image/image_skia.h" @@ -1436,9 +1438,22 @@ pinned_files_bubble->GetViewByID(kHoldingSpaceFilesAppChipId); ASSERT_TRUE(files_app_chip); + // Prior to being acted upon by the user, there should be no events logged to + // the Files app chip histogram. + base::HistogramTester histogram_tester; + histogram_tester.ExpectBucketCount( + "HoldingSpace.FilesAppChip.Action.All", + holding_space_metrics::FilesAppChipAction::kClick, 0); + // Click the chip and expect a call to open the Files app. EXPECT_CALL(*client(), OpenMyFiles); Click(files_app_chip, 0); + + // After having been acted upon by the user, there should be a single click + // event logged to the Files app chip histogram. + histogram_tester.ExpectBucketCount( + "HoldingSpace.FilesAppChip.Action.All", + holding_space_metrics::FilesAppChipAction::kClick, 1); } // User should be able to launch selected holding space items by pressing the
diff --git a/ash/system/holding_space/pinned_files_section.cc b/ash/system/holding_space/pinned_files_section.cc index 20da025..066514e 100644 --- a/ash/system/holding_space/pinned_files_section.cc +++ b/ash/system/holding_space/pinned_files_section.cc
@@ -8,6 +8,7 @@ #include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_controller.h" #include "ash/public/cpp/holding_space/holding_space_item.h" +#include "ash/public/cpp/holding_space/holding_space_metrics.h" #include "ash/public/cpp/holding_space/holding_space_prefs.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/session/session_controller_impl.h" @@ -119,6 +120,9 @@ } void OnPressed(const ui::Event& event) { + holding_space_metrics::RecordFilesAppChipAction( + holding_space_metrics::FilesAppChipAction::kClick); + HoldingSpaceController::Get()->client()->OpenMyFiles(base::DoNothing()); } };
diff --git a/ash/system/power/power_button_controller.cc b/ash/system/power/power_button_controller.cc index 7fc5df0..0c3ccfa 100644 --- a/ash/system/power/power_button_controller.cc +++ b/ash/system/power/power_button_controller.cc
@@ -391,7 +391,7 @@ } void PowerButtonController::OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) { + const AccelerometerUpdate& update) { DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kAshEnableTabletMode));
diff --git a/ash/system/power/power_button_controller.h b/ash/system/power/power_button_controller.h index d53f66d..ee660aa 100644 --- a/ash/system/power/power_button_controller.h +++ b/ash/system/power/power_button_controller.h
@@ -138,8 +138,7 @@ // TODO(minch): Remove this if/when all applicable devices expose a tablet // mode switch: https://crbug.com/798646. // AccelerometerReader::Observer: - void OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) override; + void OnAccelerometerUpdated(const AccelerometerUpdate& update) override; // BacklightsForcedOffSetter::Observer: void OnBacklightsForcedOffChanged(bool forced_off) override;
diff --git a/ash/test_shell_delegate.cc b/ash/test_shell_delegate.cc index 573fe4da..a508bd2 100644 --- a/ash/test_shell_delegate.cc +++ b/ash/test_shell_delegate.cc
@@ -78,4 +78,12 @@ return std::make_unique<TestNearbyShareDelegate>(); } +bool TestShellDelegate::IsSessionRestoreInProgress() const { + return session_restore_in_progress_; +} + +void TestShellDelegate::SetSessionRestoreInProgress(bool in_progress) { + session_restore_in_progress_ = in_progress; +} + } // namespace ash
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h index 1e5ae387..b288e27 100644 --- a/ash/test_shell_delegate.h +++ b/ash/test_shell_delegate.h
@@ -47,9 +47,11 @@ override; std::unique_ptr<NearbyShareDelegate> CreateNearbyShareDelegate( NearbyShareController* controller) const override; + bool IsSessionRestoreInProgress() const override; void SetCanGoBack(bool can_go_back); void SetShouldWaitForTouchAck(bool should_wait_for_touch_ack); + void SetSessionRestoreInProgress(bool in_progress); private: // True if the current top window can go back. @@ -64,6 +66,9 @@ // description. bool should_wait_for_touch_ack_ = false; + // True if window browser sessions are restoring. + bool session_restore_in_progress_ = false; + MultiDeviceSetupBinder multidevice_setup_binder_; DISALLOW_COPY_AND_ASSIGN(TestShellDelegate);
diff --git a/ash/wm/always_on_top_controller.cc b/ash/wm/always_on_top_controller.cc index ae420df0..5ed17710 100644 --- a/ash/wm/always_on_top_controller.cc +++ b/ash/wm/always_on_top_controller.cc
@@ -4,8 +4,10 @@ #include "ash/wm/always_on_top_controller.h" +#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_properties.h" +#include "ash/wm/desks/desks_controller.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/window_state.h" #include "ash/wm/workspace/workspace_layout_manager.h" @@ -54,6 +56,15 @@ // TODO(afakhry): Do we need to worry about the context of |window| here? Or // is it safe to assume that |window| should always be parented to the // active desks' container. + int window_workspace = + window->GetProperty(aura::client::kWindowWorkspaceKey); + if (features::IsBentoEnabled() && + window_workspace != aura::client::kUnassignedWorkspace) { + auto* desk_container = + DesksController::Get()->GetDeskContainer(root, window_workspace); + if (desk_container) + return desk_container; + } return desks_util::GetActiveDeskContainerForRoot(root); } if (window->parent() && WindowState::Get(window)->IsPip())
diff --git a/ash/wm/desks/autotest_desks_api.cc b/ash/wm/desks/autotest_desks_api.cc index ef0cc64..d9f15c6 100644 --- a/ash/wm/desks/autotest_desks_api.cc +++ b/ash/wm/desks/autotest_desks_api.cc
@@ -201,4 +201,10 @@ return true; } +bool AutotestDesksApi::IsWindowInDesk(aura::Window* window, int desk_index) { + aura::Window* desk_container = DesksController::Get()->GetDeskContainer( + window->GetRootWindow(), desk_index); + return desk_container->Contains(window); +} + } // namespace ash
diff --git a/ash/wm/desks/desk.cc b/ash/wm/desks/desk.cc index ff2cf2e1a..df0ba9b 100644 --- a/ash/wm/desks/desk.cc +++ b/ash/wm/desks/desk.cc
@@ -8,9 +8,11 @@ #include <utility> #include "ash/public/cpp/app_types.h" +#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/window_properties.h" #include "ash/shell.h" +#include "ash/wm/desks/desks_controller.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/window_positioner.h" @@ -23,6 +25,7 @@ #include "base/containers/adapters.h" #include "base/containers/contains.h" #include "base/stl_util.h" +#include "chromeos/ui/base/window_properties.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window_tracker.h" #include "ui/display/screen.h" @@ -197,6 +200,13 @@ // there in the first place. if (!window->GetProperty(kHideInDeskMiniViewKey)) NotifyContentChanged(); + + // Update the window's workspace to this parent desk. + if (features::IsBentoEnabled() && !is_desk_being_removed_) { + auto* desks_controller = DesksController::Get(); + window->SetProperty(aura::client::kWindowWorkspaceKey, + desks_controller->GetDeskIndex(this)); + } } void Desk::RemoveWindowFromDesk(aura::Window* window) { @@ -415,6 +425,10 @@ UpdateBackdropController(GetDeskContainerForRoot(root)); } +void Desk::SetDeskBeingRemoved() { + is_desk_being_removed_ = true; +} + void Desk::MoveWindowToDeskInternal(aura::Window* window, Desk* target_desk, aura::Window* target_root) {
diff --git a/ash/wm/desks/desk.h b/ash/wm/desks/desk.h index 2e07656..e2d7608 100644 --- a/ash/wm/desks/desk.h +++ b/ash/wm/desks/desk.h
@@ -124,6 +124,10 @@ // visibility on the containers (on all roots) associated with this desk. void UpdateDeskBackdrops(); + // Set desk being removed to avoid unwanted action such as `GetDeskIndex()` + // when desk is already removed from |desks_| in DesksController. + void SetDeskBeingRemoved(); + private: void MoveWindowToDeskInternal(aura::Window* window, Desk* target_desk, @@ -172,6 +176,9 @@ // are set by the user don't change. bool is_name_set_by_user_ = false; + // True if the desk is being removed. + bool is_desk_being_removed_ = false; + DISALLOW_COPY_AND_ASSIGN(Desk); };
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index c02302f..83c5500 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -567,6 +567,13 @@ return -1; } +aura::Window* DesksController::GetDeskContainer(aura::Window* target_root, + int desk_index) { + if (desk_index < 0 || desk_index >= int{desks_.size()}) + return nullptr; + return desks_[desk_index]->GetDeskContainerForRoot(target_root); +} + bool DesksController::BelongsToActiveDesk(aura::Window* window) { return desks_util::BelongsToActiveDesk(window); } @@ -607,6 +614,14 @@ if (AreDesksBeingModified()) return; + // Browser session restore opens all restored windows, so it activates + // every single window and activates the parent desk. Therefore, this check + // prevents repetitive desk activation. Moreover, when Bento desks restore is + // enabled, it avoid switching desk back and forth when windows are restored + // to different desks. + if (Shell::Get()->shell_delegate()->IsSessionRestoreInProgress()) + return; + if (!gaining_active) return; @@ -705,7 +720,7 @@ observer.OnDeskActivationChanged(active_desk_, old_active); // Only update active desk prefs when a primary user switches a desk. - if (features::IsDesksRestoreEnabled() && + if (features::IsBentoEnabled() && shell->session_controller()->IsUserPrimary()) { desks_restore_util::UpdatePrimaryUserActiveDeskPrefs( GetDeskIndex(active_desk_)); @@ -728,6 +743,7 @@ // Keep the removed desk alive until the end of this function. std::unique_ptr<Desk> removed_desk = std::move(*iter); + removed_desk->SetDeskBeingRemoved(); DCHECK_EQ(removed_desk.get(), desk); auto iter_after = desks_.erase(iter);
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h index 90840eb..add52fc 100644 --- a/ash/wm/desks/desks_controller.h +++ b/ash/wm/desks/desks_controller.h
@@ -171,6 +171,10 @@ int GetDeskIndex(const Desk* desk) const; + // Gets the container of the desk at |desk_index| in a specific screen with a + // |target_root|. If desk_index is invalid, it returns nullptr. + aura::Window* GetDeskContainer(aura::Window* target_root, int desk_index); + // DesksHelper: bool BelongsToActiveDesk(aura::Window* window) override; int GetActiveDeskIndex() const override;
diff --git a/ash/wm/desks/desks_restore_util.cc b/ash/wm/desks/desks_restore_util.cc index c18fe07..03ac2c6e 100644 --- a/ash/wm/desks/desks_restore_util.cc +++ b/ash/wm/desks/desks_restore_util.cc
@@ -46,7 +46,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { constexpr int kDefaultActiveDeskIndex = 0; registry->RegisterListPref(prefs::kDesksNamesList); - if (features::IsDesksRestoreEnabled()) { + if (features::IsBentoEnabled()) { registry->RegisterIntegerPref(prefs::kDesksActiveDesk, kDefaultActiveDeskIndex); } @@ -91,7 +91,7 @@ } // Restore an active desk for the primary user. - if (features::IsDesksRestoreEnabled()) { + if (features::IsBentoEnabled()) { const int active_desk_index = primary_user_prefs->GetInteger(prefs::kDesksActiveDesk); @@ -131,7 +131,7 @@ } void UpdatePrimaryUserActiveDeskPrefs(int active_desk_index) { - DCHECK(features::IsDesksRestoreEnabled()); + DCHECK(features::IsBentoEnabled()); DCHECK(Shell::Get()->session_controller()->IsUserPrimary()); DCHECK(IsValidDeskIndex(active_desk_index)); if (g_pause_desks_prefs_updates)
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc index dfc6545..6b584c45 100644 --- a/ash/wm/desks/desks_unittests.cc +++ b/ash/wm/desks/desks_unittests.cc
@@ -2832,7 +2832,7 @@ // AshTestBase: void SetUp() override { if (GetParam()) - scoped_feature_list_.InitAndEnableFeature(features::kDesksRestore); + scoped_feature_list_.InitAndEnableFeature(features::kBento); NoSessionAshTestBase::SetUp(); TestSessionControllerClient* session_controller = @@ -2871,7 +2871,7 @@ bool teleported) override {} void OnTransitionUserShelfToNewAccount() override {} - bool IsDesksRestoreEnabled() const { return GetParam(); } + bool IsBentoEnabled() const { return GetParam(); } AccountId GetUser1AccountId() const { return AccountId::FromUserEmail(kUser1Email); @@ -3089,7 +3089,7 @@ InitPrefsWithDesksRestoreData(user_1_prefs()); // Set the primary user1's active desk prefs to kUser1StoredActiveDesk. - if (IsDesksRestoreEnabled()) + if (IsBentoEnabled()) user_1_prefs()->SetInteger(prefs::kDesksActiveDesk, kUser1StoredActiveDesk); SimulateUserLogin(GetUser1AccountId()); @@ -3110,7 +3110,7 @@ }; verify_desks("Before switching users"); - if (IsDesksRestoreEnabled()) { + if (IsBentoEnabled()) { // The primary user1 should restore the saved active desk from its pref. EXPECT_EQ(desks[kUser1StoredActiveDesk]->container_id(), desks_util::GetActiveDeskContainerId()); @@ -3120,7 +3120,7 @@ // the time when the first user signs in. SwitchActiveUser(GetUser2AccountId()); verify_desks("After switching users"); - if (IsDesksRestoreEnabled()) { + if (IsBentoEnabled()) { // The secondary user2 should start with a default active desk. EXPECT_EQ(desks[kDefaultActiveDesk]->container_id(), desks_util::GetActiveDeskContainerId());
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.cc b/ash/wm/tablet_mode/tablet_mode_controller.cc index 088ddae..8e6ad19a 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller.cc
@@ -628,7 +628,7 @@ } void TabletModeController::OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) { + const AccelerometerUpdate& update) { if (ec_lid_angle_driver_status_ == ECLidAngleDriverStatus::UNKNOWN) { ec_lid_angle_driver_status_ = AccelerometerReader::GetInstance()->GetECLidAngleDriverStatus(); @@ -649,8 +649,8 @@ } have_seen_accelerometer_data_ = true; - can_detect_lid_angle_ = update->has(ACCELEROMETER_SOURCE_SCREEN) && - update->has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD); + can_detect_lid_angle_ = update.has(ACCELEROMETER_SOURCE_SCREEN) && + update.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD); if (!can_detect_lid_angle_) { if (record_lid_angle_timer_.IsRunning()) record_lid_angle_timer_.Stop(); @@ -665,9 +665,9 @@ // Whether or not we enter tablet mode affects whether we handle screen // rotation, so determine whether to enter tablet mode first. - if (update->IsReadingStable(ACCELEROMETER_SOURCE_SCREEN) && - update->IsReadingStable(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) && - IsAngleBetweenAccelerometerReadingsStable(*update)) { + if (update.IsReadingStable(ACCELEROMETER_SOURCE_SCREEN) && + update.IsReadingStable(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) && + IsAngleBetweenAccelerometerReadingsStable(update)) { // update.has(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD) // Ignore the reading if it appears unstable. The reading is considered // unstable if it deviates too much from gravity and/or the magnitude of the @@ -899,11 +899,11 @@ } void TabletModeController::HandleHingeRotation( - scoped_refptr<const AccelerometerUpdate> update) { + const AccelerometerUpdate& update) { static const gfx::Vector3dF hinge_vector(1.0f, 0.0f, 0.0f); gfx::Vector3dF base_reading = - update->GetVector(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD); - gfx::Vector3dF lid_reading = update->GetVector(ACCELEROMETER_SOURCE_SCREEN); + update.GetVector(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD); + gfx::Vector3dF lid_reading = update.GetVector(ACCELEROMETER_SOURCE_SCREEN); // As the hinge approaches a vertical angle, the base and lid accelerometers // approach the same values making any angle calculations highly inaccurate.
diff --git a/ash/wm/tablet_mode/tablet_mode_controller.h b/ash/wm/tablet_mode/tablet_mode_controller.h index 96069a9..056908d 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller.h +++ b/ash/wm/tablet_mode/tablet_mode_controller.h
@@ -147,8 +147,7 @@ void OnChromeTerminating() override; // AccelerometerReader::Observer: - void OnAccelerometerUpdated( - scoped_refptr<const AccelerometerUpdate> update) override; + void OnAccelerometerUpdated(const AccelerometerUpdate& update) override; // chromeos::PowerManagerClient::Observer: void LidEventReceived(chromeos::PowerManagerClient::LidState state, @@ -251,7 +250,7 @@ // If EC cannot handle lid angle calc, browser detects hinge rotation from // base and lid accelerometers and automatically start / stop tablet mode. - void HandleHingeRotation(scoped_refptr<const AccelerometerUpdate> update); + void HandleHingeRotation(const AccelerometerUpdate& update); void OnGetSwitchStates( base::Optional<chromeos::PowerManagerClient::SwitchStates> result);
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_test_api.cc b/ash/wm/tablet_mode/tablet_mode_controller_test_api.cc index aad77ff4..14d2eec 100644 --- a/ash/wm/tablet_mode/tablet_mode_controller_test_api.cc +++ b/ash/wm/tablet_mode/tablet_mode_controller_test_api.cc
@@ -89,18 +89,18 @@ } void TabletModeControllerTestApi::TriggerLidUpdate(const gfx::Vector3dF& lid) { - scoped_refptr<AccelerometerUpdate> update(new AccelerometerUpdate()); - update->Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z()); + AccelerometerUpdate update; + update.Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z()); tablet_mode_controller_->OnAccelerometerUpdated(update); } void TabletModeControllerTestApi::TriggerBaseAndLidUpdate( const gfx::Vector3dF& base, const gfx::Vector3dF& lid) { - scoped_refptr<AccelerometerUpdate> update(new AccelerometerUpdate()); - update->Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, base.x(), base.y(), - base.z()); - update->Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z()); + AccelerometerUpdate update; + update.Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, base.x(), base.y(), + base.z()); + update.Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z()); tablet_mode_controller_->OnAccelerometerUpdated(update); }
diff --git a/ash/wm/window_cycle/window_cycle_controller.cc b/ash/wm/window_cycle/window_cycle_controller.cc index daaf4c2..c2cd008 100644 --- a/ash/wm/window_cycle/window_cycle_controller.cc +++ b/ash/wm/window_cycle/window_cycle_controller.cc
@@ -89,8 +89,6 @@ if (!IsCycling()) StartCycling(); - // TODO(crbug.com/1157100): Handle window highlighting after switching - // alt-tab mode. Step(direction); } @@ -175,15 +173,33 @@ } void WindowCycleController::SetAltTabMode(DesksMruType alt_tab_mode) { - if (alt_tab_mode_ == alt_tab_mode) + if (!IsInteractiveAltTabModeAllowed() || alt_tab_mode_ == alt_tab_mode) return; alt_tab_mode_ = alt_tab_mode; MaybeResetCycleList(); + + is_switching_mode_ = true; + // When user first press alt + tab, `HandleCycleForwardMRU` triggers + // `HandleCycleWindow(WindowCycleController::FORWARD)` since it considers + // the initial tab as forward cycling. Therefore, switching the mode + // should imitate the same forward cycling behavior after the cycle is reset. + HandleCycleWindow(WindowCycleController::FORWARD); + is_switching_mode_ = false; +} + +bool WindowCycleController::IsSwitchingMode() { + return features::IsBentoEnabled() && is_switching_mode_; +} + +bool WindowCycleController::IsInteractiveAltTabModeAllowed() { + return features::IsBentoEnabled() && + Shell::Get()->desks_controller()->GetNumberOfDesks() > 1; } bool WindowCycleController::IsAltTabPerActiveDesk() { - return features::IsBentoEnabled() ? alt_tab_mode_ == kActiveDesk - : features::IsAltTabLimitedToActiveDesk(); + return IsInteractiveAltTabModeAllowed() + ? alt_tab_mode_ == kActiveDesk + : features::IsAltTabLimitedToActiveDesk(); } void WindowCycleController::SaveCurrentActiveDeskAndWindow(
diff --git a/ash/wm/window_cycle/window_cycle_controller.h b/ash/wm/window_cycle/window_cycle_controller.h index 9ff7de3..5f9ebee6 100644 --- a/ash/wm/window_cycle/window_cycle_controller.h +++ b/ash/wm/window_cycle/window_cycle_controller.h
@@ -90,11 +90,22 @@ // Sets alt-tab mode to all desks (default) or active desk. void SetAltTabMode(DesksMruType alt_tab_mode_); - // Checks if alt-tab should be per active desk. If Bento is enabled, alt-tab - // mode depends on users' alt_tab_mode_ selection. Otherwise, it'll default - // to all desk unless LimitAltTabToActiveDesk flag is explicitly enabled. + // Checks if switching between alt-tab mode via the tab slider is allowed. + // Returns true if Bento flag is enabled and users have multiple desks. + bool IsInteractiveAltTabModeAllowed(); + + // Checks if alt-tab should be per active desk. If + // `IsInteractiveAltTabModeAllowed()`, alt-tab mode depends on users' + // |alt_tab_mode_| selection. Otherwise, it'll default to all desk unless + // LimitAltTabToActiveDesk flag is explicitly enabled. bool IsAltTabPerActiveDesk(); + // Returns true while switching the alt-tab mode and Bento flag is enabled. + // This helps `Scroll()` and `Step()` distinguish between pressing tabs and + // switching mode, so they refresh |current_index_| and the highlighted + // window correctly. + bool IsSwitchingMode(); + private: // Gets a list of windows from the currently open windows, removing windows // with transient roots already in the list. The returned list of windows @@ -130,6 +141,9 @@ // TODO(crbug.com/1157105): Store per-desk mode in primary user pref. DesksMruType alt_tab_mode_ = DesksMruType::kAllDesks; + // Tracks whether alt-tab mode is currently switching or not. + bool is_switching_mode_ = false; + DISALLOW_COPY_AND_ASSIGN(WindowCycleController); };
diff --git a/ash/wm/window_cycle/window_cycle_controller_unittest.cc b/ash/wm/window_cycle/window_cycle_controller_unittest.cc index 16b87fb..1aeccbc 100644 --- a/ash/wm/window_cycle/window_cycle_controller_unittest.cc +++ b/ash/wm/window_cycle/window_cycle_controller_unittest.cc
@@ -1386,14 +1386,68 @@ ui::test::EventGenerator* generator_; }; +// Tests that if user uses only one desk, the tab slider and no recent items +// are not shown. Moreover, `SetAltTabMode()` should not change the windows +// list. +TEST_F(ModeSelectionWindowCycleControllerTest, SingleDeskHidesInteractiveMode) { + WindowCycleController* cycle_controller = + Shell::Get()->window_cycle_controller(); + + // Create two windows in the current desk. + auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100)); + auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200)); + auto* desks_controller = DesksController::Get(); + ASSERT_EQ(1u, desks_controller->desks().size()); + + // Alt-tab should contain windows from all desks without any the tab slider + // and no-recent-items view. + cycle_controller->StartCycling(); + EXPECT_TRUE(!GetWindowCycleNoRecentItemsLabel()); + EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk()); + auto cycle_windows = GetWindows(cycle_controller); + EXPECT_EQ(2u, cycle_windows.size()); + EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size()); + const gfx::Rect alttab_bounds_without_tab_slider = + GetWindowCycleListWidget()->GetWindowBoundsInScreen(); + cycle_controller->CompleteCycling(); + + // Create an empty desk_2 and start alt-tab to enter the all-desks mode. + desks_controller->NewDesk(DesksCreationRemovalSource::kButton); + const Desk* desk_2 = desks_controller->desks()[1].get(); + ActivateDesk(desk_2); + EXPECT_EQ(desk_2, desks_controller->active_desk()); + cycle_controller->StartCycling(); + EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk()); + EXPECT_EQ(2u, cycle_windows.size()); + EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size()); + + // Expect mode-switching buttons and no-recent-item label to exist. + EXPECT_FALSE(!GetWindowCycleNoRecentItemsLabel()); + auto tab_slider_buttons = GetWindowCycleTabSliderViews(); + EXPECT_EQ(2u, tab_slider_buttons.size()); + const gfx::Rect alttab_bounds_with_tab_slider = + GetWindowCycleListWidget()->GetWindowBoundsInScreen(); + const int window_cycle_list_y = + GetWindowCycleItemViews()[0]->GetBoundsInScreen().y(); + const gfx::Rect tab_slider_button_bound = + tab_slider_buttons[0]->GetBoundsInScreen(); + // Expect that alt-tab views height is larger due to the tab slider insertion + // and expect that window cycle list is placed below the tab slider. + EXPECT_LT(alttab_bounds_without_tab_slider.height(), + alttab_bounds_with_tab_slider.height()); + EXPECT_LT(tab_slider_button_bound.y() + tab_slider_button_bound.height(), + window_cycle_list_y); + + DeskSwitchAnimationWaiter waiter; + cycle_controller->CompleteCycling(); + waiter.Wait(); +} + // Tests that alt-tab shows all windows in an all-desk mode by default and // shows only windows in the current desk in a current-desk mode. Switching // between two modes should refresh the window list, while re-entering alt-tab // should display the most recently selected mode. -// -// Flaky: crbug.com/1163577 -TEST_F(ModeSelectionWindowCycleControllerTest, - DISABLED_CycleShowsWindowsPerMode) { +TEST_F(ModeSelectionWindowCycleControllerTest, CycleShowsWindowsPerMode) { WindowCycleController* cycle_controller = Shell::Get()->window_cycle_controller(); @@ -1454,7 +1508,10 @@ cycle_windows = GetWindows(cycle_controller); EXPECT_EQ(5u, cycle_windows.size()); EXPECT_EQ(cycle_windows.size(), GetWindowCycleItemViews().size()); + + DeskSwitchAnimationWaiter waiter; cycle_controller->CompleteCycling(); + waiter.Wait(); generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE); } @@ -1543,4 +1600,132 @@ waiter.Wait(); } +// Tests that switching between modes correctly reset the alt-tab-highlighted +// window to the second most recently used window, i.e. the next window to tab +// into from the currently used window. Since the window cycle list is ordered +// by MRU, such window is therefore the second window in the MRU list. +TEST_F(ModeSelectionWindowCycleControllerTest, + SwitchingModeUpdatesWindowHighlight) { + WindowCycleController* cycle_controller = + Shell::Get()->window_cycle_controller(); + + // Create two windows for desk1 and three windows for desk2 in the reversed + // order of the most recently active window. + auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 100)); + auto win3 = CreateAppWindow(gfx::Rect(50, 50, 200, 200)); + auto* desks_controller = DesksController::Get(); + desks_controller->NewDesk(DesksCreationRemovalSource::kButton); + ASSERT_EQ(2u, desks_controller->desks().size()); + const Desk* desk_2 = desks_controller->desks()[1].get(); + ActivateDesk(desk_2); + EXPECT_EQ(desk_2, desks_controller->active_desk()); + auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200)); + auto win1 = CreateAppWindow(gfx::Rect(10, 30, 400, 200)); + auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200)); + + // Enter the all-desk mode by default with the window order [0, 1, 2, 3 ,4]. + cycle_controller->StartCycling(); + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + + EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk()); + auto cycle_windows = GetWindows(cycle_controller); + // The window list is MRU ordered. + EXPECT_EQ(win0.get(), cycle_windows[0]); + EXPECT_EQ(win1.get(), cycle_windows[1]); + EXPECT_EQ(win2.get(), cycle_windows[2]); + EXPECT_EQ(win3.get(), cycle_windows[3]); + EXPECT_EQ(win4.get(), cycle_windows[4]); + // Alt-Tab should highlight the second most recently used window, which is + // the second window in the MRU list, win1. + EXPECT_EQ(win1.get(), GetTargetWindow()); + + // Step to win2 and win3, so we are now select a window in a non-active desk. + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + EXPECT_EQ(win2.get(), GetTargetWindow()); + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + EXPECT_EQ(win3.get(), GetTargetWindow()); + + // Switching from the all-desks mode, which highlights a non-current-desk + // window to the current-desk mode [0, 1, 2] should resolve the highlight + // correctly to win1, the second window in the cycle list. + SwitchPerDeskAltTabMode(true); + EXPECT_EQ(win1.get(), GetTargetWindow()); + EXPECT_EQ(win1.get(), cycle_windows[1]); + // Step to win2. + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + EXPECT_EQ(win2.get(), GetTargetWindow()); + + // Switching back to the all-desk mode should reset highlight to win1 again. + SwitchPerDeskAltTabMode(false); + EXPECT_EQ(win1.get(), GetTargetWindow()); + cycle_controller->CompleteCycling(); +} + +// Similar to `SwitchingModeUpdatesWindowHighlight`, tests that switching the +// alt-tab mode updates the highlighted window to the first window (most +// recently used) in the special case where all windows are minimized. +// When they are minimized, cycling forward should help unminimize the most +// recently used window rather than trying to open the second most recently +// used window. +TEST_F(ModeSelectionWindowCycleControllerTest, + SwitchingModeUpdatesMinimizedWindowHighlight) { + WindowCycleController* cycle_controller = + Shell::Get()->window_cycle_controller(); + + // Create two windows for desk1 and three windows for desk2 in the reversed + // order of the most recently active window. + auto win4 = CreateAppWindow(gfx::Rect(0, 0, 250, 100)); + auto win3 = CreateAppWindow(gfx::Rect(50, 50, 200, 200)); + auto* desks_controller = DesksController::Get(); + desks_controller->NewDesk(DesksCreationRemovalSource::kButton); + ASSERT_EQ(2u, desks_controller->desks().size()); + const Desk* desk_2 = desks_controller->desks()[1].get(); + ActivateDesk(desk_2); + EXPECT_EQ(desk_2, desks_controller->active_desk()); + auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200)); + auto win1 = CreateAppWindow(gfx::Rect(10, 30, 400, 200)); + auto win0 = CreateAppWindow(gfx::Rect(10, 30, 400, 200)); + + // Minimize all windows to test this special case. + WindowState::Get(win4.get())->Minimize(); + WindowState::Get(win3.get())->Minimize(); + WindowState::Get(win2.get())->Minimize(); + WindowState::Get(win1.get())->Minimize(); + WindowState::Get(win0.get())->Minimize(); + EXPECT_FALSE(WindowState::Get(win0.get())->IsActive()); + EXPECT_FALSE(WindowState::Get(win1.get())->IsActive()); + EXPECT_FALSE(WindowState::Get(win2.get())->IsActive()); + EXPECT_FALSE(WindowState::Get(win3.get())->IsActive()); + EXPECT_FALSE(WindowState::Get(win4.get())->IsActive()); + + // Enter the all-desk mode by default with the window order [0, 1, 2, 3 ,4]. + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + EXPECT_FALSE(cycle_controller->IsAltTabPerActiveDesk()); + auto cycle_windows = GetWindows(cycle_controller); + EXPECT_EQ(5u, GetWindowCycleItemViews().size()); + // The window list is MRU ordered. + EXPECT_EQ(win0.get(), cycle_windows[0]); + EXPECT_EQ(win1.get(), cycle_windows[1]); + EXPECT_EQ(win2.get(), cycle_windows[2]); + EXPECT_EQ(win3.get(), cycle_windows[3]); + EXPECT_EQ(win4.get(), cycle_windows[4]); + // Step forward a few times and switch to all-desks mode. This should + // highlight win0, the first window in the current-desk cycle list. + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + SwitchPerDeskAltTabMode(true); + EXPECT_EQ(3u, GetWindowCycleItemViews().size()); + EXPECT_EQ(win0.get(), GetTargetWindow()); + EXPECT_EQ(win0.get(), cycle_windows[0]); + + // Stepping to win1 and switching back to the all-desk mode should reset + // a highlight to win0 again. + cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD); + EXPECT_EQ(win1.get(), GetTargetWindow()); + SwitchPerDeskAltTabMode(false); + EXPECT_EQ(5u, GetWindowCycleItemViews().size()); + EXPECT_EQ(win0.get(), GetTargetWindow()); + cycle_controller->CompleteCycling(); +} + } // namespace ash
diff --git a/ash/wm/window_cycle/window_cycle_list.cc b/ash/wm/window_cycle/window_cycle_list.cc index f00ec39..4dc725a 100644 --- a/ash/wm/window_cycle/window_cycle_list.cc +++ b/ash/wm/window_cycle/window_cycle_list.cc
@@ -279,7 +279,9 @@ layer->SetBackdropFilterQuality(kBackgroundBlurQuality); layer->SetName("WindowCycleView"); - if (features::IsBentoEnabled()) { + if (Shell::Get() + ->window_cycle_controller() + ->IsInteractiveAltTabModeAllowed()) { tab_slider_container_ = AddChildView(std::make_unique<WindowCycleTabSlider>()); @@ -312,7 +314,9 @@ views::BoxLayout* layout = mirror_container_->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, - gfx::Insets(features::IsBentoEnabled() + gfx::Insets(Shell::Get() + ->window_cycle_controller() + ->IsInteractiveAltTabModeAllowed() ? kMirrorContainerVerticalPaddingDp : kInsideBorderVerticalPaddingDp, kInsideBorderHorizontalPaddingDp, @@ -347,14 +351,13 @@ void UpdateWindows(const WindowCycleList::WindowList& windows) { const bool no_windows = windows.empty(); - if (features::IsBentoEnabled()) { + if (Shell::Get() + ->window_cycle_controller() + ->IsInteractiveAltTabModeAllowed()) { no_recent_items_label_->SetVisible(no_windows); } if (no_windows) return; - - if (features::IsBentoEnabled()) - no_recent_items_label_->SetVisible(false); for (auto* window : windows) { auto* view = mirror_container_->AddChildView( std::make_unique<WindowCycleItemView>(window)); @@ -449,7 +452,9 @@ // views::WidgetDelegateView: gfx::Size CalculatePreferredSize() const override { gfx::Size size = mirror_container_->GetPreferredSize(); - if (features::IsBentoEnabled()) { + if (Shell::Get() + ->window_cycle_controller() + ->IsInteractiveAltTabModeAllowed()) { size.Enlarge(0, tab_slider_container_->GetPreferredSize().height() + kTabSliderContainerVerticalPaddingDp); } @@ -496,7 +501,9 @@ container_bounds.set_x(x_offset); // Layout a tab slider if Bento is enabled. - if (features::IsBentoEnabled()) { + if (Shell::Get() + ->window_cycle_controller() + ->IsInteractiveAltTabModeAllowed()) { // Layout the tab slider. const gfx::Size tab_slider_size = tab_slider_container_->GetPreferredSize(); @@ -690,7 +697,16 @@ } const int offset = direction == WindowCycleController::FORWARD ? 1 : -1; - SetFocusedWindow(windows_[GetOffsettedWindowIndex(offset)]); + if (offset == 1 && !wm::IsActiveWindow(windows_[0]) && + Shell::Get()->window_cycle_controller()->IsSwitchingMode()) { + // Similar to `WindowCycleList::Scroll()`, when switching to alt-tab mode, + // if all windows are minimized, the starting window should be the first + // one rather than the second. Note that during entering alt-tab mode, + // `SetFocusedWindow()` does nothing, so we don't need to prevent it here. + SetFocusedWindow(windows_[0]); + } else { + SetFocusedWindow(windows_[GetOffsettedWindowIndex(offset)]); + } Scroll(offset); } @@ -875,16 +891,17 @@ DCHECK(static_cast<size_t>(current_index_) < windows_.size()); - if (!cycle_view_ && current_index_ == 0) { - // Special case the situation where we're cycling forward but the MRU - // window is not active. This occurs when all windows are minimized. The - // starting window should be the first one rather than the second. - if (offset == 1 && !wm::IsActiveWindow(windows_[0])) - current_index_ = -1; + // If alt-tab is entered or switched to the other mode, check the following + // special case: user is cycling forward but the MRU window is not active. + // This occurs when all windows are minimized. The starting window should be + // the first one rather than the second. + if ((!cycle_view_ || + Shell::Get()->window_cycle_controller()->IsSwitchingMode()) && + current_index_ == 0 && offset == 1 && !wm::IsActiveWindow(windows_[0])) { + current_index_ = -1; } current_index_ = GetOffsettedWindowIndex(offset); - if (ShouldShowUi()) { if (current_index_ > 1) InitWindowCycleView();
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java index 3338de9..497c3f8c 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java
@@ -108,4 +108,12 @@ mActivity = ApplicationTestUtils.waitForActivityWithClass(mActivityClass, Stage.CREATED, () -> ContextUtils.getApplicationContext().startActivity(intent)); } + + /** + * Recreates the Activity, blocking until finished. + * After calling this, getActivity() returns the new Activity. + */ + public void recreateActivity() { + setActivity(ApplicationTestUtils.recreateActivity(getActivity())); + } }
diff --git a/build/android/gyp/dex.py b/build/android/gyp/dex.py index ae4df4e..87cf983 100755 --- a/build/android/gyp/dex.py +++ b/build/android/gyp/dex.py
@@ -25,42 +25,16 @@ _IGNORE_WARNINGS = ( # Caused by Play Services: r'Type `libcore.io.Memory` was not found', + # Caused by a missing final class in flogger: + r'Type `dalvik.system.VMStack` was not found', + # Caused by jacoco code coverage: + r'Type `java.lang.management.ManagementFactory` was not found', # Filter out warnings caused by our fake main dex list used to enable # multidex on library targets. # Warning: Application does not contain `Foo` as referenced in main-dex-list r'does not contain `Foo`', ) -# Missing types for desugaring that do not affect the final output. Do not add -# targets that we own to this list (e.g. any chromium targets). -_IGNORE_DESUGAR_WARNINGS = ( - r'Type `androidx.', - r'Type `com.barchart.', - r'Type `com.google.android.aidl.', - r'Type `com.google.android.apps.common.testing', - r'Type `com.google.android.gms.common.config.', - r'Type `com.google.android.gms.common.util.', - r'Type `com.google.android.gms.dynamic.', - r'Type `com.google.android.gms.dynamite.', - r'Type `com.google.android.libraries.stitch.util.Preconditions`', - r'Type `com.google.common.collect.', - r'Type `com.google.protobuf.', - r'Type `com.ning.', - r'Type `dalvik.system.VMStack`', - r'Type `difflib.DiffUtils`', - r'Type `gnu.io', - r'Type `java.', - r'Type `net.bytebuddy.', - r'Type `org.jboss.', - r'Type `net.jpountz', - r'Type `org.apache.', - r'Type `org.eclipse.', - r'Type `org.newsclub.net.unix.AFUNIXSocket`', - r'Type `org.objectweb.asm.', - r'Type `org.slf4j.', - r'Type `sun.misc.Unsafe`', -) - def _ParseArgs(args): args = build_utils.ExpandFileArgs(args) @@ -173,21 +147,15 @@ def CreateStderrFilter(show_desugar_default_interface_warnings): def filter_stderr(output): patterns = list(_IGNORE_WARNINGS) + + # When using Bazel's Desugar tool to desugar lambdas and interface methods, + # we do not provide D8 with a classpath, which causes a lot of warnings from + # D8's default interface desugaring pass. Not having a classpath makes + # incremental dexing much more effective. D8 still does backported method + # desugaring. + # These warnings are also turned off when bytecode checks are turned off. if not show_desugar_default_interface_warnings: - # When using Bazel's Desugar tool to desugar lambdas and interface - # methods, we do not provide D8 with a classpath, which causes a lot of - # warnings from D8's default interface desugaring pass. Not having a - # classpath makes incremental dexing much more effective. D8 still does - # backported method desugaring. patterns += ['default or static interface methods'] - else: - # We pass the full transitive classpath to D8, but it still emits warnings - # in its default interface desugaring pass since we have many targets that - # are third-party prebuilt jars which do not specify most of their compile - # time deps. These deps generally do not affect the final output, but D8 - # does not have Bazel's Desugar tool's --best_effort_tolerate_missing_deps - # flag, requiring us to manually curate an ignore list. - patterns += list(_IGNORE_DESUGAR_WARNINGS) combined_pattern = '|'.join(re.escape(p) for p in patterns) output = build_utils.FilterLines(output, combined_pattern)
diff --git a/build/chromeos/test_runner.py b/build/chromeos/test_runner.py index 47a1012..ea8fa84c 100755 --- a/build/chromeos/test_runner.py +++ b/build/chromeos/test_runner.py
@@ -258,6 +258,7 @@ super(TastTest, self).__init__(args, unknown_args) self._suite_name = args.suite_name + self._tast_vars = args.tast_vars self._tests = args.tests self._conditional = args.conditional self._should_strip = args.strip_chrome @@ -346,6 +347,9 @@ self._test_cmd.append('--tast') self._test_cmd.extend(self._tests) + for v in self._tast_vars or []: + self._test_cmd.extend(['--tast-var', v]) + def post_run(self, return_code): # If we don't need to parse the host-side Tast tool's results, fall back to # the parent method's default behavior. @@ -885,6 +889,12 @@ action='store_true', help='Strips symbols from the browser before deploying to the device.') tast_test_parser.add_argument( + '--tast-var', + action='append', + dest='tast_vars', + help='Runtime variables for Tast tests, and the format are expected to ' + 'be "key=value" pairs.') + tast_test_parser.add_argument( '--test', '-t', action='append',
diff --git a/build/chromeos/test_runner_test.py b/build/chromeos/test_runner_test.py index a49f0202..a1de24f 100755 --- a/build/chromeos/test_runner_test.py +++ b/build/chromeos/test_runner_test.py
@@ -163,5 +163,45 @@ self.assertItemsEqual(expected_cmd, mock_popen.call_args[0][0]) + @parameterized.expand([ + [True], + [False], + ]) + def test_tast_with_vars(self, use_vm): + """Tests running a tast tests with runtime variables.""" + with open(os.path.join(self._tmp_dir, 'streamed_results.jsonl'), 'w') as f: + json.dump(_TAST_TEST_RESULTS_JSON, f) + + args = [ + 'script_name', + 'tast', + '--suite-name=chrome_all_tast_tests', + '--board=eve', + '--flash', + '--path-to-outdir=out_eve/Release', + '--logs-dir=%s' % self._tmp_dir, + '-t=ui.ChromeLogin', + '--tast-var=key=value', + '--use-vm' if use_vm else '--device=localhost:2222', + ] + with mock.patch.object(sys, 'argv', args),\ + mock.patch.object(test_runner.subprocess, 'Popen') as mock_popen: + mock_popen.return_value.returncode = 0 + test_runner.main() + expected_cmd = [ + test_runner.CROS_RUN_TEST_PATH, '--board', 'eve', '--cache-dir', + test_runner.DEFAULT_CROS_CACHE, '--results-dest-dir', + '%s/system_logs' % self._tmp_dir, '--mount', '--deploy', '--nostrip', + '--flash', '--build-dir', 'out_eve/Release', '--results-dir', + self._tmp_dir, '--tast', 'ui.ChromeLogin', '--tast-var', 'key=value' + ] + expected_cmd.extend(['--start', '--copy-on-write'] + if use_vm else ['--device', 'localhost:2222']) + for p in test_runner.SYSTEM_LOG_LOCATIONS: + expected_cmd.extend(['--results-src', p]) + + self.assertItemsEqual(expected_cmd, mock_popen.call_args[0][0]) + + if __name__ == '__main__': unittest.main()
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 486a5448..b833e11 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -1181,6 +1181,11 @@ if (treat_warnings_as_errors) { _args += [ "--warnings-as-errors" ] } + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } if (enable_proguard_obfuscation) { # This is generally the apk name, and serves to identify the mapping @@ -1472,10 +1477,12 @@ "data", "data_deps", "deps", + "desugar_jars_paths", "disable_r8_outlining", "enable_proguard_checks", "expected_proguard_config", "expected_proguard_config_base", + "ignore_desugar_missing_deps", "is_static_library", "modules", "proguard_mapping_path", @@ -1770,6 +1777,11 @@ "--bootclasspath=@FileArg($_rebased_build_config:android:sdk_jars)", "--classpath=@FileArg($_rebased_build_config:deps_info:javac_full_interface_classpath)", ] + if (defined(invoker.desugar_jars_paths)) { + _rebased_desugar_jars_paths = + rebase_path(invoker.desugar_jars_paths, root_build_dir) + args += [ "--classpath=${_rebased_desugar_jars_paths}" ] + } if (defined(invoker.final_ijar_path)) { # Need to include the input .interface.jar on the classpath in order to make # jar_excluded_patterns classes visible to desugar. @@ -1779,6 +1791,8 @@ ] inputs += [ invoker.final_ijar_path ] } + } else { + not_needed(invoker, [ "desugar_jars_paths" ]) } _enable_assert = is_java_debug || dcheck_always_on @@ -4045,10 +4059,8 @@ } enable_desugar = _enable_desugar && enable_bazel_desugar if (enable_desugar) { - classpath_deps = _full_classpath_deps - if (defined(invoker.desugar_jars_paths)) { - desugar_jars_paths = invoker.desugar_jars_paths - } + classpath_deps = _classpath_deps + forward_variables_from(invoker, [ "desugar_jars_paths" ]) } } if (defined(invoker.enable_jetify) && invoker.enable_jetify) { @@ -4073,8 +4085,9 @@ _public_deps += [ ":${_process_prebuilt_target_name}_device" ] } - if (!defined(invoker.enable_bytecode_checks) || - invoker.enable_bytecode_checks) { + _enable_bytecode_checks = !defined(invoker.enable_bytecode_checks) || + invoker.enable_bytecode_checks + if (_enable_bytecode_checks) { _bytecode_checks_target = "${target_name}__validate_classpath" bytecode_processor(_bytecode_checks_target) { forward_variables_from(invoker, [ "missing_classes_allowlist" ]) @@ -4093,9 +4106,10 @@ if (_build_device_jar) { dex("${target_name}__dex") { - forward_variables_from(invoker, [ "ignore_desugar_missing_deps" ]) + forward_variables_from(invoker, [ "desugar_jars_paths" ]) input_class_jars = [ _device_processed_jar_path ] enable_desugar = _enable_desugar + ignore_desugar_missing_deps = !_enable_bytecode_checks # There's no value in per-class dexing prebuilts since they never # change just one class at a time.
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index fa503f9..784e39ee 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1688,6 +1688,12 @@ enable_multidex = false output = invoker.output if (defined(proguard_enabled) && proguard_enabled) { + # The individual dependencies would have caught real missing deps in + # their respective dex steps. False positives that were suppressed at + # per-target dex steps are emitted here since this is using jar files + # rather than dex files. + ignore_desugar_missing_deps = true + # When trying to build a stand-alone .dex, don't add in jdk_libs_dex. supports_jdk_library_desugaring = false } else { @@ -2956,6 +2962,12 @@ } enable_multidex = _enable_multidex + # The individual dependencies would have caught real missing deps in + # their respective dex steps. False positives that were suppressed at + # per-target dex steps are emitted here since this may use jar files + # rather than dex files. + ignore_desugar_missing_deps = true + if (_enable_main_dex_list) { forward_variables_from(invoker, [ "negative_main_dex_globs" ]) extra_main_dex_proguard_config = _generated_proguard_main_dex_config
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 2da99fd..1ac63ef 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20210106.1.1 +0.20210106.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 2da99fd..1ac63ef 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20210106.1.1 +0.20210106.3.1
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index c58dc050..8c8f34b 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -767,6 +767,7 @@ "trees/layer_tree_host_pixeltest_tiles.cc", "trees/layer_tree_host_unittest.cc", "trees/layer_tree_host_unittest_animation.cc", + "trees/layer_tree_host_unittest_capture.cc", "trees/layer_tree_host_unittest_capture_content.cc", "trees/layer_tree_host_unittest_checkerimaging.cc", "trees/layer_tree_host_unittest_context.cc",
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 3f187ae..2a0de3af 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -1003,6 +1003,22 @@ EnsureLayerTreeInputs().did_scroll_callback = std::move(callback); } +void Layer::SetSubtreeCaptureId(viz::SubtreeCaptureId subtree_id) { + DCHECK(IsPropertyChangeAllowed()); + + auto& inputs = EnsureLayerTreeInputs(); + if (inputs.subtree_capture_id == subtree_id) + return; + + DCHECK(!inputs.subtree_capture_id.is_valid() || !subtree_id.is_valid()) + << "Not allowed to change from a valid ID to another valid ID, as it may " + "already be in use."; + + inputs.subtree_capture_id = subtree_id; + SetPropertyTreesNeedRebuild(); + SetNeedsCommit(); +} + void Layer::SetScrollable(const gfx::Size& bounds) { DCHECK(IsPropertyChangeAllowed()); auto& inputs = EnsureLayerTreeInputs();
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 3f4189ef..f73be66 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -31,6 +31,7 @@ #include "cc/trees/effect_node.h" #include "cc/trees/property_tree.h" #include "cc/trees/target_property.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/rect.h" @@ -472,6 +473,27 @@ void SetDidScrollCallback(base::RepeatingCallback< void(const gfx::ScrollOffset&, const ElementId&)>); + // For layer tree mode only. + // Sets the given |subtree_id| on this layer, so that the layer subtree rooted + // at this layer can be uniquely identified by a FrameSinkVideoCapturer. + // The existence of a valid SubtreeCaptureId on this layer will force it to be + // drawn into a separate CompositorRenderPass. + // Setting a non-valid (i.e. default-constructed SubtreeCaptureId) will clear + // this property. + // It is not allowed to change this ID from a valid ID to another valid ID, + // since a client might already using the existing valid ID to make this layer + // subtree identifiable by a capturer. + // + // Note that this is useful when it's desired to video record a layer subtree + // of a non-root layer using a FrameSinkVideoCapturer, since non-root layers + // are usually not drawn into their own CompositorRenderPass. + void SetSubtreeCaptureId(viz::SubtreeCaptureId subtree_id); + viz::SubtreeCaptureId subtree_capture_id() const { + if (layer_tree_inputs()) + return layer_tree_inputs()->subtree_capture_id; + return viz::SubtreeCaptureId(); + } + // Set or get if the layer and its subtree should be cached as a texture in // the display compositor. This is used as an optimization when it is known // that the layer will be animated without changing its content, or any of its @@ -889,6 +911,12 @@ gfx::Transform transform; gfx::Point3F transform_origin; + // A unique ID that identifies the layer subtree rooted at this layer, so + // that it can be independently captured by the FrameSinkVideoCapturer. If + // this ID is set (i.e. valid), it would force this subtree into a render + // surface that darws in a render pass. + viz::SubtreeCaptureId subtree_capture_id; + SkColor safe_opaque_background_color = SK_ColorTRANSPARENT; FilterOperations filters; @@ -927,6 +955,7 @@ int clip_tree_index_; int scroll_tree_index_; int property_tree_sequence_number_; + gfx::Vector2dF offset_to_transform_parent_; // When true, the layer is about to perform an update. Any commit requests
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc index ca8fa5a7..98b2d611 100644 --- a/cc/layers/render_surface_impl.cc +++ b/cc/layers/render_surface_impl.cc
@@ -157,10 +157,19 @@ return OwningEffectNode()->has_copy_request; } +viz::SubtreeCaptureId RenderSurfaceImpl::SubtreeCaptureId() const { + return OwningEffectNode()->subtree_capture_id; +} + bool RenderSurfaceImpl::ShouldCacheRenderSurface() const { return OwningEffectNode()->cache_render_surface; } +bool RenderSurfaceImpl::CopyOfOutputRequired() const { + return HasCopyRequest() || ShouldCacheRenderSurface() || + SubtreeCaptureId().is_valid(); +} + int RenderSurfaceImpl::TransformTreeIndex() const { return OwningEffectNode()->transform_id; } @@ -210,7 +219,7 @@ } gfx::Rect RenderSurfaceImpl::CalculateClippedAccumulatedContentRect() { - if (ShouldCacheRenderSurface() || HasCopyRequest() || !is_clipped()) + if (CopyOfOutputRequired() || !is_clipped()) return accumulated_content_rect(); if (accumulated_content_rect().IsEmpty()) @@ -377,6 +386,7 @@ pass->backdrop_filters = BackdropFilters(); pass->backdrop_filter_bounds = BackdropFilterBounds(); pass->generate_mipmap = TrilinearFiltering(); + pass->subtree_capture_id = SubtreeCaptureId(); pass->cache_render_pass = ShouldCacheRenderSurface(); pass->has_damage_from_contributing_content = HasDamageFromeContributingContent();
diff --git a/cc/layers/render_surface_impl.h b/cc/layers/render_surface_impl.h index 51b07a9..105e04a 100644 --- a/cc/layers/render_surface_impl.h +++ b/cc/layers/render_surface_impl.h
@@ -18,6 +18,7 @@ #include "cc/trees/property_tree.h" #include "components/viz/common/quads/compositor_render_pass.h" #include "components/viz/common/quads/shared_quad_state.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/mask_filter_info.h" @@ -174,8 +175,15 @@ bool HasCopyRequest() const; + viz::SubtreeCaptureId SubtreeCaptureId() const; + bool ShouldCacheRenderSurface() const; + // Returns true if it's required to copy the output of this surface (i.e. when + // it has copy requests, should be cached, or has a valid subtree capture ID), + // and should be e.g. immune from occlusion, etc. Returns false otherise. + bool CopyOfOutputRequired() const; + void ResetPropertyChangedFlags(); bool SurfacePropertyChanged() const; bool SurfacePropertyChangedOnlyFromDescendant() const;
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index c2e79fc..aa4433e 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -640,19 +640,20 @@ gfx::Rect LayerVisibleRect(PropertyTrees* property_trees, LayerImpl* layer) { const EffectNode* effect_node = property_trees->effect_tree.Node(layer->effect_tree_index()); - int effect_ancestor_with_cache_render_surface = - effect_node->closest_ancestor_with_cached_render_surface_id; - int effect_ancestor_with_copy_request = - effect_node->closest_ancestor_with_copy_request_id; int lower_effect_closest_ancestor = - std::max(effect_ancestor_with_cache_render_surface, - effect_ancestor_with_copy_request); - bool non_root_copy_request_or_cache_render_surface = + effect_node->closest_ancestor_with_cached_render_surface_id; + lower_effect_closest_ancestor = + std::max(lower_effect_closest_ancestor, + effect_node->closest_ancestor_with_copy_request_id); + lower_effect_closest_ancestor = + std::max(lower_effect_closest_ancestor, + effect_node->closest_ancestor_being_captured_id); + const bool non_root_with_render_surface = lower_effect_closest_ancestor > EffectTree::kContentsRootNodeId; gfx::Rect layer_content_rect = gfx::Rect(layer->bounds()); gfx::RectF accumulated_clip_in_root_space; - if (non_root_copy_request_or_cache_render_surface) { + if (non_root_with_render_surface) { bool include_expanding_clips = true; ConditionalClip accumulated_clip = ComputeAccumulatedClip( property_trees, include_expanding_clips, layer->clip_tree_index(), @@ -668,7 +669,7 @@ } const EffectNode* root_effect_node = - non_root_copy_request_or_cache_render_surface + non_root_with_render_surface ? property_trees->effect_tree.Node(lower_effect_closest_ancestor) : property_trees->effect_tree.Node(EffectTree::kContentsRootNodeId); ConditionalClip accumulated_clip_in_layer_space = @@ -890,8 +891,7 @@ // TODO(senorblanco): make this smarter for the SkImageFilter case (check for // pixel-moving filters) const FilterOperations& filters = render_surface->Filters(); - bool is_occlusion_immune = render_surface->HasCopyRequest() || - render_surface->ShouldCacheRenderSurface() || + bool is_occlusion_immune = render_surface->CopyOfOutputRequired() || filters.HasReferenceFilter() || filters.HasFilterThatMovesPixels(); if (is_occlusion_immune) { @@ -1225,9 +1225,11 @@ if (effect_node->HasRenderSurface() && effect_node->subtree_has_copy_request) return false; - // Skip if the node's subtree is hidden and no need to cache. - if (effect_node->subtree_hidden && !effect_node->cache_render_surface) + // Skip if the node's subtree is hidden and no need to cache, or capture. + if (effect_node->subtree_hidden && !effect_node->cache_render_surface && + !effect_node->subtree_capture_id.is_valid()) { return true; + } // If the layer transform is not invertible, it should be skipped. In case the // transform is animating and singular, we should not skip it.
diff --git a/cc/trees/effect_node.cc b/cc/trees/effect_node.cc index fa07fea5..413f5888 100644 --- a/cc/trees/effect_node.cc +++ b/cc/trees/effect_node.cc
@@ -42,7 +42,8 @@ clip_id(0), target_id(1), closest_ancestor_with_cached_render_surface_id(-1), - closest_ancestor_with_copy_request_id(-1) {} + closest_ancestor_with_copy_request_id(-1), + closest_ancestor_being_captured_id(-1) {} EffectNode::EffectNode(const EffectNode& other) = default; @@ -54,6 +55,7 @@ stable_id == other.stable_id && opacity == other.opacity && screen_space_opacity == other.screen_space_opacity && backdrop_filter_quality == other.backdrop_filter_quality && + subtree_capture_id == other.subtree_capture_id && cache_render_surface == other.cache_render_surface && has_copy_request == other.has_copy_request && filters == other.filters && @@ -94,7 +96,9 @@ closest_ancestor_with_cached_render_surface_id == other.closest_ancestor_with_cached_render_surface_id && closest_ancestor_with_copy_request_id == - other.closest_ancestor_with_copy_request_id; + other.closest_ancestor_with_copy_request_id && + closest_ancestor_being_captured_id == + other.closest_ancestor_being_captured_id; } #endif // DCHECK_IS_ON() @@ -172,6 +176,7 @@ } } value->SetString("blend_mode", SkBlendMode_Name(blend_mode)); + value->SetString("subtree_capture_id", subtree_capture_id.ToString()); value->SetBoolean("cache_render_surface", cache_render_surface); value->SetBoolean("has_copy_request", has_copy_request); value->SetBoolean("double_sided", double_sided); @@ -198,6 +203,8 @@ closest_ancestor_with_cached_render_surface_id); value->SetInteger("closest_ancestor_with_copy_request_id", closest_ancestor_with_copy_request_id); + value->SetInteger("closest_ancestor_being_captured_id", + closest_ancestor_being_captured_id); value->SetBoolean("affected_by_backdrop_filter", affected_by_backdrop_filter); }
diff --git a/cc/trees/effect_node.h b/cc/trees/effect_node.h index 2a2541d1..65edbca 100644 --- a/cc/trees/effect_node.h +++ b/cc/trees/effect_node.h
@@ -8,6 +8,7 @@ #include "cc/cc_export.h" #include "cc/paint/element_id.h" #include "cc/paint/filter_operations.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "third_party/skia/include/core/SkBlendMode.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size_f.h" @@ -44,6 +45,7 @@ kCache, kCopyRequest, kMirrored, + kSubtreeIsBeingCaptured, // This must be the last value because it's used in tracing code to know the // number of reasons. kTest, @@ -90,6 +92,8 @@ gfx::Vector2dF surface_contents_scale; + viz::SubtreeCaptureId subtree_capture_id; + bool cache_render_surface : 1; bool has_copy_request : 1; bool hidden_by_backface_visibility : 1; @@ -154,6 +158,7 @@ int target_id; int closest_ancestor_with_cached_render_surface_id; int closest_ancestor_with_copy_request_id; + int closest_ancestor_being_captured_id; bool HasRenderSurface() const { return render_surface_reason != RenderSurfaceReason::kNone;
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 55c7a74..7b11dac 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -1170,8 +1170,7 @@ render_surface->EffectTreeIndex() == EffectTree::kContentsRootNodeId; bool should_draw_into_render_pass = is_root_surface || render_surface->contributes_to_drawn_surface() || - render_surface->HasCopyRequest() || - render_surface->ShouldCacheRenderSurface(); + render_surface->CopyOfOutputRequired(); if (should_draw_into_render_pass) frame->render_passes.push_back(render_surface->CreateRenderPass()); } @@ -1598,7 +1597,8 @@ } if (pass->quad_list.empty() && pass->copy_requests.empty() && - pass->filters.IsEmpty() && pass->backdrop_filters.IsEmpty()) { + !pass->subtree_capture_id.is_valid() && pass->filters.IsEmpty() && + pass->backdrop_filters.IsEmpty()) { // Remove the pass and decrement |i| to counter the for loop's increment, // so we don't skip the next pass in the loop. frame->render_passes.erase(frame->render_passes.begin() + i);
diff --git a/cc/trees/layer_tree_host_unittest_capture.cc b/cc/trees/layer_tree_host_unittest_capture.cc new file mode 100644 index 0000000..0336419 --- /dev/null +++ b/cc/trees/layer_tree_host_unittest_capture.cc
@@ -0,0 +1,143 @@ +// Copyright 2020 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 "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_picture_layer.h" +#include "cc/test/layer_tree_test.h" +#include "cc/test/property_tree_test_utils.h" +#include "cc/trees/layer_tree_impl.h" +#include "components/viz/common/quads/compositor_frame.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" + +namespace cc { +namespace { + +constexpr viz::SubtreeCaptureId kCaptureId{22}; + +// A base class for tests that verifies the bahvior of the layer tree when a +// sub layer has a valid viz::SubtreeCaptureId. +class LayerTreeHostCaptureTest : public LayerTreeTest { + public: + void SetupTree() override { + scoped_refptr<Layer> root = FakePictureLayer::Create(&client_); + root->SetBounds(gfx::Size(100, 100)); + + child_ = FakePictureLayer::Create(&client_); + child_->SetBounds(gfx::Size(50, 60)); + child_->SetPosition(gfx::PointF(10.f, 5.5f)); + root->AddChild(child_); + + grand_child_ = FakePictureLayer::Create(&client_); + grand_child_->SetBounds(gfx::Size(70, 30)); + grand_child_->SetPosition(gfx::PointF(50.f, 50.f)); + child_->AddChild(grand_child_); + + layer_tree_host()->SetRootLayer(root); + LayerTreeTest::SetupTree(); + client_.set_bounds(root->bounds()); + } + + void DrawLayersOnThread(LayerTreeHostImpl* impl) override { + LayerImpl* root = impl->active_tree()->root_layer(); + LayerImpl* child = impl->active_tree()->LayerById(child_->id()); + LayerImpl* grand_child = impl->active_tree()->LayerById(grand_child_->id()); + + VerifyLayerImpls(root, child, grand_child); + } + + protected: + // Lets test subclasses to verify the LayerImpls of the layers in the tree. + virtual void VerifyLayerImpls(LayerImpl* root, + LayerImpl* child, + LayerImpl* grand_child) = 0; + + FakeContentLayerClient client_; + scoped_refptr<Layer> child_; + scoped_refptr<Layer> grand_child_; +}; + +// ----------------------------------------------------------------------------- +// LayerTreeHostCaptureTestNoExtraRenderPassWhenNotCapturing: +// +// Tests that a layer tree that doesn't have a viz::SubtreeCaptureId on any of +// its layers, draw in a single root render surface, and generates a single +// compositor render pass. +class LayerTreeHostCaptureTestNoExtraRenderPassWhenNotCapturing + : public LayerTreeHostCaptureTest { + public: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void VerifyLayerImpls(LayerImpl* root, + LayerImpl* child, + LayerImpl* grand_child) override { + // All layers in the tree draw in the same root render surface. + auto* root_surface = GetRenderSurface(root); + auto* child_surface = GetRenderSurface(child); + auto* grand_child_surface = GetRenderSurface(grand_child); + EXPECT_EQ(root_surface, child_surface); + EXPECT_EQ(root_surface, grand_child_surface); + EXPECT_FALSE(root_surface->CopyOfOutputRequired()); + EXPECT_FALSE(root_surface->SubtreeCaptureId().is_valid()); + + EndTest(); + } + + void DisplayReceivedCompositorFrameOnThread( + const viz::CompositorFrame& frame) override { + // There should be a single compositor render pass, which has no valid + // SubtreeCaptureId. + ASSERT_EQ(frame.render_pass_list.size(), 1u); + EXPECT_FALSE(frame.render_pass_list.back()->subtree_capture_id.is_valid()); + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostCaptureTestNoExtraRenderPassWhenNotCapturing); + +// ----------------------------------------------------------------------------- +// LayerTreeHostCaptureTestLayerWithCaptureIdElevatesToSurface +// +// Tests that a layer sub tree whose root has a valid viz::SubtreeCaptureId will +// draw into a separate render surface and a separate render pass. +class LayerTreeHostCaptureTestLayerWithCaptureIdElevatesToSurface + : public LayerTreeHostCaptureTest { + public: + void BeginTest() override { child_->SetSubtreeCaptureId(kCaptureId); } + + void VerifyLayerImpls(LayerImpl* root, + LayerImpl* child, + LayerImpl* grand_child) override { + // |child| should draw into a separate render surface from that of the root, + // and the |grand_child| should draw into the render surface of its parent + // (which is |child|'s). + // The |chils|'s surface should have the expected capture ID. + auto* root_surface = GetRenderSurface(root); + auto* child_surface = GetRenderSurface(child); + auto* grand_child_surface = GetRenderSurface(grand_child); + EXPECT_NE(root_surface, child_surface); + EXPECT_NE(root_surface, grand_child_surface); + EXPECT_EQ(child_surface, grand_child_surface); + EXPECT_EQ(kCaptureId, child_surface->SubtreeCaptureId()); + EXPECT_TRUE(child_surface->CopyOfOutputRequired()); + + EndTest(); + } + + void DisplayReceivedCompositorFrameOnThread( + const viz::CompositorFrame& frame) override { + // There should be 2 render passes. The non-root render pass is associated + // with the layer subtree rooted at |child| and should have the expected + // capture ID. + ASSERT_EQ(frame.render_pass_list.size(), 2u); + EXPECT_TRUE(frame.render_pass_list.front()->subtree_capture_id.is_valid()); + EXPECT_EQ(kCaptureId, frame.render_pass_list.front()->subtree_capture_id); + EXPECT_FALSE(frame.render_pass_list.back()->subtree_capture_id.is_valid()); + } +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostCaptureTestLayerWithCaptureIdElevatesToSurface); + +} // namespace +} // namespace cc
diff --git a/cc/trees/occlusion_tracker.cc b/cc/trees/occlusion_tracker.cc index b3ed41e..2a88893 100644 --- a/cc/trees/occlusion_tracker.cc +++ b/cc/trees/occlusion_tracker.cc
@@ -196,9 +196,7 @@ // Readbacks always happen on render targets so we only need to check // for readbacks here. bool target_is_only_for_copy_request_or_force_render_surface = - (finished_target_surface->HasCopyRequest() || - finished_target_surface->ShouldCacheRenderSurface()) && - is_hidden; + is_hidden && finished_target_surface->CopyOfOutputRequired(); // If the occlusion within the surface can not be applied to things outside of // the surface's subtree, then clear the occlusion here so it won't be used.
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index d9da2f9..c854377 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -729,20 +729,24 @@ // Exceptions: // 1) Nodes that contribute to copy requests, whether hidden or not, must be // drawn. - // 2) Nodes that have a backdrop filter. - // 3) Nodes with animating screen space opacity on main thread or pending tree + // 2) Nodes that have a valid SubtreeCaptureId, must be drawn so that they can + // be captured by the FrameSinkVideoCapturer. + // 3) Nodes that have a backdrop filter. + // 4) Nodes with animating screen space opacity on main thread or pending tree // are drawn if their parent is drawn irrespective of their opacity. - if (node->has_copy_request || node->cache_render_surface) + if (node->has_copy_request || node->cache_render_surface || + node->subtree_capture_id.is_valid()) { node->is_drawn = true; - else if (EffectiveOpacity(node) == 0.f && - (!node->has_potential_opacity_animation || - property_trees()->is_active) && - node->backdrop_filters.IsEmpty()) + } else if (EffectiveOpacity(node) == 0.f && + (!node->has_potential_opacity_animation || + property_trees()->is_active) && + node->backdrop_filters.IsEmpty()) { node->is_drawn = false; - else if (parent_node) + } else if (parent_node) { node->is_drawn = parent_node->is_drawn; - else + } else { node->is_drawn = true; + } } void EffectTree::UpdateEffectChanged(EffectNode* node, @@ -789,7 +793,8 @@ void EffectTree::UpdateOnlyDrawsVisibleContent(EffectNode* node, EffectNode* parent_node) { - node->only_draws_visible_content = !node->has_copy_request; + node->only_draws_visible_content = + !node->has_copy_request && !node->subtree_capture_id.is_valid(); if (parent_node) node->only_draws_visible_content &= parent_node->only_draws_visible_content; if (!node->backdrop_filters.IsEmpty()) {
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index d0f5851..e7d040f 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -39,6 +39,7 @@ int scroll_tree_parent; int closest_ancestor_with_cached_render_surface; int closest_ancestor_with_copy_request; + int closest_ancestor_being_captured; SkColor safe_opaque_background_color; bool animation_axis_aligned_since_render_target; bool not_axis_aligned_since_last_clip; @@ -389,6 +390,9 @@ if (layer->mirror_count()) return RenderSurfaceReason::kMirrored; + if (layer->subtree_capture_id().is_valid()) + return RenderSurfaceReason::kSubtreeIsBeingCaptured; + return RenderSurfaceReason::kNone; } @@ -455,6 +459,7 @@ node->stable_id = layer->id(); node->opacity = layer->opacity(); node->blend_mode = layer->blend_mode(); + node->subtree_capture_id = layer->subtree_capture_id(); node->cache_render_surface = layer->cache_render_surface(); node->has_copy_request = layer->HasCopyRequest(); node->filters = layer->filters(); @@ -484,6 +489,10 @@ layer->HasCopyRequest() ? node_id : data_from_ancestor.closest_ancestor_with_copy_request; + node->closest_ancestor_being_captured_id = + layer->subtree_capture_id().is_valid() + ? node_id + : data_from_ancestor.closest_ancestor_being_captured; if (layer->HasRoundedCorner()) { // This is currently in the local space of the layer and hence in an invalid @@ -518,6 +527,8 @@ node->closest_ancestor_with_cached_render_surface_id; data_for_children->closest_ancestor_with_copy_request = node->closest_ancestor_with_copy_request_id; + data_for_children->closest_ancestor_being_captured = + node->closest_ancestor_being_captured_id; data_for_children->effect_tree_parent = node_id; layer->SetEffectTreeIndex(node_id); @@ -717,6 +728,8 @@ EffectTree::kInvalidNodeId; data_for_recursion.closest_ancestor_with_copy_request = EffectTree::kInvalidNodeId; + data_for_recursion.closest_ancestor_being_captured = + EffectTree::kInvalidNodeId; data_for_recursion.compound_transform_since_render_target = gfx::Transform(); data_for_recursion.animation_axis_aligned_since_render_target = true; data_for_recursion.not_axis_aligned_since_last_clip = false;
diff --git a/chrome/VERSION b/chrome/VERSION index 2eb6622..eaff515 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=89 MINOR=0 -BUILD=4381 +BUILD=4382 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index bb49f751..0a5648e 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -830,6 +830,7 @@ "//chrome/browser/image_fetcher:java", "//chrome/browser/incognito/interstitial/android:junit", "//chrome/browser/omaha/android:java", + "//chrome/browser/optimization_guide/android:java", "//chrome/browser/performance_hints/android:java", "//chrome/browser/policy/android:java", "//chrome/browser/preferences:java", @@ -904,6 +905,7 @@ "//components/module_installer/android:module_installer_java", "//components/offline_items_collection/core:core_java", "//components/omnibox/browser:browser_java", + "//components/optimization_guide/proto:optimization_guide_proto_java", "//components/page_info/android:java", "//components/payments/content/android:java", "//components/payments/content/android:service_java", @@ -1076,6 +1078,7 @@ "//chrome/browser/incognito/interstitial/android:javatests", "//chrome/browser/offline_pages/android:java", "//chrome/browser/omaha/android:java", + "//chrome/browser/optimization_guide/android:java", "//chrome/browser/optimization_guide/android:javatests", "//chrome/browser/paint_preview/android:java", "//chrome/browser/paint_preview/android:javatests",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java index 483ecdf..595c7ec 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java
@@ -53,6 +53,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.chrome.autofill_assistant.R; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto; @@ -828,6 +829,7 @@ */ @Test @MediumTest + @DisabledTest(message = "https://crbug.com/1163659") public void testCreateShippingAddressAndCreditCard() { ArrayList<ActionProto> list = new ArrayList<>(); list.add((ActionProto) ActionProto.newBuilder()
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index 23acb3db..692cb623 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -637,6 +637,12 @@ } } + // Pressing back button on the Start surface homepage is handled by + // ChromeTabbedActivity#handleBackPressed(). + if (mStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE && !mShowStackTabSwitcher) { + return false; + } + if (mPropertyModel != null && mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE) && mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER_TWO_PANES) { setExploreSurfaceVisibility(false);
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 81c0b4d4..a1d8f607 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -50,6 +50,7 @@ import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; +import android.widget.LinearLayout; import androidx.recyclerview.widget.RecyclerView; import androidx.test.espresso.UiController; @@ -98,6 +99,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.init.AsyncInitializationActivity; +import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil; import org.chromium.chrome.browser.tasks.SingleTabSwitcherMediator; import org.chromium.chrome.browser.tasks.pseudotab.TabAttributeCache; @@ -750,15 +752,26 @@ .getLayoutManager() .overviewVisible()); waitForTabModel(); - // Single surface is shown as homepage. Exit in order to get into tab switcher later. - pressBack(); + if (isInstantReturn()) { + // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar + // omnibox. + return; + } + // Single surface is shown as homepage. Clicks "more_tabs" button to get into tab + // switcher. + try { + TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity() + .findViewById(org.chromium.chrome.tab_ui.R.id.more_tabs) + .performClick()); + } catch (ExecutionException e) { + fail("Failed to tap 'more tabs' " + e.toString()); + } + } else { + TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity()); } - if (isInstantReturn()) { - // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar - // omnibox. - return; - } - TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity()); + onViewWaiting(allOf(withId(R.id.secondary_tasks_surface_view), isDisplayed())); OverviewModeBehaviorWatcher hideWatcher = @@ -1544,6 +1557,132 @@ assertEquals(taskSurfaceHeader.getBottom(), taskSurfaceHeader.getHeight()); } + @Test + @MediumTest + @Feature({"StartSurface"}) + // clang-format off + @CommandLineFlags.Add({BASE_PARAMS + "/single"}) + public void testShow_SingleAsHomepage_BackButton() throws ExecutionException { + // clang-format on + if (!mImmediateReturn) { + onView(withId(org.chromium.chrome.tab_ui.R.id.home_button)).perform(click()); + } + + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + CriteriaHelper.pollUiThread( + () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible()); + waitForTabModel(); + TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); + + // Case 1: + // Launches the first site in mv tiles, and press back button. + LinearLayout tilesLayout = + cta.findViewById(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout); + onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container), isDisplayed())); + TestThreadUtils.runOnUiThreadBlocking(() -> tilesLayout.getChildAt(0).performClick()); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + // Verifies a new Tab is created. + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + pressBack(); + + if (isInstantReturn() + && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP + && Build.VERSION.SDK_INT < Build.VERSION_CODES.O)) { + // Fix the issue that failed to perform a single click on the back button. + return; + } + + CriteriaHelper.pollUiThread(() -> cta.getLayoutManager().overviewVisible()); + // Verifies the new Tab is deleted. + TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); + + // Case 2: + // Launches the first site in mv tiles, and press home button to return to the Start + // surface. + onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container), isDisplayed())); + TestThreadUtils.runOnUiThreadBlocking(() -> tilesLayout.getChildAt(0).performClick()); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + onViewWaiting(allOf(withId(org.chromium.chrome.R.id.home_button), isDisplayed())); + TestThreadUtils.runOnUiThreadBlocking( + () -> { cta.findViewById(org.chromium.chrome.R.id.home_button).performClick(); }); + onViewWaiting(withId(R.id.primary_tasks_surface_view)); + onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view), isDisplayed())); + // Verifies a new Tab is created, and can be seen in the Start surface. + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + + // Launches the new tab from the carousel tab switcher, and press back button. + onView(allOf(withParent(withId( + org.chromium.chrome.tab_ui.R.id.carousel_tab_switcher_container)), + withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))) + .perform(RecyclerViewActions.actionOnItemAtPosition(1, click())); + Assert.assertEquals(TabLaunchType.FROM_START_SURFACE, + cta.getTabModelSelector().getCurrentTab().getLaunchType()); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + pressBack(); + onViewWaiting(withId(R.id.primary_tasks_surface_view)); + // Verifies the tab isn't auto deleted from the TabModel. + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + } + + @Test + @MediumTest + @Feature({"StartSurface"}) + // clang-format off + @CommandLineFlags.Add({BASE_PARAMS + "/single"}) + public void testShow_SingleAsHomepage_BackButtonWithTabSwitcher() throws ExecutionException { + // clang-format on + if (!mImmediateReturn) { + onView(withId(org.chromium.chrome.tab_ui.R.id.home_button)).perform(click()); + } + + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + CriteriaHelper.pollUiThread( + () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible()); + onViewWaiting(withId(org.chromium.chrome.tab_ui.R.id.mv_tiles_container)); + TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); + + // Launches the first site in mv tiles. + LinearLayout tilesLayout = + cta.findViewById(org.chromium.chrome.tab_ui.R.id.mv_tiles_layout); + TestThreadUtils.runOnUiThreadBlocking(() -> tilesLayout.getChildAt(0).performClick()); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + // Verifies a new Tab is created. + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + + if (isInstantReturn() + && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP + && Build.VERSION.SDK_INT < Build.VERSION_CODES.O)) { + // Fix the issue that failed to perform a single click on the tab switcher button. + // See code below. + return; + } + + // Enters the tab switcher, and choose the new tab. After the tab is opening, press back. + onView(allOf(withId(org.chromium.chrome.R.id.tab_switcher_button), isDisplayed())); + TestThreadUtils.runOnUiThreadBlocking(() -> { + cta.findViewById(org.chromium.chrome.R.id.tab_switcher_button).performClick(); + }); + CriteriaHelper.pollUiThread(() -> cta.getLayoutManager().overviewVisible()); + onViewWaiting(withId(R.id.primary_tasks_surface_view)); + onView(allOf(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view), isDisplayed())); + onView(allOf(withParent(withId(org.chromium.chrome.tab_ui.R.id.tasks_surface_body)), + withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))) + .perform(RecyclerViewActions.actionOnItemAtPosition(1, click())); + CriteriaHelper.pollUiThread(() -> !cta.getLayoutManager().overviewVisible()); + Assert.assertEquals(TabLaunchType.FROM_START_SURFACE, + cta.getTabModelSelector().getCurrentTab().getLaunchType()); + TestThreadUtils.runOnUiThreadBlocking( + () + -> Assert.assertTrue(StartSurfaceUserData.getKeepTab( + cta.getTabModelSelector().getCurrentTab()))); + pressBack(); + + // Verifies the new Tab isn't deleted, and Start surface is shown. + CriteriaHelper.pollUiThread(() -> cta.getLayoutManager().overviewVisible()); + onViewWaiting(withId(R.id.primary_tasks_surface_view)); + TabUiTestHelper.verifyTabModelTabCount(cta, 2, 0); + } + private static Matcher<View> isView(final View targetView) { return new TypeSafeMatcher<View>() { @Override
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java new file mode 100644 index 0000000..5b22d55a --- /dev/null +++ b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java
@@ -0,0 +1,43 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.features.start_surface; + +import org.chromium.base.UserData; +import org.chromium.chrome.browser.tab.Tab; + +/** + * Helper class for Tabs created from the Start surface. + */ +public class StartSurfaceUserData implements UserData { + private static final Class<StartSurfaceUserData> USER_DATA_KEY = StartSurfaceUserData.class; + private boolean mKeepTab; + + /** + * Sets the flag of whether to keep the given tab in the TabModel without auto deleting when + * tapping the back button. This flag is for a tab with launchType + * {@link org.chromium.chrome.browser.tab.TabLaunchType.FROM_START_SURFACE}. + */ + public static void setKeepTab(Tab tab, boolean keepTab) { + StartSurfaceUserData startSurfaceUserData = get(tab); + if (startSurfaceUserData == null) { + startSurfaceUserData = new StartSurfaceUserData(); + } + startSurfaceUserData.mKeepTab = keepTab; + tab.getUserDataHost().setUserData(USER_DATA_KEY, startSurfaceUserData); + } + + /** + * @return Whether to keep the given tab in the TabModel without auto deleting when tapping the + * back button. Returns false if the UserData isn't set. + */ + public static boolean getKeepTab(Tab tab) { + StartSurfaceUserData startSurfaceUserData = get(tab); + return startSurfaceUserData == null ? false : startSurfaceUserData.mKeepTab; + } + + private static StartSurfaceUserData get(Tab tab) { + return tab.getUserDataHost().getUserData(USER_DATA_KEY); + } +}
diff --git a/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni b/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni index 4861cb0..67dd7fa 100644 --- a/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni +++ b/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni
@@ -6,4 +6,5 @@ "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java", "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java", "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceState.java", + "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceUserData.java", ]
diff --git a/chrome/android/features/tab_ui/DEPS b/chrome/android/features/tab_ui/DEPS index 40e7b73..f93af16 100644 --- a/chrome/android/features/tab_ui/DEPS +++ b/chrome/android/features/tab_ui/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+chrome/browser/android/lifecycle", "+chrome/browser/endpoint_fetcher", + "+chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide", "+chrome/browser/profiles/android/java", "+chrome/browser/tab/java", "+chrome/browser/tabmodel/android/java", @@ -13,6 +14,5 @@ "+components/feature_engagement/public/android/java/src/org/chromium/components/feature_engagement", "+components/search_engines/android/java/src/org/chromium/components/search_engines", "+components/module_installer", - "+content/public/android/java/src/org/chromium/content_public/browser", ]
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java index 68fcda8..f92ea2e 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -259,8 +259,9 @@ /** * Run additional actions on tab selection. * @param tabId The ID of selected {@link Tab}. + * @param fromActionButton Whether it is called from the Action button on the card. */ - void onTabSelecting(int tabId); + void onTabSelecting(int tabId, boolean fromActionButton); } @IntDef({TabClosedFrom.TAB_STRIP, TabClosedFrom.GRID_TAB_SWITCHER, @@ -322,7 +323,8 @@ recordUserSwitchedTab(currentTab, newlySelectedTab); } if (mGridCardOnClickListenerProvider != null) { - mGridCardOnClickListenerProvider.onTabSelecting(tabId); + mGridCardOnClickListenerProvider.onTabSelecting( + tabId, true /* fromActiionButton */); } else { mTabModelSelector.getCurrentModel().setIndex( TabModelUtils.getTabIndexById(mTabModelSelector.getCurrentModel(), tabId),
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java index 42d4f13..fec7847 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -55,6 +55,7 @@ import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter; import org.chromium.chrome.browser.tasks.tab_management.TabListCoordinator.TabListMode; import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration; +import org.chromium.chrome.features.start_surface.StartSurfaceUserData; import org.chromium.chrome.tab_ui.R; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.ui.modelutil.PropertyModel; @@ -293,7 +294,7 @@ } if (mContainerViewModel.get(IS_VISIBLE)) { - onTabSelecting(tab.getId()); + onTabSelecting(tab.getId(), false); } } @@ -725,7 +726,7 @@ } if (mTabModelSelector.getCurrentTab() == null) return false; - onTabSelecting(mTabModelSelector.getCurrentTabId()); + onTabSelecting(mTabModelSelector.getCurrentTabId(), false); return true; } @@ -812,7 +813,12 @@ } @Override - public void onTabSelecting(int tabId) { + public void onTabSelecting(int tabId, boolean fromActionButton) { + if (fromActionButton && (mMode == TabListMode.CAROUSEL || mMode == TabListMode.GRID)) { + Tab newlySelectedTab = + TabModelUtils.getTabById(mTabModelSelector.getCurrentModel(), tabId); + StartSurfaceUserData.setKeepTab(newlySelectedTab, true); + } mIsSelectingInTabSwitcher = true; if (mOnTabSelectingListener != null) { mOnTabSelectingListener.onTabSelecting(LayoutManagerImpl.time(), tabId);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContext.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContext.java index 3f5e8cd..e376e2d 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContext.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContext.java
@@ -115,7 +115,7 @@ } public double getSiteEngagementScore() { - return SiteEngagementService.getForProfile(Profile.getLastUsedRegularProfile()) + return SiteEngagementService.getForBrowserContext(Profile.getLastUsedRegularProfile()) .getScore(visibleUrl); }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index 77a222a..2a54a971 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -95,6 +95,9 @@ import org.chromium.chrome.browser.flags.CachedFeatureFlags; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; +import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridge; +import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridge.OptimizationGuideCallback; +import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridgeJni; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.tab.MockTab; @@ -125,6 +128,7 @@ import org.chromium.components.embedder_support.util.UrlUtilitiesJni; import org.chromium.components.feature_engagement.EventConstants; import org.chromium.components.feature_engagement.Tracker; +import org.chromium.components.optimization_guide.OptimizationGuideDecision; import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.NavigationController; @@ -240,6 +244,8 @@ @Mock UrlUtilities.Natives mUrlUtilitiesJniMock; @Mock + OptimizationGuideBridge.Natives mOptimizationGuideBridgeJniMock; + @Mock TabListMediator.TabGridAccessibilityHelper mTabGridAccessibilityHelper; @Mock TemplateUrlService mTemplateUrlService; @@ -278,6 +284,10 @@ MockitoAnnotations.initMocks(this); mMocker.mock(UrlUtilitiesJni.TEST_HOOKS, mUrlUtilitiesJniMock); mMocker.mock(EndpointFetcherJni.TEST_HOOKS, mEndpointFetcherJniMock); + mMocker.mock(OptimizationGuideBridgeJni.TEST_HOOKS, mOptimizationGuideBridgeJniMock); + // Ensure native pointer is initialized + doReturn(1L).when(mOptimizationGuideBridgeJniMock).init(); + mockOptimizationGuideResponse(OptimizationGuideDecision.TRUE); CachedFeatureFlags.setForTesting(ChromeFeatureList.START_SURFACE_ANDROID, false); TabUiFeatureUtilities.ENABLE_SEARCH_CHIP.setForTesting(true); @@ -480,7 +490,7 @@ .run(mModel.get(1).model.get(TabProperties.TAB_ID)); verify(mGridCardOnClickListenerProvider) - .onTabSelecting(mModel.get(1).model.get(TabProperties.TAB_ID)); + .onTabSelecting(mModel.get(1).model.get(TabProperties.TAB_ID), true); } @Test @@ -2092,7 +2102,7 @@ .run(mModel.get(0).model.get(TabProperties.TAB_ID)); verify(mGridCardOnClickListenerProvider) - .onTabSelecting(mModel.get(0).model.get(TabProperties.TAB_ID)); + .onTabSelecting(mModel.get(0).model.get(TabProperties.TAB_ID), true); verify(mTab1).loadUrl( refEq(new LoadUrlParams(searchUrl.getSpec(), PageTransition.KEYWORD_GENERATED))); } @@ -2123,7 +2133,7 @@ .run(mModel.get(0).model.get(TabProperties.TAB_ID)); verify(mGridCardOnClickListenerProvider) - .onTabSelecting(mModel.get(0).model.get(TabProperties.TAB_ID)); + .onTabSelecting(mModel.get(0).model.get(TabProperties.TAB_ID), true); verify(navigationController, never()).goToOffset(0); doReturn(webContents).when(mTab1).getWebContents(); @@ -2579,4 +2589,19 @@ any(Callback.class)); } } + + private void mockOptimizationGuideResponse(@OptimizationGuideDecision int decision) { + doAnswer(new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + OptimizationGuideCallback callback = + (OptimizationGuideCallback) invocation.getArguments()[3]; + callback.onOptimizationGuideDecision(decision, null); + return null; + } + }) + .when(mOptimizationGuideBridgeJniMock) + .canApplyOptimization( + anyLong(), any(GURL.class), anyInt(), any(OptimizationGuideCallback.class)); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 6403222..9398ff8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -160,6 +160,7 @@ import org.chromium.chrome.features.start_surface.StartSurface; import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration; import org.chromium.chrome.features.start_surface.StartSurfaceState; +import org.chromium.chrome.features.start_surface.StartSurfaceUserData; import org.chromium.components.browser_ui.util.BrowserControlsVisibilityDelegate; import org.chromium.components.browser_ui.util.ComposedBrowserControlsVisibilityDelegate; import org.chromium.components.embedder_support.util.UrlConstants; @@ -1860,8 +1861,12 @@ return true; } - // If we are in overview mode and not a tablet, then leave overview mode on back. - if (mOverviewModeController.overviewVisible() && !isTablet()) { + // If we are in the tab switcher mode (not in the Start surface homepage) and not a tablet, + // then leave tab switcher mode on back. + if (mOverviewModeController.overviewVisible() && !isTablet() + && (mStartSurfaceSupplier.get() == null + || mStartSurfaceSupplier.get().getController().getStartSurfaceState() + == StartSurfaceState.SHOWN_TABSWITCHER)) { mOverviewModeController.hideOverview(true); return true; } @@ -1878,11 +1883,22 @@ return true; } - // If the current tab is created from the start surface, then the back button should close - // the tab and go back to the start surface. - if (type == TabLaunchType.FROM_START_SURFACE) { - getCurrentTabModel().closeTab(currentTab); - showOverview(StartSurfaceState.SHOWING_PREVIOUS); + // If we aren't in the overview mode, we handle the Tab with launchType + // TabLaunchType.FROM_START_SURFACE here. + if (!mOverviewModeController.overviewVisible() + && type == TabLaunchType.FROM_START_SURFACE) { + if (StartSurfaceUserData.getKeepTab(currentTab)) { + // If the current tab is created from the start surface with the keepTab property, + // shows the Start surface Homepage to prevent a loop between the current tab and + // previous overview mode. Once in the Start surface, it will close Chrome if back + // button is tapped again. + showOverview(StartSurfaceState.SHOWING_HOMEPAGE); + } else { + // Otherwise, clicking the back button should close the tab and go back to the + // previous overview mode. + getCurrentTabModel().closeTab(currentTab); + showOverview(StartSurfaceState.SHOWING_PREVIOUS); + } return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java index c1fd6ad..04c22be 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
@@ -840,9 +840,10 @@ * bookmark ID will be returned. * @param title The title to be used for the reading list item. * @param url The URL of the reading list item. - * @return The bookmark ID created after saving the article to the reading list. + * @return The bookmark ID created after saving the article to the reading list, or null on + * error. */ - public BookmarkId addToReadingList(String title, String url) { + public @Nullable BookmarkId addToReadingList(String title, String url) { ThreadUtils.assertOnUiThread(); assert title != null; assert url != null;
diff --git a/chrome/android/javatests/DEPS b/chrome/android/javatests/DEPS index aa27657..1bced8b 100644 --- a/chrome/android/javatests/DEPS +++ b/chrome/android/javatests/DEPS
@@ -14,6 +14,7 @@ "+chrome/browser/endpoint_fetcher", "+chrome/browser/ui/android/appmenu", "-chrome/browser/ui/android/appmenu/internal", + "+chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide", "+chrome/browser/ui/android/theme/java", "+chrome/browser/ui/messages/android/java", "+chrome/browser/signin/services/android/java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java index fe57444d..a9347c6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/background_sync/PeriodicBackgroundSyncTest.java
@@ -230,7 +230,7 @@ private void resetEngagementForUrl(final String url, final double engagement) { TestThreadUtils.runOnUiThreadBlocking(() -> { // TODO (https://crbug.com/1063807): Add incognito mode tests. - SiteEngagementService.getForProfile(Profile.getLastUsedRegularProfile()) + SiteEngagementService.getForBrowserContext(Profile.getLastUsedRegularProfile()) .resetBaseScoreForUrl(url, engagement); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java index 9442632..742dbf0e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
@@ -18,10 +18,13 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.util.BookmarkTestUtil; +import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.components.bookmarks.BookmarkType; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.ArrayList; @@ -314,4 +317,21 @@ + "over partner bookmarks", expectedSearchResults, searchResults); } + + @Test + @SmallTest + @UiThreadTest + @Features.EnableFeatures({ChromeFeatureList.READ_LATER}) + public void testAddToReadingList() { + Assert.assertNull("Should return null for non http/https URLs.", + mBookmarkBridge.addToReadingList("a", "chrome://flags")); + BookmarkId readingListId = mBookmarkBridge.addToReadingList("a", "https://www.google.com/"); + Assert.assertNotNull(readingListId); + Assert.assertEquals(BookmarkType.READING_LIST, readingListId.getType()); + BookmarkItem readingListItem = + mBookmarkBridge.getReadingListItem("https://www.google.com/"); + Assert.assertNotNull(readingListItem); + Assert.assertEquals("https://www.google.com/", readingListItem.getUrl()); + Assert.assertEquals("a", readingListItem.getTitle()); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java index 424496e2..11edd12 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
@@ -116,7 +116,8 @@ @Override public Double call() { // TODO (https://crbug.com/1063807): Add incognito mode tests. - return SiteEngagementService.getForProfile(Profile.getLastUsedRegularProfile()) + return SiteEngagementService + .getForBrowserContext(Profile.getLastUsedRegularProfile()) .getScore(mPermissionTestRule.getOrigin()); } });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java index 3973dd03..39ae4ec2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
@@ -624,7 +624,7 @@ final String url = WebappTestPage.getServiceWorkerUrlWithAction( mTestServer, "call_stashed_prompt_on_click"); TestThreadUtils.runOnUiThreadBlocking(() -> { - SiteEngagementService.getForProfile(Profile.getLastUsedRegularProfile()) + SiteEngagementService.getForBrowserContext(Profile.getLastUsedRegularProfile()) .resetBaseScoreForUrl(url, 10); });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java index e2a7b8a..213c8ed1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java
@@ -13,8 +13,6 @@ import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.is; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; import static org.chromium.chrome.test.util.ViewUtils.onViewWaiting; @@ -47,9 +45,6 @@ import org.chromium.components.signin.identitymanager.ConsentLevel; import org.chromium.content_public.browser.test.util.TestThreadUtils; -/** - * Tests {@link AccountManagementFragment}. - */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class AccountManagementFragmentTest { @@ -72,16 +67,9 @@ public final ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus().build(); - private Profile mSpyProfile; - @Before public void setUp() { mActivityTestRule.startMainActivityOnBlankPage(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - mSpyProfile = spy(Profile.getLastUsedRegularProfile()); - when(mSpyProfile.isChild()).thenReturn(false); - Profile.setLastUsedProfileForTesting(mSpyProfile); - }); } @Test @@ -122,32 +110,6 @@ } @Test - @MediumTest - @Feature("RenderTest") - @Features.DisableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY) - public void testAccountManagementViewForChildAccountLegacy() throws Exception { - when(mSpyProfile.isChild()).thenReturn(true); - mAccountManagerTestRule.addTestAccountThenSigninAndEnableSync(); - mSettingsActivityTestRule.startSettingsActivity(); - View view = mSettingsActivityTestRule.getFragment().getView(); - onViewWaiting(allOf(is(view), isDisplayed())); - mRenderTestRule.render(view, "account_management_fragment_for_child_account_legacy"); - } - - @Test - @MediumTest - @Feature("RenderTest") - @Features.EnableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY) - public void testAccountManagementViewForChildAccount() throws Exception { - when(mSpyProfile.isChild()).thenReturn(true); - mAccountManagerTestRule.addTestAccountThenSigninAndEnableSync(); - mSettingsActivityTestRule.startSettingsActivity(); - View view = mSettingsActivityTestRule.getFragment().getView(); - onViewWaiting(allOf(is(view), isDisplayed())); - mRenderTestRule.render(view, "account_management_fragment_for_child_account"); - } - - @Test @SmallTest @Features.EnableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY) public void testSignOutUserWithoutShowingSignOutDialog() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java index ad981e5..59b2136d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabDataTest.java
@@ -5,9 +5,11 @@ package org.chromium.chrome.browser.tab.state; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -31,11 +33,16 @@ import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher; import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcherJni; import org.chromium.chrome.browser.endpoint_fetcher.EndpointResponse; +import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridge; +import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridge.OptimizationGuideCallback; +import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridgeJni; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.MockTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeBrowserTestRule; +import org.chromium.components.optimization_guide.OptimizationGuideDecision; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.url.GURL; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -58,6 +65,12 @@ @Mock EndpointFetcher.Natives mEndpointFetcherJniMock; + @Mock + OptimizationGuideBridge.Natives mOptimizationGuideBridgeJniMock; + + // Tracks if the endpoint fetcher has been called once or not + private boolean mCalledOnce; + private static final long PRICE_MICROS = 123456789012345L; private static final long UPDATED_PRICE_MICROS = 287000000L; private static final long HIGH_PRICE_MICROS = 141000000L; @@ -89,6 +102,10 @@ public void setUp() { MockitoAnnotations.initMocks(this); mMocker.mock(EndpointFetcherJni.TEST_HOOKS, mEndpointFetcherJniMock); + mMocker.mock(OptimizationGuideBridgeJni.TEST_HOOKS, mOptimizationGuideBridgeJniMock); + // Ensure native pointer is initialized + doReturn(1L).when(mOptimizationGuideBridgeJniMock).init(); + mockOptimizationGuideResponse(OptimizationGuideDecision.TRUE); PersistedTabDataConfiguration.setUseTestConfig(true); } @@ -146,6 +163,39 @@ acquireSemaphore(semaphore); } + @SmallTest + @Test + public void testShoppingBloomFilterNotShoppingWebsite() { + mockEndpointResponse(ENDPOINT_RESPONSE_INITIAL); + mockOptimizationGuideResponse(OptimizationGuideDecision.FALSE); + Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO); + Semaphore semaphore = new Semaphore(0); + TestThreadUtils.runOnUiThreadBlocking(() -> { + ShoppingPersistedTabData.from( + tab, (shoppingPersistedTabData) -> { semaphore.release(); }); + }); + acquireSemaphore(semaphore); + verifyEndpointFetcherCalled(0); + } + + @SmallTest + @Test + public void testShoppingBloomFilterShoppingWebsite() { + for (@OptimizationGuideDecision int decision : + new int[] {OptimizationGuideDecision.TRUE, OptimizationGuideDecision.UNKNOWN}) { + mockEndpointResponse(ENDPOINT_RESPONSE_INITIAL); + mockOptimizationGuideResponse(decision); + Tab tab = createTabOnUiThread(TAB_ID, IS_INCOGNITO); + Semaphore semaphore = new Semaphore(0); + TestThreadUtils.runOnUiThreadBlocking(() -> { + ShoppingPersistedTabData.from( + tab, (shoppingPersistedTabData) -> { semaphore.release(); }); + }); + acquireSemaphore(semaphore); + verifyEndpointFetcherCalled(1); + } + } + private long shoppingPriceChange(Tab tab) { final Semaphore initialSemaphore = new Semaphore(0); final Semaphore updateSemaphore = new Semaphore(0); @@ -619,4 +669,19 @@ throw new RuntimeException(e); } } + + private void mockOptimizationGuideResponse(@OptimizationGuideDecision int decision) { + doAnswer(new Answer<Void>() { + @Override + public Void answer(InvocationOnMock invocation) { + OptimizationGuideCallback callback = + (OptimizationGuideCallback) invocation.getArguments()[3]; + callback.onOptimizationGuideDecision(decision, null); + return null; + } + }) + .when(mOptimizationGuideBridgeJniMock) + .canApplyOptimization( + anyLong(), any(GURL.class), anyInt(), any(OptimizationGuideCallback.class)); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java index 39821a2..48640dc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/AsyncTabCreationParamsManagerTest.java
@@ -11,6 +11,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.UiThreadTest; +import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.LoadUrlParams; @@ -19,6 +20,7 @@ * Tests that the AsyncTabCreationParamsManager works as expected. */ @RunWith(ChromeJUnit4ClassRunner.class) +@Batch(Batch.UNIT_TESTS) public class AsyncTabCreationParamsManagerTest { @Test @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java index 413e893e..817a66c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ContextMenuLoadUrlParamsTest.java
@@ -12,10 +12,13 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; @@ -29,10 +32,10 @@ import org.chromium.chrome.browser.tabmodel.NextTabPolicy.NextTabPolicySupplier; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; import org.chromium.chrome.test.util.browser.contextmenu.RevampedContextMenuUtils; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.net.test.EmbeddedTestServer; import java.util.concurrent.TimeoutException; import java.util.regex.Pattern; @@ -42,26 +45,30 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@Batch(Batch.PER_CLASS) public class ContextMenuLoadUrlParamsTest { + @ClassRule + public static ChromeTabbedActivityTestRule sActivityTestRule = + new ChromeTabbedActivityTestRule(); + @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + public BlankCTATabInitialStateRule mBlankCTATabInitialStateRule = + new BlankCTATabInitialStateRule(sActivityTestRule, false); private static final String HTML_PATH = "/chrome/test/data/android/contextmenu/context_menu_test.html"; private static final Pattern SCHEME_SEPARATOR_RE = Pattern.compile("://"); // Load parameters of the last call to openNewTab(). - LoadUrlParams mOpenNewTabLoadUrlParams; - - private EmbeddedTestServer mTestServer; + private static LoadUrlParams sOpenNewTabLoadUrlParams; // Records parameters of calls to TabModelSelector methods and otherwise behaves like // TabModelSelectorImpl. - class RecordingTabModelSelector extends TabModelSelectorImpl { + private static class RecordingTabModelSelector extends TabModelSelectorImpl { @Override public Tab openNewTab(LoadUrlParams loadUrlParams, @TabLaunchType int type, Tab parent, boolean incognito) { - mOpenNewTabLoadUrlParams = loadUrlParams; + sOpenNewTabLoadUrlParams = loadUrlParams; return super.openNewTab(loadUrlParams, type, parent, incognito); } @@ -75,8 +82,8 @@ } } - @Before - public void setUp() throws Exception { + @BeforeClass + public static void beforeClass() throws Exception { // Plant RecordingTabModelSelector as the TabModelSelector used in Main. The factory has to // be set before super.setUp(), as super.setUp() creates Main and consequently the // TabModelSelector. @@ -90,18 +97,18 @@ new ChromeTabModelFilterFactory(), selectorIndex); } }); - mActivityTestRule.startMainActivityOnBlankPage(); + } + + @Before + public void setUp() throws Exception { TestThreadUtils.runOnUiThreadBlocking( () -> { FirstRunStatus.setFirstRunFlowComplete(true); }); - - mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); } @After public void tearDown() { TestThreadUtils.runOnUiThreadBlocking( () -> { FirstRunStatus.setFirstRunFlowComplete(false); }); - mTestServer.stopAndDestroyServer(); } /** @@ -111,12 +118,12 @@ @MediumTest @Feature({"Browser"}) public void testOpenInNewTabReferrer() throws TimeoutException { - triggerContextMenuLoad(mTestServer.getURL(HTML_PATH), "testLink", + triggerContextMenuLoad(sActivityTestRule.getTestServer().getURL(HTML_PATH), "testLink", R.id.contextmenu_open_in_new_tab); - Assert.assertNotNull(mOpenNewTabLoadUrlParams); - Assert.assertEquals( - mTestServer.getURL(HTML_PATH), mOpenNewTabLoadUrlParams.getReferrer().getUrl()); + Assert.assertNotNull(sOpenNewTabLoadUrlParams); + Assert.assertEquals(sActivityTestRule.getTestServer().getURL(HTML_PATH), + sOpenNewTabLoadUrlParams.getReferrer().getUrl()); } /** @@ -126,11 +133,11 @@ @MediumTest @Feature({"Browser"}) public void testOpenInIncognitoTabNoReferrer() throws TimeoutException { - triggerContextMenuLoad(mTestServer.getURL(HTML_PATH), "testLink", + triggerContextMenuLoad(sActivityTestRule.getTestServer().getURL(HTML_PATH), "testLink", R.id.contextmenu_open_in_incognito_tab); - Assert.assertNotNull(mOpenNewTabLoadUrlParams); - Assert.assertNull(mOpenNewTabLoadUrlParams.getReferrer()); + Assert.assertNotNull(sOpenNewTabLoadUrlParams); + Assert.assertNull(sOpenNewTabLoadUrlParams.getReferrer()); } /** @@ -140,22 +147,22 @@ @MediumTest @Feature({"Browser"}) public void testOpenInNewTabSanitizeReferrer() throws TimeoutException { - String testUrl = mTestServer.getURL(HTML_PATH); + String testUrl = sActivityTestRule.getTestServer().getURL(HTML_PATH); String[] schemeAndUrl = SCHEME_SEPARATOR_RE.split(testUrl, 2); Assert.assertEquals(2, schemeAndUrl.length); String testUrlUserPass = schemeAndUrl[0] + "://user:pass@" + schemeAndUrl[1]; triggerContextMenuLoad(testUrlUserPass, "testLink", R.id.contextmenu_open_in_new_tab); - Assert.assertNotNull(mOpenNewTabLoadUrlParams); - Assert.assertEquals(testUrl, mOpenNewTabLoadUrlParams.getReferrer().getUrl()); + Assert.assertNotNull(sOpenNewTabLoadUrlParams); + Assert.assertEquals(testUrl, sOpenNewTabLoadUrlParams.getReferrer().getUrl()); } private void triggerContextMenuLoad(String url, String openerDomId, int menuItemId) throws TimeoutException { - mActivityTestRule.loadUrl(url); - mActivityTestRule.assertWaitForPageScaleFactorMatch(0.5f); - Tab tab = mActivityTestRule.getActivity().getActivityTab(); + sActivityTestRule.loadUrl(url); + sActivityTestRule.assertWaitForPageScaleFactorMatch(0.5f); + Tab tab = sActivityTestRule.getActivity().getActivityTab(); RevampedContextMenuUtils.selectContextMenuItem(InstrumentationRegistry.getInstrumentation(), - mActivityTestRule.getActivity(), tab, openerDomId, menuItemId); + sActivityTestRule.getActivity(), tab, openerDomId, menuItemId); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java index 6d38eef..56ccce071 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelImplTest.java
@@ -12,12 +12,13 @@ import androidx.test.filters.SmallTest; import org.hamcrest.Matchers; -import org.junit.Before; +import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.test.util.ApplicationTestUtils; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; @@ -26,6 +27,7 @@ import org.chromium.chrome.browser.tab.TabStateExtractor; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -34,25 +36,26 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@Batch(Batch.PER_CLASS) public class TabModelImplTest { - @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + @ClassRule + public static ChromeTabbedActivityTestRule sActivityTestRule = + new ChromeTabbedActivityTestRule(); - @Before - public void setUp() { - mActivityTestRule.startMainActivityOnBlankPage(); - } + @Rule + public BlankCTATabInitialStateRule mBlankCTATabInitialStateRule = + new BlankCTATabInitialStateRule(sActivityTestRule, false); private void createTabs(int tabsCount, boolean isIncognito, String url) { TabModel tabModel = - mActivityTestRule.getActivity().getTabModelSelector().getModel(isIncognito); + sActivityTestRule.getActivity().getTabModelSelector().getModel(isIncognito); int oldTabsCount = tabModel.getCount(); for (int i = 0; i < tabsCount; i++) { ChromeTabUtils.newTabFromMenu(InstrumentationRegistry.getInstrumentation(), - mActivityTestRule.getActivity(), isIncognito, url == null); + sActivityTestRule.getActivity(), isIncognito, url == null); - if (url != null) mActivityTestRule.loadUrl(url); + if (url != null) sActivityTestRule.loadUrl(url); } CriteriaHelper.pollUiThread(() -> { @@ -64,12 +67,12 @@ @SmallTest public void validIndexAfterRestored_FromColdStart() { TabModel normalTabModel = - mActivityTestRule.getActivity().getTabModelSelector().getModel(false); + sActivityTestRule.getActivity().getTabModelSelector().getModel(false); assertEquals(1, normalTabModel.getCount()); assertNotEquals(TabModel.INVALID_TAB_INDEX, normalTabModel.index()); TabModel incognitoTabModel = - mActivityTestRule.getActivity().getTabModelSelector().getModel(true); + sActivityTestRule.getActivity().getTabModelSelector().getModel(true); assertEquals(0, incognitoTabModel.getCount()); assertEquals(TabModel.INVALID_TAB_INDEX, incognitoTabModel.index()); } @@ -81,23 +84,23 @@ // Need to wait for contentsState to be initialized for the tab to restore correctly. CriteriaHelper.pollUiThread( () - -> TabStateExtractor.from(mActivityTestRule.getActivity().getActivityTab()) + -> TabStateExtractor.from(sActivityTestRule.getActivity().getActivityTab()) .contentsState != null); - ApplicationTestUtils.finishActivity(mActivityTestRule.getActivity()); + ApplicationTestUtils.finishActivity(sActivityTestRule.getActivity()); - mActivityTestRule.startMainActivityOnBlankPage(); + sActivityTestRule.startMainActivityOnBlankPage(); TabModel normalTabModel = - mActivityTestRule.getActivity().getTabModelSelector().getModel(false); + sActivityTestRule.getActivity().getTabModelSelector().getModel(false); // Tab count is 2, because startMainActivityOnBlankPage() is called twice. assertEquals(2, normalTabModel.getCount()); assertNotEquals(TabModel.INVALID_TAB_INDEX, normalTabModel.index()); // No incognito tabs are restored from a cold start. TabModel incognitoTabModel = - mActivityTestRule.getActivity().getTabModelSelector().getModel(true); + sActivityTestRule.getActivity().getTabModelSelector().getModel(true); assertEquals(0, incognitoTabModel.getCount()); assertEquals(TabModel.INVALID_TAB_INDEX, incognitoTabModel.index()); } @@ -106,8 +109,8 @@ @SmallTest public void validIndexAfterRestored_FromPreviousActivity() { - ChromeTabbedActivity newActivity = - ApplicationTestUtils.recreateActivity(mActivityTestRule.getActivity()); + sActivityTestRule.recreateActivity(); + ChromeTabbedActivity newActivity = sActivityTestRule.getActivity(); CriteriaHelper.pollUiThread(newActivity.getTabModelSelector()::isTabStateInitialized); TabModel normalTabModel = newActivity.getTabModelSelector().getModel(false); @@ -123,19 +126,19 @@ @SmallTest public void validIndexAfterRestored_FromPreviousActivity_WithIncognitoTabs() { TestThreadUtils.runOnUiThreadBlocking(() -> { - mActivityTestRule.getActivity().getActivityTab().setIsTabSaveEnabled(false); + sActivityTestRule.getActivity().getActivityTab().setIsTabSaveEnabled(false); }); createTabs(1, true, "about:blank"); // Need to wait for contentsState to be initialized for the tab to restore correctly. CriteriaHelper.pollUiThread( () - -> TabStateExtractor.from(mActivityTestRule.getActivity().getActivityTab()) + -> TabStateExtractor.from(sActivityTestRule.getActivity().getActivityTab()) .contentsState != null); - ChromeTabbedActivity newActivity = - ApplicationTestUtils.recreateActivity(mActivityTestRule.getActivity()); + sActivityTestRule.recreateActivity(); + ChromeTabbedActivity newActivity = sActivityTestRule.getActivity(); CriteriaHelper.pollUiThread(newActivity.getTabModelSelector()::isTabStateInitialized); TabModel normalTabModel = newActivity.getTabModelSelector().getModel(false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java index 7a5aa84..02af0f0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabObserverTest.java
@@ -7,13 +7,14 @@ import androidx.test.filters.SmallTest; import org.junit.Assert; -import org.junit.Rule; +import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.ObserverList.RewindableIterator; import org.chromium.base.ThreadUtils; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.Batch; import org.chromium.chrome.browser.tab.MockTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabCreationState; @@ -30,9 +31,10 @@ * Tests for the TabModelSelectorTabObserver. */ @RunWith(BaseJUnit4ClassRunner.class) +@Batch(Batch.PER_CLASS) public class TabModelSelectorTabObserverTest { - @Rule - public final TabModelSelectorObserverTestRule mTestRule = + @ClassRule + public static final TabModelSelectorObserverTestRule sTestRule = new TabModelSelectorObserverTestRule(); @Test @@ -41,7 +43,7 @@ TestTabModelSelectorTabObserver observer = createTabModelSelectorTabObserver(); Tab tab = createTestTab(false); assertTabDoesNotHaveObserver(tab, observer, /* checkUnregistration= */ false); - addTab(mTestRule.getNormalTabModel(), tab); + addTab(sTestRule.getNormalTabModel(), tab); assertTabHasObserver(tab, observer); } @@ -50,9 +52,9 @@ public void testClosingTab() { TestTabModelSelectorTabObserver observer = createTabModelSelectorTabObserver(); Tab tab = createTestTab(false); - addTab(mTestRule.getNormalTabModel(), tab); + addTab(sTestRule.getNormalTabModel(), tab); assertTabHasObserver(tab, observer); - closeTab(mTestRule.getNormalTabModel(), tab); + closeTab(sTestRule.getNormalTabModel(), tab); assertTabDoesNotHaveObserver(tab, observer, true); } @@ -61,9 +63,9 @@ public void testRemovingTab() { TestTabModelSelectorTabObserver observer = createTabModelSelectorTabObserver(); Tab tab = createTestTab(false); - addTab(mTestRule.getNormalTabModel(), tab); + addTab(sTestRule.getNormalTabModel(), tab); assertTabHasObserver(tab, observer); - removeTab(mTestRule.getNormalTabModel(), tab); + removeTab(sTestRule.getNormalTabModel(), tab); assertTabDoesNotHaveObserver(tab, observer, true); } @@ -71,14 +73,14 @@ @SmallTest public void testPreExistingTabs() { Tab normalTab1 = createTestTab(false); - addTab(mTestRule.getNormalTabModel(), normalTab1); + addTab(sTestRule.getNormalTabModel(), normalTab1); Tab normalTab2 = createTestTab(false); - addTab(mTestRule.getNormalTabModel(), normalTab2); + addTab(sTestRule.getNormalTabModel(), normalTab2); Tab incognitoTab1 = createTestTab(true); - addTab(mTestRule.getIncognitoTabModel(), incognitoTab1); + addTab(sTestRule.getIncognitoTabModel(), incognitoTab1); Tab incognitoTab2 = createTestTab(true); - addTab(mTestRule.getIncognitoTabModel(), incognitoTab2); + addTab(sTestRule.getIncognitoTabModel(), incognitoTab2); TestTabModelSelectorTabObserver observer = createTabModelSelectorTabObserver(); assertTabHasObserver(normalTab1, observer); @@ -91,9 +93,9 @@ @SmallTest public void testDestroyRemovesObserver() { Tab normalTab1 = createTestTab(false); - addTab(mTestRule.getNormalTabModel(), normalTab1); + addTab(sTestRule.getNormalTabModel(), normalTab1); Tab incognitoTab1 = createTestTab(true); - addTab(mTestRule.getIncognitoTabModel(), incognitoTab1); + addTab(sTestRule.getIncognitoTabModel(), incognitoTab1); TestTabModelSelectorTabObserver observer = createTabModelSelectorTabObserver(); assertTabHasObserver(normalTab1, observer); @@ -116,20 +118,20 @@ } }; TestTabModelSelectorTabObserver observer = createTabModelSelectorTabObserver(); - selector.initialize(mTestRule.getNormalTabModel(), mTestRule.getIncognitoTabModel()); + selector.initialize(sTestRule.getNormalTabModel(), sTestRule.getIncognitoTabModel()); Tab normalTab1 = createTestTab(false); - addTab(mTestRule.getNormalTabModel(), normalTab1); + addTab(sTestRule.getNormalTabModel(), normalTab1); assertTabHasObserver(normalTab1, observer); Tab incognitoTab1 = createTestTab(true); - addTab(mTestRule.getIncognitoTabModel(), incognitoTab1); + addTab(sTestRule.getIncognitoTabModel(), incognitoTab1); assertTabHasObserver(incognitoTab1, observer); } private TestTabModelSelectorTabObserver createTabModelSelectorTabObserver() { return ThreadUtils.runOnUiThreadBlockingNoException( - () -> new TestTabModelSelectorTabObserver(mTestRule.getSelector())); + () -> new TestTabModelSelectorTabObserver(sTestRule.getSelector())); } private Tab createTestTab(boolean incognito) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java index 899dbae..9d03941 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -13,6 +13,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,6 +23,7 @@ import org.chromium.base.task.AsyncTask; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.AdvancedMockContext; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; @@ -60,6 +62,7 @@ /** Tests for the TabPersistentStore. */ @RunWith(BaseJUnit4ClassRunner.class) +@Batch(Batch.PER_CLASS) public class TabPersistentStoreTest { @Rule public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); @@ -198,7 +201,7 @@ } } - private final TabModelSelectorFactory mMockTabModelSelectorFactory = + private static final TabModelSelectorFactory sMockTabModelSelectorFactory = new TabModelSelectorFactory() { @Override public TabModelSelector buildSelector(Activity activity, @@ -211,20 +214,25 @@ } } }; + private static TabWindowManagerImpl sTabWindowManager; /** Class for mocking out the directory containing all of the TabState files. */ private TestTabModelDirectory mMockDirectory; private AdvancedMockContext mAppContext; private SharedPreferencesManager mPreferences; - private TabWindowManagerImpl mTabWindowManager; + + @BeforeClass + public static void beforeClassSetUp() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + TabWindowManagerSingleton.setTabModelSelectorFactoryForTesting( + sMockTabModelSelectorFactory); + sTabWindowManager = (TabWindowManagerImpl) TabWindowManagerSingleton.getInstance(); + }); + } @Before public void setUp() { TestThreadUtils.runOnUiThreadBlocking(() -> { - TabWindowManagerSingleton.setTabModelSelectorFactoryForTesting( - mMockTabModelSelectorFactory); - mTabWindowManager = (TabWindowManagerImpl) TabWindowManagerSingleton.getInstance(); - mChromeActivity = new ChromeActivity() { @Override protected boolean handleBackPressed() { @@ -268,7 +276,7 @@ @After public void tearDown() { TestThreadUtils.runOnUiThreadBlocking(() -> { - mTabWindowManager.onActivityStateChange(mChromeActivity, ActivityState.DESTROYED); + sTabWindowManager.onActivityStateChange(mChromeActivity, ActivityState.DESTROYED); }); mMockDirectory.tearDown(); } @@ -705,9 +713,9 @@ public TestTabModelSelector call() { // Clear any existing TestTabModelSelector (required when // createAndRestoreRealTabModelImpls is called multiple times in one test). - mTabWindowManager.onActivityStateChange( + sTabWindowManager.onActivityStateChange( mChromeActivity, ActivityState.DESTROYED); - return (TestTabModelSelector) mTabWindowManager.requestSelector( + return (TestTabModelSelector) sTabWindowManager.requestSelector( mChromeActivity, mChromeActivity, null, 0); } });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java index 2309ac9..9864a32 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java
@@ -10,13 +10,14 @@ import org.junit.After; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.chromium.base.ActivityState; import org.chromium.base.ApplicationStatus; import org.chromium.base.test.UiThreadTest; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton; @@ -39,9 +40,10 @@ * {@link Activity}s getting destroyed, etc. */ @RunWith(ChromeJUnit4ClassRunner.class) +@Batch(Batch.UNIT_TESTS) public class TabWindowManagerTest { private List<Activity> mActivities = new ArrayList<>(); - private final TabModelSelectorFactory mMockTabModelSelectorFactory = + private static final TabModelSelectorFactory sMockTabModelSelectorFactory = new TabModelSelectorFactory() { @Override public TabModelSelector buildSelector(Activity activity, @@ -51,10 +53,10 @@ } }; - @Before - public void setUp() { + @BeforeClass + public static void setUp() { TabWindowManagerSingleton.setTabModelSelectorFactoryForTesting( - mMockTabModelSelectorFactory); + sMockTabModelSelectorFactory); } private ChromeActivity buildActivity() {
diff --git a/chrome/android/modules/chrome_bundle_tmpl.gni b/chrome/android/modules/chrome_bundle_tmpl.gni index 0b0dd95b..0f67ea2f 100644 --- a/chrome/android/modules/chrome_bundle_tmpl.gni +++ b/chrome/android/modules/chrome_bundle_tmpl.gni
@@ -22,96 +22,37 @@ _bundle_target_name = target_name _package_id = 126 # == 0x7e. _extra_modules = [] - _module_descs = [] + _module_descs = invoker.module_descs _enable_chrome_module = enable_chrome_module && invoker.is_monochrome_or_trichrome # If enable_chrome_module is true, //chrome Java code and resources will be # split out into a chrome DFM in Monochrome and Trichrome bundles. This will - # additionally cause a few other changes in the structure of the APK: - # - All other DFMs Java code and resources will be folded into the chrome DFM. - # - All native code from other DFMs will be moved to the base module. - # - All //chrome-specific manifest definitions (e.g. activities, services) - # will be moved to the chrome DFM AndroidManifest.xml. + # additionally move all //chrome-specific manifest definitions (e.g. + # activities, services) to the chrome DFM AndroidManifest.xml. if (_enable_chrome_module) { _base_target_gen_dir = get_label_info(invoker.base_module_target, "target_gen_dir") _base_name = get_label_info(invoker.base_module_target, "name") _split_android_manifest = "${_base_target_gen_dir}/manifest/${_base_name}/AndroidManifest_split.xml" - _java_deps = [] - _paks = [] - _pak_deps = [] - foreach(_module_desc, invoker.module_descs) { - _supports_isolated_split = - defined(_module_desc.supports_isolated_split) && - _module_desc.supports_isolated_split - _uses_chrome_split = - defined(_module_desc.uses_split) && - _module_desc.uses_split == "chrome" && enable_chrome_child_modules - if (_supports_isolated_split || _uses_chrome_split) { - _module_descs += [ _module_desc ] - } else { - _shared_libraries = [] - if (defined(_module_desc.native_deps) && - _module_desc.native_deps != []) { - _arch = "" - _toolchain = "" - if (android_64bit_target_cpu) { - if (invoker.is_64_bit_browser) { - _arch = "_64" - } else { - _toolchain = "($android_secondary_abi_toolchain)" - } - } - _shared_libraries += [ "//chrome/android:libmonochrome${_arch}_${_module_desc.name}${_toolchain}" ] - } - _module_desc_target_name = - "${target_name}__${_module_desc.name}__module_desc_java" - module_desc_java(_module_desc_target_name) { - module_name = _module_desc.name - shared_libraries = _shared_libraries - if (defined(_module_desc.pak_deps)) { - paks = _module_desc.paks - } - if (defined(_module_desc.load_native_on_get_impl)) { - load_native_on_get_impl = _module_desc.load_native_on_get_impl - } - } - _java_deps += - _module_desc.java_deps + [ ":${_module_desc_target_name}" ] - if (defined(_module_desc.pak_deps)) { - _paks += _module_desc.paks - _pak_deps += _module_desc.pak_deps - } - } - } chrome_module_desc = { name = "chrome" android_manifest = _split_android_manifest android_manifest_dep = "${invoker.base_module_target}__android_manifest__split" - java_deps = [ "//chrome/android:chrome_all_java" ] + _java_deps + java_deps = [ "//chrome/android:chrome_all_java" ] if (enable_arcore) { java_deps += [ "//components/webxr/android:ar_java", "//third_party/arcore-android-sdk-client:com_google_ar_core_java", ] } - pak_deps = _pak_deps - paks = _paks if (defined(invoker.chrome_deps)) { java_deps += invoker.chrome_deps } - - # Native code for all DFMs is moved to the base module's library, and paks - # for DFMs will use the value of load_native_on_get_impl from the module - # descriptor for that DFM. - load_native_on_get_impl = false } _module_descs += [ chrome_module_desc ] - } else { - _module_descs = invoker.module_descs } _enable_isolated_splits =
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 9b9601e1..484f830 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -2053,6 +2053,20 @@ desc="The title of a download notification inidcating that the file may be malicious, and the Advanced Protection Program recommends sending the file to Google. This message is for screen reader users"> <ph name="FILE_NAME">$1<ex>file.exe</ex></ph> is being scanned. </message> + <if expr="is_macosx"> + <then> + <message name="IDS_PROMPT_DOWNLOAD_MIXED_CONTENT_BLOCKED_ACCESSIBLE_ALERT" + desc="The title of a download notification inidcating that the download was delivered insecurely. This message is for screen reader users"> + <ph name="FILE_NAME">$1<ex>file.exe</ex></ph> can't be downloaded securely. + </message> + </then> + <else> + <message name="IDS_PROMPT_DOWNLOAD_MIXED_CONTENT_BLOCKED_ACCESSIBLE_ALERT" + desc="The title of a download notification inidcating that the download was delivered insecurely. This message is for screen reader users"> + <ph name="FILE_NAME">$1<ex>file.exe</ex></ph> can't be downloaded securely. Press Shift+F6 to cycle to the downloads bar area. + </message> + </else> + </if> <!-- Download Notification Labels --> <message name="IDS_DOWNLOAD_NOTIFICATION_COPY_TO_CLIPBOARD"
diff --git a/chrome/app/generated_resources_grd/IDS_PROMPT_DOWNLOAD_MIXED_CONTENT_BLOCKED_ACCESSIBLE_ALERT.png.sha1 b/chrome/app/generated_resources_grd/IDS_PROMPT_DOWNLOAD_MIXED_CONTENT_BLOCKED_ACCESSIBLE_ALERT.png.sha1 new file mode 100644 index 0000000..d627135f1 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PROMPT_DOWNLOAD_MIXED_CONTENT_BLOCKED_ACCESSIBLE_ALERT.png.sha1
@@ -0,0 +1 @@ +5a7ce03653dab66e283e8303fa279a44ea171a81 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index adb8a3d..b877bd8 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -479,12 +479,8 @@ "engagement/important_sites_util.h", "engagement/site_engagement_helper.cc", "engagement/site_engagement_helper.h", - "engagement/site_engagement_metrics.cc", - "engagement/site_engagement_metrics.h", "engagement/site_engagement_observer.cc", "engagement/site_engagement_observer.h", - "engagement/site_engagement_score.cc", - "engagement/site_engagement_score.h", "engagement/site_engagement_service.cc", "engagement/site_engagement_service.h", "engagement/site_engagement_service_factory.cc", @@ -819,6 +815,7 @@ "metrics/network_quality_estimator_provider_impl.h", "metrics/oom/out_of_memory_reporter.cc", "metrics/oom/out_of_memory_reporter.h", + "metrics/power/battery_level_provider.h", "metrics/process_memory_metrics_emitter.cc", "metrics/process_memory_metrics_emitter.h", "metrics/renderer_uptime_tracker.cc", @@ -2119,7 +2116,6 @@ "//components/language/content/browser/ulp_language_code_locator", "//components/language/core/browser", "//components/language/core/common", - "//components/language_usage_metrics", "//components/leveldb_proto", "//components/lookalikes/core", "//components/lookalikes/core:features", @@ -2228,6 +2224,7 @@ "//components/signin/public/base:signin_buildflags", "//components/signin/public/identity_manager", "//components/signin/public/webdata", + "//components/site_engagement/content", "//components/site_engagement/core/mojom:mojo_bindings", "//components/site_isolation", "//components/soda:constants", @@ -4962,8 +4959,9 @@ "media_galleries/mac/mtp_device_delegate_impl_mac.mm", "memory_details_mac.cc", "metrics/chrome_browser_main_extra_parts_metrics_mac.mm", - "metrics/power_metrics_provider_mac.h", - "metrics/power_metrics_provider_mac.mm", + "metrics/power/battery_level_provider_mac.mm", + "metrics/power/power_metrics_provider_mac.h", + "metrics/power/power_metrics_provider_mac.mm", "notifications/alert_dispatcher_mac.h", "notifications/notification_platform_bridge_mac.h", "notifications/notification_platform_bridge_mac.mm",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 260402d..c7e8543 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -160,7 +160,6 @@ "+components/language/content/browser", "+components/language/core/browser", "+components/language/core/common", - "+components/language_usage_metrics", "+components/leveldb_proto/content", "+components/leveldb_proto/public", "+components/leveldb_proto/testing",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 0e0d7d46..dd05591 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2668,13 +2668,6 @@ flag_descriptions::kFractionalScrollOffsetsName, flag_descriptions::kFractionalScrollOffsetsDescription, kOsAll, FEATURE_VALUE_TYPE(features::kFractionalScrollOffsets)}, -#if defined(USE_AURA) - {"overlay-scrollbars", flag_descriptions::kOverlayScrollbarsName, - flag_descriptions::kOverlayScrollbarsDescription, - // Uses the system preference on Mac (a different implementation). - // On Android, this is always enabled. - kOsAura, FEATURE_VALUE_TYPE(features::kOverlayScrollbar)}, -#endif // USE_AURA {"enable-quic", flag_descriptions::kQuicName, flag_descriptions::kQuicDescription, kOsAll, ENABLE_DISABLE_VALUE_TYPE(switches::kEnableQuic, switches::kDisableQuic)}, @@ -3360,6 +3353,10 @@ flag_descriptions::kDesktopPWAsTabStripLinkCapturingDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kDesktopPWAsTabStripLinkCapturing)}, + {"enable-desktop-pwas-link-capturing", + flag_descriptions::kDesktopPWAsLinkCapturingName, + flag_descriptions::kDesktopPWAsLinkCapturingDescription, kOsDesktop, + FEATURE_VALUE_TYPE(blink::features::kWebAppEnableLinkCapturing)}, {"enable-desktop-pwas-run-on-os-login", flag_descriptions::kDesktopPWAsRunOnOsLoginName, flag_descriptions::kDesktopPWAsRunOnOsLoginDescription, kOsWin | kOsLinux, @@ -3427,11 +3424,11 @@ flag_descriptions::kMacV2GPUSandboxDescription, kOsMac, FEATURE_VALUE_TYPE(features::kMacV2GPUSandbox)}, #endif // OS_MAC -#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) +#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) || defined(OS_MAC) {"web-share", flag_descriptions::kWebShareName, flag_descriptions::kWebShareDescription, kOsWin | kOsCrOS, FEATURE_VALUE_TYPE(features::kWebShare)}, -#endif // BUILDFLAG(IS_CHROMEOS_ASH) || OS_WIN +#endif // BUILDFLAG(IS_CHROMEOS_ASH) || OS_WIN || OS_MAC #if BUILDFLAG(ENABLE_VR) {"webxr-incubations", flag_descriptions::kWebXrIncubationsName, flag_descriptions::kWebXrIncubationsDescription, kOsAll,
diff --git a/chrome/browser/accessibility/accessibility_labels_service.cc b/chrome/browser/accessibility/accessibility_labels_service.cc index 5bf970f..aae9ab8 100644 --- a/chrome/browser/accessibility/accessibility_labels_service.cc +++ b/chrome/browser/accessibility/accessibility_labels_service.cc
@@ -13,9 +13,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/channel_info.h" #include "chrome/common/pref_names.h" +#include "components/language/core/browser/language_usage_metrics.h" #include "components/language/core/browser/pref_names.h" #include "components/language/core/browser/url_language_histogram.h" -#include "components/language_usage_metrics/language_usage_metrics.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "components/sync_preferences/pref_service_syncable.h" @@ -107,12 +107,10 @@ const std::string& requested_language) override { base::UmaHistogramSparse( "Accessibility.ImageLabels.PageLanguage", - language_usage_metrics::LanguageUsageMetrics::ToLanguageCode( - page_language)); + language::LanguageUsageMetrics::ToLanguageCode(page_language)); base::UmaHistogramSparse( "Accessibility.ImageLabels.RequestLanguage", - language_usage_metrics::LanguageUsageMetrics::ToLanguageCode( - requested_language)); + language::LanguageUsageMetrics::ToLanguageCode(requested_language)); } private:
diff --git a/chrome/browser/android/bookmarks/bookmark_bridge.cc b/chrome/browser/android/bookmarks/bookmark_bridge.cc index 52ef5096..048b4ce7 100644 --- a/chrome/browser/android/bookmarks/bookmark_bridge.cc +++ b/chrome/browser/android/bookmarks/bookmark_bridge.cc
@@ -828,8 +828,9 @@ const BookmarkNode* node = reading_list_manager_->Add( GURL(base::android::ConvertJavaStringToUTF16(env, j_url)), base::android::ConvertJavaStringToUTF8(env, j_title)); - DCHECK(node); - return JavaBookmarkIdCreateBookmarkId(env, node->id(), GetBookmarkType(node)); + return node ? JavaBookmarkIdCreateBookmarkId(env, node->id(), + GetBookmarkType(node)) + : ScopedJavaLocalRef<jobject>(); } ScopedJavaLocalRef<jobject> BookmarkBridge::GetReadingListItem(
diff --git a/chrome/browser/android/history/history_deletion_bridge.cc b/chrome/browser/android/history/history_deletion_bridge.cc index bbc944af..744703d 100644 --- a/chrome/browser/android/history/history_deletion_bridge.cc +++ b/chrome/browser/android/history/history_deletion_bridge.cc
@@ -36,22 +36,16 @@ } HistoryDeletionBridge::HistoryDeletionBridge(const JavaRef<jobject>& jobj) - : jobj_(ScopedJavaGlobalRef<jobject>(jobj)), - profile_(ProfileManager::GetLastUsedProfile()->GetOriginalProfile()) { + : jobj_(ScopedJavaGlobalRef<jobject>(jobj)) { + Profile* profile = ProfileManager::GetLastUsedProfile()->GetOriginalProfile(); history::HistoryService* history_service = - HistoryServiceFactory::GetForProfile(profile_, + HistoryServiceFactory::GetForProfile(profile, ServiceAccessType::IMPLICIT_ACCESS); if (history_service) - history_service->AddObserver(this); + scoped_history_service_observer_.Observe(history_service); } -HistoryDeletionBridge::~HistoryDeletionBridge() { - history::HistoryService* history_service = - HistoryServiceFactory::GetForProfile(profile_, - ServiceAccessType::IMPLICIT_ACCESS); - if (history_service) - history_service->RemoveObserver(this); -} +HistoryDeletionBridge::~HistoryDeletionBridge() = default; void HistoryDeletionBridge::OnURLsDeleted( history::HistoryService* history_service, @@ -62,3 +56,8 @@ Java_HistoryDeletionBridge_onURLsDeleted( env, jobj_, CreateHistoryDeletionInfo(env, &sanitized_info)); } + +void HistoryDeletionBridge::HistoryServiceBeingDeleted( + history::HistoryService* history_service) { + scoped_history_service_observer_.Reset(); +}
diff --git a/chrome/browser/android/history/history_deletion_bridge.h b/chrome/browser/android/history/history_deletion_bridge.h index a6e49e8..ee8060a 100644 --- a/chrome/browser/android/history/history_deletion_bridge.h +++ b/chrome/browser/android/history/history_deletion_bridge.h
@@ -6,6 +6,8 @@ #define CHROME_BROWSER_ANDROID_HISTORY_HISTORY_DELETION_BRIDGE_H_ #include "base/macros.h" +#include "base/scoped_observation.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" #include "components/history/core/browser/history_types.h" @@ -13,8 +15,6 @@ class HistoryService; } // namespace history -class Profile; - // Native counterpart of HistoryDeletionBridge.java. Receives history deletion // events that originate in native code and forwards them to Java. class HistoryDeletionBridge : public history::HistoryServiceObserver { @@ -24,6 +24,8 @@ // history::HistoryServiceObserver. void OnURLsDeleted(history::HistoryService* history_service, const history::DeletionInfo& deletion_info) override; + void HistoryServiceBeingDeleted( + history::HistoryService* history_service) override; // Sanitize the DeletionInfo of empty/invalid urls before passing to java. // Fix for empty java strings being passed to the content capture service @@ -37,7 +39,9 @@ // Reference to the Java half of this bridge. Always valid. base::android::ScopedJavaGlobalRef<jobject> jobj_; - Profile* profile_; + base::ScopedObservation<history::HistoryService, + history::HistoryServiceObserver> + scoped_history_service_observer_{this}; DISALLOW_COPY_AND_ASSIGN(HistoryDeletionBridge); };
diff --git a/chrome/browser/android/provider/chrome_browser_provider.cc b/chrome/browser/android/provider/chrome_browser_provider.cc index a6def0a8..988cfc73 100644 --- a/chrome/browser/android/provider/chrome_browser_provider.cc +++ b/chrome/browser/android/provider/chrome_browser_provider.cc
@@ -814,8 +814,10 @@ // Register as observer for service we are interested. bookmark_model_->AddObserver(this); - history_service_observer_.Add(HistoryServiceFactory::GetForProfile( - profile_, ServiceAccessType::EXPLICIT_ACCESS)); + auto* history_service = HistoryServiceFactory::GetForProfile( + profile_, ServiceAccessType::EXPLICIT_ACCESS); + if (history_service) + scoped_history_service_observer_.Observe(history_service); TemplateURLService* template_service = TemplateURLServiceFactory::GetForProfile(profile_); if (!template_service->loaded()) @@ -824,7 +826,7 @@ ChromeBrowserProvider::~ChromeBrowserProvider() { bookmark_model_->RemoveObserver(this); - history_service_observer_.RemoveAll(); + scoped_history_service_observer_.Reset(); } // ------------- Provider public APIs ------------- // @@ -1192,6 +1194,11 @@ history::URLID url_id) { } +void ChromeBrowserProvider::HistoryServiceBeingDeleted( + history::HistoryService* history_service) { + scoped_history_service_observer_.Reset(); +} + bool ChromeBrowserProvider::GetJavaProviderOrDeleteSelf( ScopedJavaLocalRef<jobject>* out_ref, JNIEnv* env) {
diff --git a/chrome/browser/android/provider/chrome_browser_provider.h b/chrome/browser/android/provider/chrome_browser_provider.h index ff247d5..cb211a5 100644 --- a/chrome/browser/android/provider/chrome_browser_provider.h +++ b/chrome/browser/android/provider/chrome_browser_provider.h
@@ -10,7 +10,7 @@ #include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" #include "base/macros.h" -#include "base/scoped_observer.h" +#include "base/scoped_observation.h" #include "base/synchronization/waitable_event.h" #include "base/task/cancelable_task_tracker.h" #include "components/bookmarks/browser/base_bookmark_model_observer.h" @@ -166,6 +166,9 @@ const base::string16& term) override; void OnKeywordSearchTermDeleted(history::HistoryService* history_service, history::URLID url_id) override; + void HistoryServiceBeingDeleted( + history::HistoryService* history_service) override; + bool GetJavaProviderOrDeleteSelf( base::android::ScopedJavaLocalRef<jobject>* out_ref, JNIEnv* env); @@ -186,8 +189,9 @@ base::CancelableTaskTracker cancelable_task_tracker_; - ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_service_observer_{this}; + base::ScopedObservation<history::HistoryService, + history::HistoryServiceObserver> + scoped_history_service_observer_{this}; bool handling_extensive_changes_;
diff --git a/chrome/browser/android/usage_stats/usage_stats_bridge.cc b/chrome/browser/android/usage_stats/usage_stats_bridge.cc index 442b750..61bb846 100644 --- a/chrome/browser/android/usage_stats/usage_stats_bridge.cc +++ b/chrome/browser/android/usage_stats/usage_stats_bridge.cc
@@ -62,16 +62,10 @@ HistoryServiceFactory::GetForProfile(profile_, ServiceAccessType::IMPLICIT_ACCESS); if (history_service) - history_service->AddObserver(this); + scoped_history_service_observer_.Observe(history_service); } -UsageStatsBridge::~UsageStatsBridge() { - history::HistoryService* history_service = - HistoryServiceFactory::GetForProfile(profile_, - ServiceAccessType::IMPLICIT_ACCESS); - if (history_service) - history_service->RemoveObserver(this); -} +UsageStatsBridge::~UsageStatsBridge() = default; void UsageStatsBridge::Destroy(JNIEnv* env, const JavaRef<jobject>& j_this) { delete this; @@ -346,4 +340,9 @@ } } +void UsageStatsBridge::HistoryServiceBeingDeleted( + history::HistoryService* history_service) { + scoped_history_service_observer_.Reset(); +} + } // namespace usage_stats
diff --git a/chrome/browser/android/usage_stats/usage_stats_bridge.h b/chrome/browser/android/usage_stats/usage_stats_bridge.h index ea1e11c..997cd96 100644 --- a/chrome/browser/android/usage_stats/usage_stats_bridge.h +++ b/chrome/browser/android/usage_stats/usage_stats_bridge.h
@@ -11,7 +11,9 @@ #include "base/android/scoped_java_ref.h" #include "base/memory/weak_ptr.h" +#include "base/scoped_observation.h" #include "chrome/browser/android/usage_stats/usage_stats_database.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" namespace history { @@ -94,6 +96,8 @@ // Overridden from history::HistoryServiceObserver. void OnURLsDeleted(history::HistoryService* history_service, const history::DeletionInfo& deletion_info) override; + void HistoryServiceBeingDeleted( + history::HistoryService* history_service) override; static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); @@ -119,6 +123,10 @@ base::android::ScopedJavaGlobalRef<jobject> j_this_; + base::ScopedObservation<history::HistoryService, + history::HistoryServiceObserver> + scoped_history_service_observer_{this}; + base::WeakPtrFactory<UsageStatsBridge> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(UsageStatsBridge);
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm index dc09116..e4011497 100644 --- a/chrome/browser/app_controller_mac_browsertest.mm +++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -332,8 +332,10 @@ } // Test that for a locked last profile, a reopen event opens the User Manager. +// +// Flaky: crbug.com/1163620 IN_PROC_BROWSER_TEST_F(AppControllerNewProfileManagementBrowserTest, - LockedProfileReopenWithNoWindows) { + DISABLED_LockedProfileReopenWithNoWindows) { // The User Manager uses the system profile as its underlying profile. To // minimize flakiness due to the scheduling/descheduling of tasks on the // different threads, pre-initialize the guest profile before it is needed. @@ -555,8 +557,10 @@ } // Test that the ProfilePicker is shown when there are multiple profiles. +// +// Flaky: crbug.com/1163620 IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest, - MultiProfilePickerShown) { + DISABLED_MultiProfilePickerShown) { CreateAndWaitForSystemProfile(); AppController* ac = base::mac::ObjCCastStrict<AppController>( [[NSApplication sharedApplication] delegate]);
diff --git a/chrome/browser/background_sync/background_sync_controller_impl_unittest.cc b/chrome/browser/background_sync/background_sync_controller_impl_unittest.cc index ac2fb24..2c3d2d19 100644 --- a/chrome/browser/background_sync/background_sync_controller_impl_unittest.cc +++ b/chrome/browser/background_sync/background_sync_controller_impl_unittest.cc
@@ -10,13 +10,13 @@ #include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "chrome/browser/background_sync/background_sync_delegate_impl.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/test/base/testing_profile.h" #include "components/history/core/browser/history_database_params.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/test/test_history_database.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "components/variations/variations_associated_data.h" #include "content/public/browser/background_sync_parameters.h" #include "content/public/browser/background_sync_registration.h"
diff --git a/chrome/browser/background_sync/background_sync_delegate_impl.cc b/chrome/browser/background_sync/background_sync_delegate_impl.cc index cf94bc7..7b16a18f 100644 --- a/chrome/browser/background_sync/background_sync_delegate_impl.cc +++ b/chrome/browser/background_sync/background_sync_delegate_impl.cc
@@ -119,7 +119,7 @@ content::WebContents* web_contents, const GURL& url, double score, - site_engagement::SiteEngagementService::EngagementType engagement_type) { + site_engagement::EngagementType engagement_type) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (score == 0.0)
diff --git a/chrome/browser/background_sync/background_sync_delegate_impl.h b/chrome/browser/background_sync/background_sync_delegate_impl.h index 14e9b8d..50dc9e7 100644 --- a/chrome/browser/background_sync/background_sync_delegate_impl.h +++ b/chrome/browser/background_sync/background_sync_delegate_impl.h
@@ -51,11 +51,11 @@ #endif // defined(OS_ANDROID) // SiteEngagementObserver overrides. - void OnEngagementEvent(content::WebContents* web_contents, - const GURL& url, - double score, - site_engagement::SiteEngagementService::EngagementType - engagement_type) override; + void OnEngagementEvent( + content::WebContents* web_contents, + const GURL& url, + double score, + site_engagement::EngagementType engagement_type) override; private: Profile* profile_;
diff --git a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index e420cf2..1008b68 100644 --- a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -278,7 +278,7 @@ private void resetEngagementForUrl(final String url, final double engagement) { ThreadUtils.runOnUiThreadBlocking(() -> { // TODO (https://crbug.com/1063807): Add incognito mode tests. - SiteEngagementService.getForProfile(Profile.getLastUsedRegularProfile()) + SiteEngagementService.getForBrowserContext(Profile.getLastUsedRegularProfile()) .resetBaseScoreForUrl(url, engagement); }); }
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc index ee92a155..dadee4d 100644 --- a/chrome/browser/banners/app_banner_manager.cc +++ b/chrome/browser/banners/app_banner_manager.cc
@@ -667,7 +667,7 @@ content::WebContents* contents, const GURL& url, double score, - site_engagement::SiteEngagementService::EngagementType /*type*/) { + site_engagement::EngagementType /*type*/) { // Only trigger a banner using site engagement if: // 1. engagement increased for the web contents which we are attached to; and // 2. there are no currently active media players; and
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h index feac490..0a4eb00 100644 --- a/chrome/browser/banners/app_banner_manager.h +++ b/chrome/browser/banners/app_banner_manager.h
@@ -326,11 +326,10 @@ void WebContentsDestroyed() override; // SiteEngagementObserver overrides. - void OnEngagementEvent( - content::WebContents* web_contents, - const GURL& url, - double score, - site_engagement::SiteEngagementService::EngagementType type) override; + void OnEngagementEvent(content::WebContents* web_contents, + const GURL& url, + double score, + site_engagement::EngagementType type) override; // Subclass accessors for private fields which should not be changed outside // this class.
diff --git a/chrome/browser/banners/app_banner_manager_android.cc b/chrome/browser/banners/app_banner_manager_android.cc index 4c0a6c8..592a9b7e 100644 --- a/chrome/browser/banners/app_banner_manager_android.cc +++ b/chrome/browser/banners/app_banner_manager_android.cc
@@ -14,8 +14,6 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/android/chrome_jni_headers/AppBannerManagerHelper_jni.h" -#include "chrome/browser/android/tab_android.h" -#include "chrome/browser/android/tab_web_contents_delegate_android.h" #include "chrome/browser/android/webapk/webapk_metrics.h" #include "chrome/browser/android/webapk/webapk_ukm_recorder.h" #include "chrome/browser/android/webapps/add_to_homescreen_coordinator.h" @@ -24,6 +22,7 @@ #include "chrome/browser/banners/android/jni_headers/AppBannerManager_jni.h" #include "chrome/browser/banners/app_banner_metrics.h" #include "chrome/browser/banners/app_banner_settings_helper.h" +#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/flags/android/chrome_feature_list.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/webapps/android/features.h" @@ -67,14 +66,6 @@ // Whether to ignore the Chrome channel in QueryNativeApp() for testing. bool gIgnoreChromeChannelForTesting = false; -bool CanShowAppBanners(TabAndroid* tab) { - if (!tab) - return false; - return static_cast<android::TabWebContentsDelegateAndroid*>( - tab->web_contents()->GetDelegate()) - ->CanShowAppBanners(); -} - } // anonymous namespace AppBannerManagerAndroid::AppBannerManagerAndroid( @@ -126,12 +117,10 @@ void AppBannerManagerAndroid::RequestAppBanner(const GURL& validated_url) { JNIEnv* env = base::android::AttachCurrentThread(); - if (!Java_AppBannerManagerHelper_isEnabledForTab(env)) + if (!Java_AppBannerManagerHelper_isEnabledForTab(env) || + !WebappsClient::Get()->CanShowAppBanners(web_contents())) { return; - - TabAndroid* tab = TabAndroid::FromWebContents(web_contents()); - if (!CanShowAppBanners(tab)) - return; + } AppBannerManager::RequestAppBanner(validated_url); }
diff --git a/chrome/browser/banners/app_banner_manager_browsertest.cc b/chrome/browser/banners/app_banner_manager_browsertest.cc index 6ff73e82..2a90e31f 100644 --- a/chrome/browser/banners/app_banner_manager_browsertest.cc +++ b/chrome/browser/banners/app_banner_manager_browsertest.cc
@@ -19,12 +19,12 @@ #include "chrome/browser/banners/app_banner_manager_desktop.h" #include "chrome/browser/banners/app_banner_metrics.h" #include "chrome/browser/banners/app_banner_settings_helper.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "components/webapps/installable/installable_logging.h" #include "components/webapps/installable/installable_manager.h" #include "components/webapps/installable/installable_metrics.h"
diff --git a/chrome/browser/banners/app_banner_manager_desktop.cc b/chrome/browser/banners/app_banner_manager_desktop.cc index 7643654c..748a63b 100644 --- a/chrome/browser/banners/app_banner_manager_desktop.cc +++ b/chrome/browser/banners/app_banner_manager_desktop.cc
@@ -220,7 +220,7 @@ content::WebContents* web_contents, const GURL& url, double score, - site_engagement::SiteEngagementService::EngagementType type) { + site_engagement::EngagementType type) { if (gDisableTriggeringForTesting) return;
diff --git a/chrome/browser/banners/app_banner_manager_desktop.h b/chrome/browser/banners/app_banner_manager_desktop.h index ed9f1e3..dd52866 100644 --- a/chrome/browser/banners/app_banner_manager_desktop.h +++ b/chrome/browser/banners/app_banner_manager_desktop.h
@@ -83,11 +83,10 @@ const GURL& validated_url) override; // SiteEngagementObserver override. - void OnEngagementEvent( - content::WebContents* web_contents, - const GURL& url, - double score, - site_engagement::SiteEngagementService::EngagementType type) override; + void OnEngagementEvent(content::WebContents* web_contents, + const GURL& url, + double score, + site_engagement::EngagementType type) override; // web_app::AppRegistrarObserver: void OnWebAppInstalled(const web_app::AppId& app_id) override;
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 9478344..fee4d5f 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -119,9 +119,9 @@ #include "components/flags_ui/pref_service_flags_storage.h" #include "components/google/core/common/google_util.h" #include "components/language/content/browser/geo_language_provider.h" +#include "components/language/core/browser/language_usage_metrics.h" #include "components/language/core/browser/pref_names.h" #include "components/language/core/common/language_experiments.h" -#include "components/language_usage_metrics/language_usage_metrics.h" #include "components/metrics/call_stack_profile_metrics_provider.h" #include "components/metrics/call_stack_profile_params.h" #include "components/metrics/expired_histogram_util.h" @@ -1541,13 +1541,13 @@ browser_process_->metrics_service()->RecordBreakpadHasDebugger( base::debug::BeingDebugged()); - language_usage_metrics::LanguageUsageMetrics::RecordAcceptLanguages( + language::LanguageUsageMetrics::RecordAcceptLanguages( profile_->GetPrefs()->GetString(language::prefs::kAcceptLanguages)); - language_usage_metrics::LanguageUsageMetrics::RecordApplicationLanguage( + language::LanguageUsageMetrics::RecordApplicationLanguage( browser_process_->GetApplicationLocale()); // On ChromeOS results in a crash. https://crbug.com/1151558 #if !BUILDFLAG(IS_CHROMEOS_ASH) - language_usage_metrics::LanguageUsageMetrics::RecordPageLanguages( + language::LanguageUsageMetrics::RecordPageLanguages( *UrlLanguageHistogramFactory::GetForBrowserContext(profile_)); #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/chrome_resource_bundle_helper.cc b/chrome/browser/chrome_resource_bundle_helper.cc index 494d1f7..8ec6175 100644 --- a/chrome/browser/chrome_resource_bundle_helper.cc +++ b/chrome/browser/chrome_resource_bundle_helper.cc
@@ -10,7 +10,6 @@ #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/metrics/chrome_feature_list_creator.h" #include "chrome/browser/prefs/chrome_command_line_pref_store.h" #include "chrome/browser/prefs/chrome_pref_service_factory.h"
diff --git a/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_browsertest.cc b/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_browsertest.cc index da0946e..e75b95bb 100644 --- a/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_browsertest.cc +++ b/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_browsertest.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/supervised_user/logged_in_user_mixin.h" #include "chrome/test/base/mixin_based_in_process_browser_test.h" -#include "chromeos/constants/chromeos_switches.h" #include "components/account_id/account_id.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" @@ -89,18 +88,11 @@ logged_in_user_mixin_.GetAccountId())) {} ~ParentAccessServiceTest() override = default; - void SetUpCommandLine(base::CommandLine* command_line) override { - MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kOobeSkipPostLogin); - } - void SetUpOnMainThread() override { ASSERT_NO_FATAL_FAILURE(GetTestAccessCodeValues(&test_values_)); ParentAccessService::Get().AddObserver(test_observer_.get()); MixinBasedInProcessBrowserTest::SetUpOnMainThread(); - logged_in_user_mixin_.LogInUser(false /*issue_any_scope_token*/, - true /*wait_for_active_session*/, - true /*request_policy_update*/); + logged_in_user_mixin_.LogInUser(); } void TearDownOnMainThread() override {
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc index 3699acb..706a368 100644 --- a/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc +++ b/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/supervised_user/logged_in_user_mixin.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/mixin_based_in_process_browser_test.h" -#include "chromeos/constants/chromeos_switches.h" #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" #include "content/public/browser/notification_service.h" @@ -66,12 +65,6 @@ ~ScreenTimeControllerTest() override = default; // MixinBasedInProcessBrowserTest: - void SetUpCommandLine(base::CommandLine* command_line) override { - MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kOobeSkipPostLogin); - } - - // MixinBasedInProcessBrowserTest: void SetUpInProcessBrowserTestFixture() override { MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture(); // A basic starting policy. @@ -87,9 +80,7 @@ protected: void LogInChildAndSetupClockWithTime(const char* time) { SetupTaskRunnerWithTime(utils::TimeFromString(time)); - logged_in_user_mixin_.LogInUser(false /*issue_any_scope_token*/, - true /*wait_for_active_session*/, - true /*request_policy_update*/); + logged_in_user_mixin_.LogInUser(); MockClockForActiveUser(); }
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc b/chrome/browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc index e62ec66..d86cc2c 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc +++ b/chrome/browser/chromeos/child_accounts/time_limits/app_time_browsertest.cc
@@ -37,7 +37,6 @@ #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "content/public/test/browser_test.h" -#include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" @@ -106,10 +105,7 @@ void SetUpOnMainThread() override { MixinBasedInProcessBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(embedded_test_server()->Started()); - host_resolver()->AddIPLiteralRule("*", "127.0.0.1", "localhost"); - logged_in_user_mixin_.LogInUser(false /*issue_any_scope_token*/, - true /*wait_for_active_session*/, - true /*request_policy_update*/); + logged_in_user_mixin_.LogInUser(); arc::SetArcPlayStoreEnabledForProfile(browser()->profile(), true); arc_app_list_prefs_ = ArcAppListPrefs::Get(browser()->profile());
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/web_time_calculation_browsertest.cc b/chrome/browser/chromeos/child_accounts/time_limits/web_time_calculation_browsertest.cc index a8e0eb1..46fd50ef 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/web_time_calculation_browsertest.cc +++ b/chrome/browser/chromeos/child_accounts/time_limits/web_time_calculation_browsertest.cc
@@ -40,7 +40,6 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" -#include "net/dns/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/window_open_disposition.h" #include "url/gurl.h" @@ -101,12 +100,7 @@ ASSERT_TRUE(embedded_test_server()->Started()); - // Resolve everything to localhost. - host_resolver()->AddIPLiteralRule("*", "127.0.0.1", "localhost"); - - logged_in_user_mixin_.LogInUser(false /*issue_any_scope_token*/, - true /*wait_for_active_session*/, - true /*request_policy_update*/); + logged_in_user_mixin_.LogInUser(); profile_ = browser()->profile(); // During tests, AppService doesn't notify AppActivityRegistry that chrome app
diff --git a/chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc b/chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc index 072a6ed..522c079 100644 --- a/chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc +++ b/chrome/browser/chromeos/child_accounts/time_limits/web_time_limit_enforcer_browsertest.cc
@@ -38,7 +38,6 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" -#include "net/dns/mock_host_resolver.h" #include "ui/base/window_open_disposition.h" #include "url/gurl.h" @@ -130,12 +129,7 @@ ASSERT_TRUE(embedded_test_server()->Started()); - // Resolve everything to localhost. - host_resolver()->AddIPLiteralRule("*", "127.0.0.1", "localhost"); - - logged_in_user_mixin_.LogInUser(false /*issue_any_scope_token*/, - true /*wait_for_active_session*/, - true /*request_policy_update*/); + logged_in_user_mixin_.LogInUser(); } bool WebTimeLimitEnforcerThrottleTest::IsErrorPageBeingShownInWebContents(
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc b/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc index e9eaefa..5413ff9 100644 --- a/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc +++ b/chrome/browser/chromeos/extensions/login_screen/login/login_apitest.cc
@@ -401,11 +401,7 @@ ~LoginApitestWithEnterpriseUser() override = default; - void LoginUser() { - logged_in_user_mixin_.LogInUser(/*issue_any_scope_token=*/false, - /*wait_for_active_session=*/true, - /*request_policy_update=*/true); - } + void LoginUser() { logged_in_user_mixin_.LogInUser(); } void SetUpInSessionExtension() override { AccountId account_id = logged_in_user_mixin_.GetAccountId();
diff --git a/chrome/browser/chromeos/login/login_ui_browsertest.cc b/chrome/browser/chromeos/login/login_ui_browsertest.cc index f7db98a..b9faf35 100644 --- a/chrome/browser/chromeos/login/login_ui_browsertest.cc +++ b/chrome/browser/chromeos/login/login_ui_browsertest.cc
@@ -397,9 +397,7 @@ // having logged a child account into a session and having locked the screen. IN_PROC_BROWSER_TEST_F(UserManagementDisclosureChildTest, PRE_EnterpriseIconVisibleChildUser) { - logged_in_user_mixin_.LogInUser(false /*issue_any_scope_token*/, - true /*wait_for_active_session*/, - true /*request_policy_update*/); + logged_in_user_mixin_.LogInUser(); ScreenLockerTester screen_locker_tester; screen_locker_tester.Lock(); EXPECT_FALSE(ash::LoginScreenTestApi::IsManagedIconShown(
diff --git a/chrome/browser/chromeos/login/screens/supervision_transition_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/supervision_transition_screen_browsertest.cc index 63d55c8..bb8d44d 100644 --- a/chrome/browser/chromeos/login/screens/supervision_transition_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/supervision_transition_screen_browsertest.cc
@@ -79,8 +79,7 @@ // WaitForActiveSession() otherwise. logged_in_user_mixin_.LogInUser( false /*issue_any_scope_token*/, - content::IsPreTest() /*wait_for_active_session*/, - true /*request_policy_update*/); + content::IsPreTest() /*wait_for_active_session*/); } // The tests simulate user type changes between regular and child user.
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc index 80d35f2..c14bd873 100644 --- a/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc +++ b/chrome/browser/chromeos/ownership/owner_settings_service_chromeos.cc
@@ -739,7 +739,7 @@ void OwnerSettingsServiceChromeOS::StorePendingChanges() { if (!HasPendingChanges() || store_settings_factory_.HasWeakPtrs() || - !device_settings_service_ || user_id_.empty()) { + !device_settings_service_ || user_id_.empty() || !IsOwner()) { return; }
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc index 4e5e3cda..413c5ff 100644 --- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc +++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_browsertest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/mixin_based_in_process_browser_test.h" -#include "chromeos/constants/chromeos_switches.h" #include "components/arc/arc_features.h" #include "components/arc/arc_prefs.h" #include "components/policy/core/browser/browser_policy_connector.h" @@ -59,16 +58,12 @@ MixinBasedInProcessBrowserTest::TearDown(); } - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch(chromeos::switches::kOobeSkipPostLogin); - MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line); - } - // Sets up fake GAIA for specified user login, and requests login for the user // (using LoggedInUserMixin). void StartUserLogIn(bool wait_for_active_session) { logged_in_user_mixin_.LogInUser(true /*issue_any_scope_token*/, - wait_for_active_session); + wait_for_active_session, + /*request_policy_update=*/false); } protected:
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/OWNERS b/chrome/browser/chromeos/power/auto_screen_brightness/OWNERS index 0b16b90..50ec292 100644 --- a/chrome/browser/chromeos/power/auto_screen_brightness/OWNERS +++ b/chrome/browser/chromeos/power/auto_screen_brightness/OWNERS
@@ -1,3 +1,3 @@ amoylan@chromium.org -jiameng@chromium.org martis@chromium.org +thanhdng@chromium.org \ No newline at end of file
diff --git a/chrome/browser/content_index/content_index_provider_impl.cc b/chrome/browser/content_index/content_index_provider_impl.cc index 7db9b0f..52014b7f 100644 --- a/chrome/browser/content_index/content_index_provider_impl.cc +++ b/chrome/browser/content_index/content_index_provider_impl.cc
@@ -11,7 +11,6 @@ #include "base/strings/string_split.h" #include "base/task/post_task.h" #include "build/build_config.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/engagement/site_engagement_service_factory.h" #include "chrome/browser/metrics/ukm_background_recorder_service.h" @@ -21,6 +20,7 @@ #include "components/offline_items_collection/core/offline_content_aggregator.h" #include "components/offline_items_collection/core/offline_item.h" #include "components/offline_items_collection/core/update_delta.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_index_context.h"
diff --git a/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java b/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java index 61c7256..b01b334 100644 --- a/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java +++ b/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementService.java
@@ -8,10 +8,10 @@ import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; -import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.components.embedder_support.browser_context.BrowserContextHandle; /** - * Provides access to the Site Engagement Service for a profile. + * Provides access to the Site Engagement Service for a browser context. * * Site engagement measures the level of engagement that a user has with an origin. This class * allows Java to retrieve and modify engagement scores for URLs. @@ -22,12 +22,13 @@ private long mNativePointer; /** - * Returns a SiteEngagementService for the provided profile. + * Returns a SiteEngagementService for the provided browser context. * Must be called on the UI thread. */ - public static SiteEngagementService getForProfile(Profile profile) { + public static SiteEngagementService getForBrowserContext(BrowserContextHandle browserContext) { assert ThreadUtils.runningOnUiThread(); - return SiteEngagementServiceJni.get().siteEngagementServiceForProfile(profile); + return SiteEngagementServiceJni.get().siteEngagementServiceForBrowserContext( + browserContext); } /** @@ -64,7 +65,7 @@ return new SiteEngagementService(nativePointer); } - /** This object may only be created via the static getForProfile method. */ + /** This object may only be created via the static getForBrowserContext method. */ private SiteEngagementService(long nativePointer) { mNativePointer = nativePointer; } @@ -76,7 +77,8 @@ @NativeMethods interface Natives { - SiteEngagementService siteEngagementServiceForProfile(Profile profile); + SiteEngagementService siteEngagementServiceForBrowserContext( + BrowserContextHandle browserContext); void setParamValuesForTesting(); double getScore( long nativeSiteEngagementServiceAndroid, SiteEngagementService caller, String url);
diff --git a/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java b/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java index f2f57fa..229f89e7 100644 --- a/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java +++ b/chrome/browser/engagement/android/java/src/org/chromium/chrome/browser/engagement/SiteEngagementServiceTest.java
@@ -40,7 +40,7 @@ public void run() { final String url = "https://www.example.com"; SiteEngagementService service = - SiteEngagementService.getForProfile(Profile.fromWebContents( + SiteEngagementService.getForBrowserContext(Profile.fromWebContents( mActivityTestRule.getActivity().getActivityTab().getWebContents())); Assert.assertEquals(0.0, service.getScore(url), 0); @@ -68,14 +68,14 @@ mActivityTestRule.getActivity().getActivityTab().getWebContents()); Assert.assertEquals( - 0.0, SiteEngagementService.getForProfile(profile).getScore(url), 0); - SiteEngagementService.getForProfile(profile).resetBaseScoreForUrl(url, 5.0); + 0.0, SiteEngagementService.getForBrowserContext(profile).getScore(url), 0); + SiteEngagementService.getForBrowserContext(profile).resetBaseScoreForUrl(url, 5.0); Assert.assertEquals( - 5.0, SiteEngagementService.getForProfile(profile).getScore(url), 0); + 5.0, SiteEngagementService.getForBrowserContext(profile).getScore(url), 0); - SiteEngagementService.getForProfile(profile).resetBaseScoreForUrl(url, 2.0); + SiteEngagementService.getForBrowserContext(profile).resetBaseScoreForUrl(url, 2.0); Assert.assertEquals( - 2.0, SiteEngagementService.getForProfile(profile).getScore(url), 0); + 2.0, SiteEngagementService.getForBrowserContext(profile).getScore(url), 0); } }); }
diff --git a/chrome/browser/engagement/history_aware_site_engagement_service.cc b/chrome/browser/engagement/history_aware_site_engagement_service.cc index 196fdc9..cecd1be 100644 --- a/chrome/browser/engagement/history_aware_site_engagement_service.cc +++ b/chrome/browser/engagement/history_aware_site_engagement_service.cc
@@ -7,8 +7,8 @@ #include "base/time/clock.h" #include "base/time/time.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/browser_context.h" namespace site_engagement {
diff --git a/chrome/browser/engagement/important_sites_util.cc b/chrome/browser/engagement/important_sites_util.cc index 51eb0530..d59b459f 100644 --- a/chrome/browser/engagement/important_sites_util.cc +++ b/chrome/browser/engagement/important_sites_util.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/banners/app_banner_settings_helper.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/installable/installable_utils.h" #include "chrome/browser/profiles/profile.h" @@ -30,6 +29,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "components/site_engagement/core/mojom/site_engagement_details.mojom.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h"
diff --git a/chrome/browser/engagement/important_sites_util_unittest.cc b/chrome/browser/engagement/important_sites_util_unittest.cc index 7bc09582..3490d94 100644 --- a/chrome/browser/engagement/important_sites_util_unittest.cc +++ b/chrome/browser/engagement/important_sites_util_unittest.cc
@@ -16,7 +16,6 @@ #include "build/build_config.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" @@ -27,6 +26,7 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/web_contents.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/engagement/site_engagement_helper.cc b/chrome/browser/engagement/site_engagement_helper.cc index 6caaa13..cdf0efec 100644 --- a/chrome/browser/engagement/site_engagement_helper.cc +++ b/chrome/browser/engagement/site_engagement_helper.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/prefetch/no_state_prefetch/chrome_prerender_contents_delegate.h" #include "chrome/browser/profiles/profile.h" #include "components/no_state_prefetch/browser/prerender_contents.h" +#include "components/site_engagement/content/engagement_type.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" @@ -124,17 +125,16 @@ // compiler verifying that all cases are covered). switch (type) { case blink::WebInputEvent::Type::kRawKeyDown: - helper()->RecordUserInput(SiteEngagementService::ENGAGEMENT_KEYPRESS); + helper()->RecordUserInput(EngagementType::kKeypress); break; case blink::WebInputEvent::Type::kMouseDown: - helper()->RecordUserInput(SiteEngagementService::ENGAGEMENT_MOUSE); + helper()->RecordUserInput(EngagementType::kMouse); break; case blink::WebInputEvent::Type::kTouchStart: - helper()->RecordUserInput( - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE); + helper()->RecordUserInput(EngagementType::kTouchGesture); break; case blink::WebInputEvent::Type::kGestureScrollBegin: - helper()->RecordUserInput(SiteEngagementService::ENGAGEMENT_SCROLL); + helper()->RecordUserInput(EngagementType::kScroll); break; default: NOTREACHED(); @@ -197,8 +197,7 @@ service_(SiteEngagementService::Get( Profile::FromBrowserContext(web_contents->GetBrowserContext()))) {} -void SiteEngagementService::Helper::RecordUserInput( - SiteEngagementService::EngagementType type) { +void SiteEngagementService::Helper::RecordUserInput(EngagementType type) { TRACE_EVENT0("SiteEngagement", "RecordUserInput"); content::WebContents* contents = web_contents(); if (contents)
diff --git a/chrome/browser/engagement/site_engagement_helper.h b/chrome/browser/engagement/site_engagement_helper.h index dace299..16f8d64 100644 --- a/chrome/browser/engagement/site_engagement_helper.h +++ b/chrome/browser/engagement/site_engagement_helper.h
@@ -20,6 +20,8 @@ namespace site_engagement { +enum class EngagementType; + // Per-WebContents class to handle updating the site engagement scores for // origins. class SiteEngagementService::Helper @@ -157,7 +159,7 @@ // Ask the SiteEngagementService to record engagement via user input at the // current WebContents URL. - void RecordUserInput(SiteEngagementService::EngagementType type); + void RecordUserInput(EngagementType type); // Ask the SiteEngagementService to record engagement via media playing at the // current WebContents URL.
diff --git a/chrome/browser/engagement/site_engagement_helper_unittest.cc b/chrome/browser/engagement/site_engagement_helper_unittest.cc index 410dd91..8134641 100644 --- a/chrome/browser/engagement/site_engagement_helper_unittest.cc +++ b/chrome/browser/engagement/site_engagement_helper_unittest.cc
@@ -8,12 +8,13 @@ #include "base/test/metrics/histogram_tester.h" #include "base/timer/mock_timer.h" #include "base/values.h" -#include "chrome/browser/engagement/site_engagement_metrics.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" +#include "components/site_engagement/content/engagement_type.h" +#include "components/site_engagement/content/site_engagement_metrics.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/page_navigator.h" #include "content/public/browser/web_contents.h" @@ -323,10 +324,9 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 2); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, 1); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 1); + EngagementType::kNavigation, 1); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 1); HandleUserInputAndRestartTracking(helper, blink::WebInputEvent::Type::kRawKeyDown); @@ -344,17 +344,15 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 7); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, 1); + EngagementType::kNavigation, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_KEYPRESS, 2); + EngagementType::kKeypress, 2); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MOUSE, 1); + EngagementType::kMouse, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE, - 2); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 1); + EngagementType::kTouchGesture, 2); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 1); HandleUserInputAndRestartTracking( helper, blink::WebInputEvent::Type::kGestureScrollBegin); @@ -370,21 +368,17 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 12); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MOUSE, 2); + EngagementType::kMouse, 2); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_SCROLL, 1); + EngagementType::kScroll, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE, - 3); + EngagementType::kTouchGesture, 3); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MEDIA_VISIBLE, - 1); + EngagementType::kMediaVisible, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MEDIA_HIDDEN, - 1); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 1); + EngagementType::kMediaHidden, 1); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 1); NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url2); TrackingStarted(helper); @@ -404,15 +398,13 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 16); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, 2); + EngagementType::kNavigation, 2); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_KEYPRESS, 3); + EngagementType::kKeypress, 3); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE, - 4); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 2); + EngagementType::kTouchGesture, 4); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 2); } TEST_F(SiteEngagementHelperTest, CheckTimerAndCallbacks) {
diff --git a/chrome/browser/engagement/site_engagement_metrics.cc b/chrome/browser/engagement/site_engagement_metrics.cc deleted file mode 100644 index e4c7e43..0000000 --- a/chrome/browser/engagement/site_engagement_metrics.cc +++ /dev/null
@@ -1,136 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/engagement/site_engagement_metrics.h" - -#include "base/metrics/histogram_macros.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "chrome/browser/engagement/site_engagement_score.h" -#include "components/site_engagement/core/mojom/site_engagement_details.mojom.h" - -namespace site_engagement { - -namespace { - -// These numbers are used as suffixes for the -// SiteEngagementService.EngagementScoreBucket_* histogram. If these bases -// change, the EngagementScoreBuckets suffix in histograms.xml should be -// updated. -const int kEngagementBucketHistogramBuckets[] = {0, 10, 20, 30, 40, 50, - 60, 70, 80, 90, 100}; - -} // namespace - -const char SiteEngagementMetrics::kTotalEngagementHistogram[] = - "SiteEngagementService.TotalEngagement"; - -const char SiteEngagementMetrics::kTotalOriginsHistogram[] = - "SiteEngagementService.OriginsEngaged"; - -const char SiteEngagementMetrics::kMeanEngagementHistogram[] = - "SiteEngagementService.MeanEngagement"; - -const char SiteEngagementMetrics::kMedianEngagementHistogram[] = - "SiteEngagementService.MedianEngagement"; - -const char SiteEngagementMetrics::kEngagementScoreHistogram[] = - "SiteEngagementService.EngagementScore"; - -const char SiteEngagementMetrics::kOriginsWithMaxEngagementHistogram[] = - "SiteEngagementService.OriginsWithMaxEngagement"; - -const char SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram[] = - "SiteEngagementService.OriginsWithMaxDailyEngagement"; - -const char SiteEngagementMetrics::kEngagementTypeHistogram[] = - "SiteEngagementService.EngagementType"; - -const char SiteEngagementMetrics::kEngagementBucketHistogramBase[] = - "SiteEngagementService.EngagementScoreBucket_"; - -const char SiteEngagementMetrics::kDaysSinceLastShortcutLaunchHistogram[] = - "SiteEngagementService.DaysSinceLastShortcutLaunch"; - -void SiteEngagementMetrics::RecordTotalSiteEngagement(double total_engagement) { - UMA_HISTOGRAM_COUNTS_10000(kTotalEngagementHistogram, total_engagement); -} - -void SiteEngagementMetrics::RecordTotalOriginsEngaged(int num_origins) { - UMA_HISTOGRAM_COUNTS_10000(kTotalOriginsHistogram, num_origins); -} - -void SiteEngagementMetrics::RecordMeanEngagement(double mean_engagement) { - UMA_HISTOGRAM_COUNTS_100(kMeanEngagementHistogram, mean_engagement); -} - -void SiteEngagementMetrics::RecordMedianEngagement(double median_engagement) { - UMA_HISTOGRAM_COUNTS_100(kMedianEngagementHistogram, median_engagement); -} - -void SiteEngagementMetrics::RecordEngagementScores( - const std::vector<mojom::SiteEngagementDetails>& details) { - if (details.empty()) - return; - - std::map<int, int> score_buckets; - for (size_t i = 0; i < base::size(kEngagementBucketHistogramBuckets); ++i) - score_buckets[kEngagementBucketHistogramBuckets[i]] = 0; - - for (const auto& detail : details) { - double score = detail.total_score; - UMA_HISTOGRAM_COUNTS_100(kEngagementScoreHistogram, score); - - auto bucket = score_buckets.lower_bound(score); - if (bucket == score_buckets.end()) - continue; - - bucket->second++; - } - - for (const auto& b : score_buckets) { - std::string histogram_name = - kEngagementBucketHistogramBase + base::NumberToString(b.first); - - base::LinearHistogram::FactoryGet( - histogram_name, 1, 100, 10, - base::HistogramBase::kUmaTargetedHistogramFlag) - ->Add(b.second * 100 / details.size()); - } -} - -void SiteEngagementMetrics::RecordOriginsWithMaxEngagement(int total_origins) { - UMA_HISTOGRAM_COUNTS_100(kOriginsWithMaxEngagementHistogram, total_origins); -} - -void SiteEngagementMetrics::RecordOriginsWithMaxDailyEngagement( - int total_origins) { - UMA_HISTOGRAM_COUNTS_100(kOriginsWithMaxDailyEngagementHistogram, - total_origins); -} - -void SiteEngagementMetrics::RecordEngagement( - SiteEngagementService::EngagementType type) { - UMA_HISTOGRAM_ENUMERATION(kEngagementTypeHistogram, type, - SiteEngagementService::ENGAGEMENT_LAST); -} - -void SiteEngagementMetrics::RecordDaysSinceLastShortcutLaunch(int days) { - UMA_HISTOGRAM_COUNTS_100(kDaysSinceLastShortcutLaunchHistogram, days); -} - -// static -std::vector<std::string> -SiteEngagementMetrics::GetEngagementBucketHistogramNames() { - std::vector<std::string> histogram_names; - for (size_t i = 0; i < base::size(kEngagementBucketHistogramBuckets); ++i) { - histogram_names.push_back( - kEngagementBucketHistogramBase + - base::NumberToString(kEngagementBucketHistogramBuckets[i])); - } - - return histogram_names; -} - -} // namespace site_engagement
diff --git a/chrome/browser/engagement/site_engagement_metrics.h b/chrome/browser/engagement/site_engagement_metrics.h deleted file mode 100644 index 77f2ddfe..0000000 --- a/chrome/browser/engagement/site_engagement_metrics.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_METRICS_H_ -#define CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_METRICS_H_ - -#include <vector> - -#include "base/gtest_prod_util.h" -#include "chrome/browser/engagement/site_engagement_service.h" -#include "url/gurl.h" - -namespace site_engagement { - -namespace mojom { -class SiteEngagementDetails; -} - -// Helper class managing the UMA histograms for the Site Engagement Service. -class SiteEngagementMetrics { - public: - static void RecordTotalSiteEngagement(double total_engagement); - static void RecordTotalOriginsEngaged(int total_origins); - static void RecordMeanEngagement(double mean_engagement); - static void RecordMedianEngagement(double median_engagement); - static void RecordEngagementScores( - const std::vector<mojom::SiteEngagementDetails>& details); - static void RecordOriginsWithMaxEngagement(int total_origins); - static void RecordOriginsWithMaxDailyEngagement(int total_origins); - static void RecordEngagement(SiteEngagementService::EngagementType type); - static void RecordDaysSinceLastShortcutLaunch(int days); - - private: - FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, CheckHistograms); - FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, - GetTotalNotificationPoints); - FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, LastShortcutLaunch); - FRIEND_TEST_ALL_PREFIXES(SiteEngagementHelperTest, - MixedInputEngagementAccumulation); - static const char kTotalEngagementHistogram[]; - static const char kTotalOriginsHistogram[]; - static const char kMeanEngagementHistogram[]; - static const char kMedianEngagementHistogram[]; - static const char kEngagementScoreHistogram[]; - static const char kOriginsWithMaxEngagementHistogram[]; - static const char kOriginsWithMaxDailyEngagementHistogram[]; - static const char kEngagementTypeHistogram[]; - static const char kEngagementBucketHistogramBase[]; - static const char kDaysSinceLastShortcutLaunchHistogram[]; - - static std::vector<std::string> GetEngagementBucketHistogramNames(); -}; - -} // namespace site_engagement - -#endif // CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_METRICS_H_
diff --git a/chrome/browser/engagement/site_engagement_observer.h b/chrome/browser/engagement/site_engagement_observer.h index eabe213..a5ff3c44 100644 --- a/chrome/browser/engagement/site_engagement_observer.h +++ b/chrome/browser/engagement/site_engagement_observer.h
@@ -7,17 +7,18 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "chrome/browser/engagement/site_engagement_service.h" namespace content { class WebContents; } class GURL; -class SiteEngagementService; namespace site_engagement { +class SiteEngagementService; +enum class EngagementType; + class SiteEngagementObserver { public: // Called when the engagement for |url| loaded in |web_contents| is changed @@ -28,7 +29,7 @@ virtual void OnEngagementEvent(content::WebContents* web_contents, const GURL& url, double score, - SiteEngagementService::EngagementType type) {} + EngagementType type) {} protected: explicit SiteEngagementObserver(SiteEngagementService* service);
diff --git a/chrome/browser/engagement/site_engagement_score.cc b/chrome/browser/engagement/site_engagement_score.cc deleted file mode 100644 index 2fcec2af..0000000 --- a/chrome/browser/engagement/site_engagement_score.cc +++ /dev/null
@@ -1,405 +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/engagement/site_engagement_score.h" - -#include <algorithm> -#include <cmath> -#include <utility> - -#include "base/no_destructor.h" -#include "base/strings/string_number_conversions.h" -#include "base/time/clock.h" -#include "base/time/time.h" -#include "base/values.h" -#include "chrome/browser/engagement/site_engagement_metrics.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" -#include "components/content_settings/core/common/content_settings.h" -#include "components/content_settings/core/common/content_settings_types.h" -#include "components/variations/variations_associated_data.h" - -namespace site_engagement { - -namespace { - -// Delta within which to consider scores equal. -const double kScoreDelta = 0.001; - -// Delta within which to consider internal time values equal. Internal time -// values are in microseconds, so this delta comes out at one second. -const double kTimeDelta = 1000000; - -// Number of days after the last launch of an origin from an installed shortcut -// for which WEB_APP_INSTALLED_POINTS will be added to the engagement score. -const int kMaxDaysSinceShortcutLaunch = 10; - -bool DoublesConsideredDifferent(double value1, double value2, double delta) { - double abs_difference = fabs(value1 - value2); - return abs_difference > delta; -} - -std::unique_ptr<base::DictionaryValue> GetSiteEngagementScoreDictForSettings( - const HostContentSettingsMap* settings, - const GURL& origin_url) { - if (!settings) - return std::make_unique<base::DictionaryValue>(); - - std::unique_ptr<base::DictionaryValue> value = - base::DictionaryValue::From(settings->GetWebsiteSetting( - origin_url, origin_url, ContentSettingsType::SITE_ENGAGEMENT, NULL)); - - if (value.get()) - return value; - - return std::make_unique<base::DictionaryValue>(); -} - -} // namespace - -const double SiteEngagementScore::kMaxPoints = 100; - -const char SiteEngagementScore::kRawScoreKey[] = "rawScore"; -const char SiteEngagementScore::kPointsAddedTodayKey[] = "pointsAddedToday"; -const char SiteEngagementScore::kLastEngagementTimeKey[] = "lastEngagementTime"; -const char SiteEngagementScore::kLastShortcutLaunchTimeKey[] = - "lastShortcutLaunchTime"; - -// static -SiteEngagementScore::ParamValues& SiteEngagementScore::GetParamValues() { - static base::NoDestructor<ParamValues> param_values([]() { - SiteEngagementScore::ParamValues param_values; - param_values[MAX_POINTS_PER_DAY] = {"max_points_per_day", 15}; - param_values[DECAY_PERIOD_IN_HOURS] = {"decay_period_in_hours", 2}; - param_values[DECAY_POINTS] = {"decay_points", 0}; - param_values[DECAY_PROPORTION] = {"decay_proportion", 0.984}; - param_values[SCORE_CLEANUP_THRESHOLD] = {"score_cleanup_threshold", 0.5}; - param_values[NAVIGATION_POINTS] = {"navigation_points", 1.5}; - param_values[USER_INPUT_POINTS] = {"user_input_points", 0.6}; - param_values[VISIBLE_MEDIA_POINTS] = {"visible_media_playing_points", 0.06}; - param_values[HIDDEN_MEDIA_POINTS] = {"hidden_media_playing_points", 0.01}; - param_values[WEB_APP_INSTALLED_POINTS] = {"web_app_installed_points", 5}; - param_values[FIRST_DAILY_ENGAGEMENT] = {"first_daily_engagement_points", - 1.5}; - param_values[BOOTSTRAP_POINTS] = {"bootstrap_points", 24}; - param_values[MEDIUM_ENGAGEMENT_BOUNDARY] = {"medium_engagement_boundary", - 15}; - param_values[HIGH_ENGAGEMENT_BOUNDARY] = {"high_engagement_boundary", 50}; - param_values[MAX_DECAYS_PER_SCORE] = {"max_decays_per_score", 4}; - param_values[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS] = { - "last_engagement_grace_period_in_hours", 1}; - param_values[NOTIFICATION_INTERACTION_POINTS] = { - "notification_interaction_points", 1}; - return param_values; - }()); - return *param_values; -} - -double SiteEngagementScore::GetMaxPointsPerDay() { - return GetParamValues()[MAX_POINTS_PER_DAY].second; -} - -double SiteEngagementScore::GetDecayPeriodInHours() { - return GetParamValues()[DECAY_PERIOD_IN_HOURS].second; -} - -double SiteEngagementScore::GetDecayPoints() { - return GetParamValues()[DECAY_POINTS].second; -} - -double SiteEngagementScore::GetDecayProportion() { - return GetParamValues()[DECAY_PROPORTION].second; -} - -double SiteEngagementScore::GetScoreCleanupThreshold() { - return GetParamValues()[SCORE_CLEANUP_THRESHOLD].second; -} - -double SiteEngagementScore::GetNavigationPoints() { - return GetParamValues()[NAVIGATION_POINTS].second; -} - -double SiteEngagementScore::GetUserInputPoints() { - return GetParamValues()[USER_INPUT_POINTS].second; -} - -double SiteEngagementScore::GetVisibleMediaPoints() { - return GetParamValues()[VISIBLE_MEDIA_POINTS].second; -} - -double SiteEngagementScore::GetHiddenMediaPoints() { - return GetParamValues()[HIDDEN_MEDIA_POINTS].second; -} - -double SiteEngagementScore::GetWebAppInstalledPoints() { - return GetParamValues()[WEB_APP_INSTALLED_POINTS].second; -} - -double SiteEngagementScore::GetFirstDailyEngagementPoints() { - return GetParamValues()[FIRST_DAILY_ENGAGEMENT].second; -} - -double SiteEngagementScore::GetBootstrapPoints() { - return GetParamValues()[BOOTSTRAP_POINTS].second; -} - -double SiteEngagementScore::GetMediumEngagementBoundary() { - return GetParamValues()[MEDIUM_ENGAGEMENT_BOUNDARY].second; -} - -double SiteEngagementScore::GetHighEngagementBoundary() { - return GetParamValues()[HIGH_ENGAGEMENT_BOUNDARY].second; -} - -double SiteEngagementScore::GetMaxDecaysPerScore() { - return GetParamValues()[MAX_DECAYS_PER_SCORE].second; -} - -double SiteEngagementScore::GetLastEngagementGracePeriodInHours() { - return GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second; -} - -double SiteEngagementScore::GetNotificationInteractionPoints() { - return GetParamValues()[NOTIFICATION_INTERACTION_POINTS].second; -} - -void SiteEngagementScore::SetParamValuesForTesting() { - GetParamValues()[MAX_POINTS_PER_DAY].second = 5; - GetParamValues()[DECAY_PERIOD_IN_HOURS].second = 7 * 24; - GetParamValues()[DECAY_POINTS].second = 5; - GetParamValues()[NAVIGATION_POINTS].second = 0.5; - GetParamValues()[USER_INPUT_POINTS].second = 0.05; - GetParamValues()[VISIBLE_MEDIA_POINTS].second = 0.02; - GetParamValues()[HIDDEN_MEDIA_POINTS].second = 0.01; - GetParamValues()[WEB_APP_INSTALLED_POINTS].second = 5; - GetParamValues()[BOOTSTRAP_POINTS].second = 8; - GetParamValues()[MEDIUM_ENGAGEMENT_BOUNDARY].second = 5; - GetParamValues()[HIGH_ENGAGEMENT_BOUNDARY].second = 50; - GetParamValues()[MAX_DECAYS_PER_SCORE].second = 1; - GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second = 72; - GetParamValues()[NOTIFICATION_INTERACTION_POINTS].second = 1; - - // This is set to values that avoid interference with tests and are set when - // testing these features. - GetParamValues()[FIRST_DAILY_ENGAGEMENT].second = 0; - GetParamValues()[DECAY_PROPORTION].second = 1; - GetParamValues()[SCORE_CLEANUP_THRESHOLD].second = 0; -} -// static -void SiteEngagementScore::UpdateFromVariations(const char* param_name) { - double param_vals[MAX_VARIATION]; - - for (int i = 0; i < MAX_VARIATION; ++i) { - std::string param_string = variations::GetVariationParamValue( - param_name, GetParamValues()[i].first); - - // Bail out if we didn't get a param string for the key, or if we couldn't - // convert the param string to a double, or if we get a negative value. - if (param_string.empty() || - !base::StringToDouble(param_string, ¶m_vals[i]) || - param_vals[i] < 0) { - return; - } - } - - // Once we're sure everything is valid, assign the variation to the param - // values array. - for (int i = 0; i < MAX_VARIATION; ++i) - SiteEngagementScore::GetParamValues()[i].second = param_vals[i]; -} - -SiteEngagementScore::SiteEngagementScore(base::Clock* clock, - const GURL& origin, - HostContentSettingsMap* settings) - : SiteEngagementScore( - clock, - origin, - GetSiteEngagementScoreDictForSettings(settings, origin)) { - settings_map_ = settings; -} - -SiteEngagementScore::SiteEngagementScore(SiteEngagementScore&& other) = default; - -SiteEngagementScore::~SiteEngagementScore() {} - -SiteEngagementScore& SiteEngagementScore::operator=( - SiteEngagementScore&& other) = default; - -void SiteEngagementScore::AddPoints(double points) { - DCHECK_NE(0, points); - - // As the score is about to be updated, commit any decay that has happened - // since the last update. - raw_score_ = DecayedScore(); - - base::Time now = clock_->Now(); - if (!last_engagement_time_.is_null() && - now.LocalMidnight() != last_engagement_time_.LocalMidnight()) { - points_added_today_ = 0; - } - - if (points_added_today_ == 0) { - // Award bonus engagement for the first engagement of the day for a site. - points += GetFirstDailyEngagementPoints(); - SiteEngagementMetrics::RecordEngagement( - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT); - } - - double to_add = std::min(kMaxPoints - raw_score_, - GetMaxPointsPerDay() - points_added_today_); - to_add = std::min(to_add, points); - - points_added_today_ += to_add; - raw_score_ += to_add; - - last_engagement_time_ = now; -} - -double SiteEngagementScore::GetTotalScore() const { - return std::min(DecayedScore() + BonusIfShortcutLaunched(), kMaxPoints); -} - -mojom::SiteEngagementDetails SiteEngagementScore::GetDetails() const { - mojom::SiteEngagementDetails engagement; - engagement.origin = origin_; - engagement.base_score = DecayedScore(); - engagement.installed_bonus = BonusIfShortcutLaunched(); - engagement.total_score = GetTotalScore(); - return engagement; -} - -void SiteEngagementScore::Commit() { - DCHECK(settings_map_); - if (!UpdateScoreDict(score_dict_.get())) - return; - - settings_map_->SetWebsiteSettingDefaultScope( - origin_, GURL(), ContentSettingsType::SITE_ENGAGEMENT, - std::move(score_dict_)); -} - -blink::mojom::EngagementLevel SiteEngagementScore::GetEngagementLevel() const { - DCHECK_LT(GetMediumEngagementBoundary(), GetHighEngagementBoundary()); - - double score = GetTotalScore(); - if (score == 0) - return blink::mojom::EngagementLevel::NONE; - - if (score < 1) - return blink::mojom::EngagementLevel::MINIMAL; - - if (score < GetMediumEngagementBoundary()) - return blink::mojom::EngagementLevel::LOW; - - if (score < GetHighEngagementBoundary()) - return blink::mojom::EngagementLevel::MEDIUM; - - if (score < SiteEngagementScore::kMaxPoints) - return blink::mojom::EngagementLevel::HIGH; - - return blink::mojom::EngagementLevel::MAX; -} - -bool SiteEngagementScore::MaxPointsPerDayAdded() const { - if (!last_engagement_time_.is_null() && - clock_->Now().LocalMidnight() != last_engagement_time_.LocalMidnight()) { - return false; - } - - return points_added_today_ == GetMaxPointsPerDay(); -} - -void SiteEngagementScore::Reset(double points, - const base::Time last_engagement_time) { - raw_score_ = points; - points_added_today_ = 0; - - // This must be set in order to prevent the score from decaying when read. - last_engagement_time_ = last_engagement_time; -} - -bool SiteEngagementScore::UpdateScoreDict(base::DictionaryValue* score_dict) { - double raw_score_orig = 0; - double points_added_today_orig = 0; - double last_engagement_time_internal_orig = 0; - double last_shortcut_launch_time_internal_orig = 0; - - score_dict->GetDouble(kRawScoreKey, &raw_score_orig); - score_dict->GetDouble(kPointsAddedTodayKey, &points_added_today_orig); - score_dict->GetDouble(kLastEngagementTimeKey, - &last_engagement_time_internal_orig); - score_dict->GetDouble(kLastShortcutLaunchTimeKey, - &last_shortcut_launch_time_internal_orig); - bool changed = - DoublesConsideredDifferent(raw_score_orig, raw_score_, kScoreDelta) || - DoublesConsideredDifferent(points_added_today_orig, points_added_today_, - kScoreDelta) || - DoublesConsideredDifferent(last_engagement_time_internal_orig, - last_engagement_time_.ToInternalValue(), - kTimeDelta) || - DoublesConsideredDifferent(last_shortcut_launch_time_internal_orig, - last_shortcut_launch_time_.ToInternalValue(), - kTimeDelta); - - if (!changed) - return false; - - score_dict->SetDouble(kRawScoreKey, raw_score_); - score_dict->SetDouble(kPointsAddedTodayKey, points_added_today_); - score_dict->SetDouble(kLastEngagementTimeKey, - last_engagement_time_.ToInternalValue()); - score_dict->SetDouble(kLastShortcutLaunchTimeKey, - last_shortcut_launch_time_.ToInternalValue()); - - return true; -} - -SiteEngagementScore::SiteEngagementScore( - base::Clock* clock, - const GURL& origin, - std::unique_ptr<base::DictionaryValue> score_dict) - : clock_(clock), - raw_score_(0), - points_added_today_(0), - last_engagement_time_(), - last_shortcut_launch_time_(), - score_dict_(score_dict.release()), - origin_(origin), - settings_map_(nullptr) { - if (!score_dict_) - return; - - score_dict_->GetDouble(kRawScoreKey, &raw_score_); - score_dict_->GetDouble(kPointsAddedTodayKey, &points_added_today_); - - double internal_time; - if (score_dict_->GetDouble(kLastEngagementTimeKey, &internal_time)) - last_engagement_time_ = base::Time::FromInternalValue(internal_time); - if (score_dict_->GetDouble(kLastShortcutLaunchTimeKey, &internal_time)) - last_shortcut_launch_time_ = base::Time::FromInternalValue(internal_time); -} - -double SiteEngagementScore::DecayedScore() const { - // Note that users can change their clock, so from this system's perspective - // time can go backwards. If that does happen and the system detects that the - // current day is earlier than the last engagement, no decay (or growth) is - // applied. - int hours_since_engagement = - (clock_->Now() - last_engagement_time_).InHours(); - if (hours_since_engagement < 0) - return raw_score_; - - int periods = hours_since_engagement / GetDecayPeriodInHours(); - return std::max(0.0, raw_score_ * pow(GetDecayProportion(), periods) - - periods * GetDecayPoints()); -} - -double SiteEngagementScore::BonusIfShortcutLaunched() const { - int days_since_shortcut_launch = - (clock_->Now() - last_shortcut_launch_time_).InDays(); - if (days_since_shortcut_launch <= kMaxDaysSinceShortcutLaunch) - return GetWebAppInstalledPoints(); - return 0; -} - -} // namespace site_engagement
diff --git a/chrome/browser/engagement/site_engagement_score.h b/chrome/browser/engagement/site_engagement_score.h deleted file mode 100644 index de9acbd..0000000 --- a/chrome/browser/engagement/site_engagement_score.h +++ /dev/null
@@ -1,248 +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. - -#ifndef CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_SCORE_H_ -#define CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_SCORE_H_ - -#include <array> -#include <memory> -#include <string> -#include <utility> - -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/time/time.h" -#include "base/values.h" -#include "components/site_engagement/core/mojom/site_engagement_details.mojom-forward.h" -#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom-forward.h" -#include "url/gurl.h" - -namespace base { -class Clock; -} - -class HostContentSettingsMap; - -namespace site_engagement { - -class SiteEngagementScore { - public: - // The parameters which can be varied via field trial. - enum Variation { - // The maximum number of points that can be accrued in one day. - MAX_POINTS_PER_DAY = 0, - - // The period over which site engagement decays. - DECAY_PERIOD_IN_HOURS, - - // The number of points to decay per period. - DECAY_POINTS, - - // The proportion [0-1] which the current engagement value is multiplied by - // at each decay period, before subtracting DECAY_POINTS. - DECAY_PROPORTION, - - // A score will be erased from the engagement system if it's less than this - // value. - SCORE_CLEANUP_THRESHOLD, - - // The number of points given for navigations. - NAVIGATION_POINTS, - - // The number of points given for user input. - USER_INPUT_POINTS, - - // The number of points given for media playing. Initially calibrated such - // that at least 30 minutes of foreground media would be required to allow a - // site to reach the daily engagement maximum. - VISIBLE_MEDIA_POINTS, - HIDDEN_MEDIA_POINTS, - - // The number of points added to engagement when a site is launched from - // homescreen or added as a bookmark app. This bonus will apply for ten days - // following a launch; each new launch resets the ten days. - WEB_APP_INSTALLED_POINTS, - - // The number of points given for the first engagement event of the day for - // each site. - FIRST_DAILY_ENGAGEMENT, - - // The number of points that the engagement service must accumulate to be - // considered 'useful'. - BOOTSTRAP_POINTS, - - // The boundaries between low/medium and medium/high engagement as returned - // by GetEngagementLevel(). - MEDIUM_ENGAGEMENT_BOUNDARY, - HIGH_ENGAGEMENT_BOUNDARY, - - // The maximum number of decays that a SiteEngagementScore can incur before - // entering a grace period. MAX_DECAYS_PER_SCORE * DECAY_PERIOD_IN_DAYS is - // the max decay period, i.e. the maximum duration permitted for - // (clock_->Now() - score.last_engagement_time()). - MAX_DECAYS_PER_SCORE, - - // If a SiteEngagamentScore has not been accessed or updated for a period - // longer than the max decay period + LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS - // (see above), its last engagement time will be reset to be max decay - // period prior to clock_->Now(). - LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS, - - // The number of points given for interacting with a displayed notification. - NOTIFICATION_INTERACTION_POINTS, - - MAX_VARIATION - }; - - // The maximum number of points that are allowed. - static const double kMaxPoints; - - static double GetMaxPointsPerDay(); - static double GetDecayPeriodInHours(); - static double GetDecayPoints(); - static double GetDecayProportion(); - static double GetScoreCleanupThreshold(); - static double GetNavigationPoints(); - static double GetUserInputPoints(); - static double GetVisibleMediaPoints(); - static double GetHiddenMediaPoints(); - static double GetWebAppInstalledPoints(); - static double GetFirstDailyEngagementPoints(); - static double GetBootstrapPoints(); - static double GetMediumEngagementBoundary(); - static double GetHighEngagementBoundary(); - static double GetMaxDecaysPerScore(); - static double GetLastEngagementGracePeriodInHours(); - static double GetNotificationInteractionPoints(); - - // Sets fixed parameter values for testing site engagement. Ensure that any - // newly added parameters receive a fixed value here. - static void SetParamValuesForTesting(); - - // Update the default engagement settings via variations. - static void UpdateFromVariations(const char* param_name); - - // The SiteEngagementScore does not take ownership of |clock|. It is the - // responsibility of the caller to make sure |clock| outlives this - // SiteEngagementScore. - SiteEngagementScore(base::Clock* clock, - const GURL& origin, - HostContentSettingsMap* settings); - SiteEngagementScore(SiteEngagementScore&& other); - ~SiteEngagementScore(); - - SiteEngagementScore& operator=(SiteEngagementScore&& other); - - // Adds |points| to this score, respecting daily limits and the maximum - // possible score. Decays the score if it has not been updated recently - // enough. - void AddPoints(double points); - - // Returns the total score, taking into account the base, bonus and maximum - // values. - double GetTotalScore() const; - - // Returns a structure containing the origin URL and score, and details - // of the base and bonus scores. Note that the |score| is limited to - // kMaxPoints, while the detailed scores are returned raw. - mojom::SiteEngagementDetails GetDetails() const; - - // Writes the values in this score into |settings_map_|. - void Commit(); - - // Returns the discrete engagement level for this score. - blink::mojom::EngagementLevel GetEngagementLevel() const; - - // Returns true if the maximum number of points today has been added. - bool MaxPointsPerDayAdded() const; - - // Resets the score to |points| and resets the daily point limit. If - // |updated_time| is non-null, sets the last engagement time to that value. - void Reset(double points, const base::Time updated_time); - - // Get/set the last time this origin was launched from an installed shortcut. - base::Time last_shortcut_launch_time() const { - return last_shortcut_launch_time_; - } - void set_last_shortcut_launch_time(const base::Time& time) { - last_shortcut_launch_time_ = time; - } - - // Get/set the last time this origin recorded an engagement change. - base::Time last_engagement_time() const { - return last_engagement_time_; - } - void set_last_engagement_time(const base::Time& time) { - last_engagement_time_ = time; - } - - private: - FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, FirstDailyEngagementBonus); - FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, PartiallyEmptyDictionary); - FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, PopulatedDictionary); - FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, Reset); - friend class SiteEngagementScoreTest; - friend class SiteEngagementServiceTest; - - using ParamValues = std::array<std::pair<std::string, double>, MAX_VARIATION>; - - // Array holding the values corresponding to each item in Variation array. - static ParamValues& GetParamValues(); - - // Keys used in the content settings dictionary. - static const char kRawScoreKey[]; - static const char kPointsAddedTodayKey[]; - static const char kLastEngagementTimeKey[]; - static const char kLastShortcutLaunchTimeKey[]; - - // This version of the constructor is used in unit tests. - SiteEngagementScore(base::Clock* clock, - const GURL& origin, - std::unique_ptr<base::DictionaryValue> score_dict); - - // Determine the score, accounting for any decay. - double DecayedScore() const; - - // Determine bonus from being installed, and having been launched recently.. - double BonusIfShortcutLaunched() const; - - // Updates the content settings dictionary |score_dict| with the current score - // fields. Returns true if |score_dict| changed, otherwise return false. - bool UpdateScoreDict(base::DictionaryValue* score_dict); - - // The clock used to vend times. Enables time travelling in tests. Owned by - // the SiteEngagementService. - base::Clock* clock_; - - // |raw_score_| is the score before any decay is applied. - double raw_score_; - - // The points added 'today' are tracked to avoid adding more than - // kMaxPointsPerDay on any one day. 'Today' is defined in local time. - double points_added_today_; - - // The last time the score was updated for engagement. Used in conjunction - // with |points_added_today_| to avoid adding more than kMaxPointsPerDay on - // any one day. - base::Time last_engagement_time_; - - // The last time the site with this score was launched from an installed - // shortcut. - base::Time last_shortcut_launch_time_; - - // The dictionary that represents this engagement score. - std::unique_ptr<base::DictionaryValue> score_dict_; - - // The origin this score represents. - GURL origin_; - - // The settings to write this score to when Commit() is called. - HostContentSettingsMap* settings_map_; - - DISALLOW_COPY_AND_ASSIGN(SiteEngagementScore); -}; - -} // namespace site_engagement - -#endif // CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_SCORE_H_
diff --git a/chrome/browser/engagement/site_engagement_score_unittest.cc b/chrome/browser/engagement/site_engagement_score_unittest.cc deleted file mode 100644 index f4cf3a06..0000000 --- a/chrome/browser/engagement/site_engagement_score_unittest.cc +++ /dev/null
@@ -1,488 +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/engagement/site_engagement_score.h" - -#include <utility> - -#include "base/macros.h" -#include "base/test/simple_test_clock.h" -#include "base/values.h" -#include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/engagement/site_engagement_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "chrome/test/base/testing_profile.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace site_engagement { - -namespace { - -const int kLessAccumulationsThanNeededToMaxDailyEngagement = 2; -const int kMoreAccumulationsThanNeededToMaxDailyEngagement = 40; -const int kMoreAccumulationsThanNeededToMaxTotalEngagement = 200; -const int kLessDaysThanNeededToMaxTotalEngagement = 4; -const int kMoreDaysThanNeededToMaxTotalEngagement = 40; -const int kLessPeriodsThanNeededToDecayMaxScore = 2; -const int kMorePeriodsThanNeededToDecayMaxScore = 40; -const double kMaxRoundingDeviation = 0.0001; - -base::Time GetReferenceTime() { - base::Time::Exploded exploded_reference_time; - exploded_reference_time.year = 2015; - exploded_reference_time.month = 1; - exploded_reference_time.day_of_month = 30; - exploded_reference_time.day_of_week = 5; - exploded_reference_time.hour = 11; - exploded_reference_time.minute = 0; - exploded_reference_time.second = 0; - exploded_reference_time.millisecond = 0; - - base::Time out_time; - EXPECT_TRUE( - base::Time::FromLocalExploded(exploded_reference_time, &out_time)); - return out_time; -} - -} // namespace - -class SiteEngagementScoreTest : public ChromeRenderViewHostTestHarness { - public: - SiteEngagementScoreTest() : score_(&test_clock_, GURL(), nullptr) {} - - void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - // Disable the first engagement bonus for tests. - SiteEngagementScore::SetParamValuesForTesting(); - } - - protected: - void VerifyScore(const SiteEngagementScore& score, - double expected_raw_score, - double expected_points_added_today, - base::Time expected_last_engagement_time) { - EXPECT_EQ(expected_raw_score, score.raw_score_); - EXPECT_EQ(expected_points_added_today, score.points_added_today_); - EXPECT_EQ(expected_last_engagement_time, score.last_engagement_time_); - } - - void UpdateScore(SiteEngagementScore* score, - double raw_score, - double points_added_today, - base::Time last_engagement_time) { - score->raw_score_ = raw_score; - score->points_added_today_ = points_added_today; - score->last_engagement_time_ = last_engagement_time; - } - - void TestScoreInitializesAndUpdates( - std::unique_ptr<base::DictionaryValue> score_dict, - double expected_raw_score, - double expected_points_added_today, - base::Time expected_last_engagement_time) { - std::unique_ptr<base::DictionaryValue> copy(score_dict->DeepCopy()); - SiteEngagementScore initial_score(&test_clock_, GURL(), - std::move(score_dict)); - VerifyScore(initial_score, expected_raw_score, expected_points_added_today, - expected_last_engagement_time); - - // Updating the score dict should return false, as the score shouldn't - // have changed at this point. - EXPECT_FALSE(initial_score.UpdateScoreDict(copy.get())); - - // Update the score to new values and verify it updates the score dict - // correctly. - base::Time different_day = - GetReferenceTime() + base::TimeDelta::FromDays(1); - UpdateScore(&initial_score, 5, 10, different_day); - EXPECT_TRUE(initial_score.UpdateScoreDict(copy.get())); - SiteEngagementScore updated_score(&test_clock_, GURL(), std::move(copy)); - VerifyScore(updated_score, 5, 10, different_day); - } - - void SetParamValue(SiteEngagementScore::Variation variation, double value) { - SiteEngagementScore::GetParamValues()[variation].second = value; - } - - base::SimpleTestClock test_clock_; - SiteEngagementScore score_; -}; - -// Accumulate score many times on the same day. Ensure each time the score goes -// up, but not more than the maximum per day. -TEST_F(SiteEngagementScoreTest, AccumulateOnSameDay) { - base::Time reference_time = GetReferenceTime(); - - test_clock_.SetNow(reference_time); - for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - EXPECT_EQ(std::min(SiteEngagementScore::GetMaxPointsPerDay(), - (i + 1) * SiteEngagementScore::GetNavigationPoints()), - score_.GetTotalScore()); - } - - EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.GetTotalScore()); -} - -// Accumulate on the first day to max that day's engagement, then accumulate on -// a different day. -TEST_F(SiteEngagementScoreTest, AccumulateOnTwoDays) { - base::Time reference_time = GetReferenceTime(); - base::Time later_date = reference_time + base::TimeDelta::FromDays(2); - - test_clock_.SetNow(reference_time); - for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - - EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.GetTotalScore()); - - test_clock_.SetNow(later_date); - for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - double day_score = - std::min(SiteEngagementScore::GetMaxPointsPerDay(), - (i + 1) * SiteEngagementScore::GetNavigationPoints()); - EXPECT_EQ(day_score + SiteEngagementScore::GetMaxPointsPerDay(), - score_.GetTotalScore()); - } - - EXPECT_EQ(2 * SiteEngagementScore::GetMaxPointsPerDay(), - score_.GetTotalScore()); -} - -// Accumulate score on many consecutive days and ensure the score doesn't exceed -// the maximum allowed. -TEST_F(SiteEngagementScoreTest, AccumulateALotOnManyDays) { - base::Time current_day = GetReferenceTime(); - - for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) { - current_day += base::TimeDelta::FromDays(1); - test_clock_.SetNow(current_day); - for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - - EXPECT_EQ(std::min(SiteEngagementScore::kMaxPoints, - (i + 1) * SiteEngagementScore::GetMaxPointsPerDay()), - score_.GetTotalScore()); - } - - EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); -} - -// Accumulate a little on many consecutive days and ensure the score doesn't -// exceed the maximum allowed. -TEST_F(SiteEngagementScoreTest, AccumulateALittleOnManyDays) { - base::Time current_day = GetReferenceTime(); - - for (int i = 0; i < kMoreAccumulationsThanNeededToMaxTotalEngagement; ++i) { - current_day += base::TimeDelta::FromDays(1); - test_clock_.SetNow(current_day); - - for (int j = 0; j < kLessAccumulationsThanNeededToMaxDailyEngagement; ++j) - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - - EXPECT_EQ( - std::min(SiteEngagementScore::kMaxPoints, - (i + 1) * kLessAccumulationsThanNeededToMaxDailyEngagement * - SiteEngagementScore::GetNavigationPoints()), - score_.GetTotalScore()); - } - - EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); -} - -// Accumulate a bit, then check the score decays properly for a range of times. -TEST_F(SiteEngagementScoreTest, ScoresDecayOverTime) { - base::Time current_day = GetReferenceTime(); - - // First max the score. - for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) { - current_day += base::TimeDelta::FromDays(1); - test_clock_.SetNow(current_day); - - for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - } - - EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); - - // The score should not have decayed before the first decay period has - // elapsed. - test_clock_.SetNow(current_day + - base::TimeDelta::FromHours( - SiteEngagementScore::GetDecayPeriodInHours() - 1)); - EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); - - // The score should have decayed by one chunk after one decay period has - // elapsed. - test_clock_.SetNow( - current_day + - base::TimeDelta::FromHours(SiteEngagementScore::GetDecayPeriodInHours())); - EXPECT_EQ( - SiteEngagementScore::kMaxPoints - SiteEngagementScore::GetDecayPoints(), - score_.GetTotalScore()); - - // The score should have decayed by the right number of chunks after a few - // decay periods have elapsed. - test_clock_.SetNow( - current_day + - base::TimeDelta::FromHours(kLessPeriodsThanNeededToDecayMaxScore * - SiteEngagementScore::GetDecayPeriodInHours())); - EXPECT_EQ(SiteEngagementScore::kMaxPoints - - kLessPeriodsThanNeededToDecayMaxScore * - SiteEngagementScore::GetDecayPoints(), - score_.GetTotalScore()); - - // The score should not decay below zero. - test_clock_.SetNow( - current_day + - base::TimeDelta::FromHours(kMorePeriodsThanNeededToDecayMaxScore * - SiteEngagementScore::GetDecayPeriodInHours())); - EXPECT_EQ(0, score_.GetTotalScore()); -} - -// Test that any expected decays are applied before adding points. -TEST_F(SiteEngagementScoreTest, DecaysAppliedBeforeAdd) { - base::Time current_day = GetReferenceTime(); - - // Get the score up to something that can handle a bit of decay before - for (int i = 0; i < kLessDaysThanNeededToMaxTotalEngagement; ++i) { - current_day += base::TimeDelta::FromDays(1); - test_clock_.SetNow(current_day); - - for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - } - - double initial_score = kLessDaysThanNeededToMaxTotalEngagement * - SiteEngagementScore::GetMaxPointsPerDay(); - EXPECT_EQ(initial_score, score_.GetTotalScore()); - - // Go forward a few decay periods. - test_clock_.SetNow( - current_day + - base::TimeDelta::FromHours(kLessPeriodsThanNeededToDecayMaxScore * - SiteEngagementScore::GetDecayPeriodInHours())); - - double decayed_score = initial_score - - kLessPeriodsThanNeededToDecayMaxScore * - SiteEngagementScore::GetDecayPoints(); - EXPECT_EQ(decayed_score, score_.GetTotalScore()); - - // Now add some points. - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - EXPECT_EQ(decayed_score + SiteEngagementScore::GetNavigationPoints(), - score_.GetTotalScore()); -} - -// Test that going back in time is handled properly. -TEST_F(SiteEngagementScoreTest, GoBackInTime) { - base::Time current_day = GetReferenceTime(); - - test_clock_.SetNow(current_day); - for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - - EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.GetTotalScore()); - - // Adding to the score on an earlier date should be treated like another day, - // and should not cause any decay. - test_clock_.SetNow(current_day - base::TimeDelta::FromDays( - kMorePeriodsThanNeededToDecayMaxScore * - SiteEngagementScore::GetDecayPoints())); - for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - double day_score = - std::min(SiteEngagementScore::GetMaxPointsPerDay(), - (i + 1) * SiteEngagementScore::GetNavigationPoints()); - EXPECT_EQ(day_score + SiteEngagementScore::GetMaxPointsPerDay(), - score_.GetTotalScore()); - } - - EXPECT_EQ(2 * SiteEngagementScore::GetMaxPointsPerDay(), - score_.GetTotalScore()); -} - -// Test that scores are read / written correctly from / to empty score -// dictionaries. -TEST_F(SiteEngagementScoreTest, EmptyDictionary) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - TestScoreInitializesAndUpdates(std::move(dict), 0, 0, base::Time()); -} - -// Test that scores are read / written correctly from / to partially empty -// score dictionaries. -TEST_F(SiteEngagementScoreTest, PartiallyEmptyDictionary) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2); - - TestScoreInitializesAndUpdates(std::move(dict), 0, 2, base::Time()); -} - -// Test that scores are read / written correctly from / to populated score -// dictionaries. -TEST_F(SiteEngagementScoreTest, PopulatedDictionary) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetDouble(SiteEngagementScore::kRawScoreKey, 1); - dict->SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2); - dict->SetDouble(SiteEngagementScore::kLastEngagementTimeKey, - GetReferenceTime().ToInternalValue()); - - TestScoreInitializesAndUpdates(std::move(dict), 1, 2, GetReferenceTime()); -} - -// Ensure bonus engagement is awarded for the first engagement of a day. -TEST_F(SiteEngagementScoreTest, FirstDailyEngagementBonus) { - SetParamValue(SiteEngagementScore::FIRST_DAILY_ENGAGEMENT, 0.5); - - SiteEngagementScore score1(&test_clock_, GURL(), - std::unique_ptr<base::DictionaryValue>()); - SiteEngagementScore score2(&test_clock_, GURL(), - std::unique_ptr<base::DictionaryValue>()); - base::Time current_day = GetReferenceTime(); - - test_clock_.SetNow(current_day); - - // The first engagement event gets the bonus. - score1.AddPoints(0.5); - EXPECT_EQ(1.0, score1.GetTotalScore()); - - // Subsequent events do not. - score1.AddPoints(0.5); - EXPECT_EQ(1.5, score1.GetTotalScore()); - - // Bonuses are awarded independently between scores. - score2.AddPoints(1.0); - EXPECT_EQ(1.5, score2.GetTotalScore()); - score2.AddPoints(1.0); - EXPECT_EQ(2.5, score2.GetTotalScore()); - - test_clock_.SetNow(current_day + base::TimeDelta::FromDays(1)); - - // The first event for the next day gets the bonus. - score1.AddPoints(0.5); - EXPECT_EQ(2.5, score1.GetTotalScore()); - - // Subsequent events do not. - score1.AddPoints(0.5); - EXPECT_EQ(3.0, score1.GetTotalScore()); - - score2.AddPoints(1.0); - EXPECT_EQ(4.0, score2.GetTotalScore()); - score2.AddPoints(1.0); - EXPECT_EQ(5.0, score2.GetTotalScore()); -} - -// Test that resetting a score has the correct properties. -TEST_F(SiteEngagementScoreTest, Reset) { - base::Time current_day = GetReferenceTime(); - - test_clock_.SetNow(current_day); - score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); - EXPECT_EQ(SiteEngagementScore::GetNavigationPoints(), score_.GetTotalScore()); - - current_day += base::TimeDelta::FromDays(7); - test_clock_.SetNow(current_day); - - score_.Reset(20.0, current_day); - EXPECT_DOUBLE_EQ(20.0, score_.GetTotalScore()); - EXPECT_DOUBLE_EQ(0, score_.points_added_today_); - EXPECT_EQ(current_day, score_.last_engagement_time_); - EXPECT_TRUE(score_.last_shortcut_launch_time_.is_null()); - - // Adding points after the reset should work as normal. - score_.AddPoints(5); - EXPECT_EQ(25.0, score_.GetTotalScore()); - - // The decay should happen one decay period from the current time. - test_clock_.SetNow(current_day + - base::TimeDelta::FromHours( - SiteEngagementScore::GetDecayPeriodInHours() + 1)); - EXPECT_EQ(25.0 - SiteEngagementScore::GetDecayPoints(), - score_.GetTotalScore()); - - // Ensure that manually setting a time works as expected. - score_.AddPoints(5); - test_clock_.SetNow(GetReferenceTime()); - base::Time now = test_clock_.Now(); - score_.Reset(10.0, now); - - EXPECT_DOUBLE_EQ(10.0, score_.GetTotalScore()); - EXPECT_DOUBLE_EQ(0, score_.points_added_today_); - EXPECT_EQ(now, score_.last_engagement_time_); - EXPECT_TRUE(score_.last_shortcut_launch_time_.is_null()); - - base::Time old_now = test_clock_.Now(); - - score_.set_last_shortcut_launch_time(test_clock_.Now()); - test_clock_.SetNow(GetReferenceTime() + base::TimeDelta::FromDays(3)); - now = test_clock_.Now(); - score_.Reset(15.0, now); - - // 5 bonus from the last shortcut launch. - EXPECT_DOUBLE_EQ(20.0, score_.GetTotalScore()); - EXPECT_DOUBLE_EQ(0, score_.points_added_today_); - EXPECT_EQ(now, score_.last_engagement_time_); - EXPECT_EQ(old_now, score_.last_shortcut_launch_time_); -} - -// Test proportional decay. -TEST_F(SiteEngagementScoreTest, ProportionalDecay) { - SetParamValue(SiteEngagementScore::DECAY_PROPORTION, 0.5); - SetParamValue(SiteEngagementScore::DECAY_POINTS, 0); - SetParamValue(SiteEngagementScore::MAX_POINTS_PER_DAY, 20); - base::Time current_day = GetReferenceTime(); - test_clock_.SetNow(current_day); - - // Single decay period, expect the score to be halved once. - score_.AddPoints(2.0); - current_day += base::TimeDelta::FromDays(7); - test_clock_.SetNow(current_day); - EXPECT_DOUBLE_EQ(1.0, score_.GetTotalScore()); - - // 3 decay periods, expect the score to be halved 3 times. - score_.AddPoints(15.0); - current_day += base::TimeDelta::FromDays(21); - test_clock_.SetNow(current_day); - EXPECT_DOUBLE_EQ(2.0, score_.GetTotalScore()); - - // Ensure point removal happens after proportional decay. - score_.AddPoints(4.0); - EXPECT_DOUBLE_EQ(6.0, score_.GetTotalScore()); - SetParamValue(SiteEngagementScore::DECAY_POINTS, 2.0); - current_day += base::TimeDelta::FromDays(7); - test_clock_.SetNow(current_day); - EXPECT_NEAR(1.0, score_.GetTotalScore(), kMaxRoundingDeviation); -} - -// Verify that GetDetails fills out all fields correctly. -TEST_F(SiteEngagementScoreTest, GetDetails) { - // Advance the clock, otherwise Now() is the same as the null Time value. - test_clock_.Advance(base::TimeDelta::FromDays(365)); - - GURL url("http://www.google.com/"); - - // Replace |score_| with one with an actual URL, and with a settings map. - HostContentSettingsMap* settings_map = - HostContentSettingsMapFactory::GetForProfile(profile()); - score_ = SiteEngagementScore(&test_clock_, url, settings_map); - - // Initially all component scores should be zero. - mojom::SiteEngagementDetails details = score_.GetDetails(); - EXPECT_DOUBLE_EQ(0.0, details.total_score); - EXPECT_DOUBLE_EQ(0.0, details.installed_bonus); - EXPECT_DOUBLE_EQ(0.0, details.base_score); - EXPECT_EQ(url, details.origin); - - // Simulate the app having been launched. - score_.set_last_shortcut_launch_time(test_clock_.Now()); - details = score_.GetDetails(); - EXPECT_DOUBLE_EQ(details.installed_bonus, details.total_score); - EXPECT_LT(0.0, details.installed_bonus); - EXPECT_DOUBLE_EQ(0.0, details.base_score); -} - -} // namespace site_engagement
diff --git a/chrome/browser/engagement/site_engagement_service.cc b/chrome/browser/engagement/site_engagement_service.cc index 11d943b..e4fd43a 100644 --- a/chrome/browser/engagement/site_engagement_service.cc +++ b/chrome/browser/engagement/site_engagement_service.cc
@@ -18,15 +18,16 @@ #include "base/time/default_clock.h" #include "base/time/time.h" #include "base/values.h" -#include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/engagement/site_engagement_metrics.h" #include "chrome/browser/engagement/site_engagement_observer.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/common/pref_names.h" #include "components/browsing_data/core/browsing_data_utils.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_pattern.h" +#include "components/permissions/permissions_client.h" #include "components/prefs/pref_service.h" +#include "components/site_engagement/content/engagement_type.h" +#include "components/site_engagement/content/site_engagement_metrics.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "components/user_prefs/user_prefs.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -78,7 +79,8 @@ content::BrowserContext* browser_context, ContentSettingsType type) { return GetContentSettingsFromMap( - HostContentSettingsMapFactory::GetForProfile(browser_context), type); + permissions::PermissionsClient::Get()->GetSettingsMap(browser_context), + type); } // Returns the combined list of origins which either have site engagement @@ -245,7 +247,7 @@ return GetAllDetailsImpl( browsing_data::TimePeriod::ALL_TIME, clock_, - HostContentSettingsMapFactory::GetForProfile(browser_context_)); + permissions::PermissionsClient::Get()->GetSettingsMap(browser_context_)); } std::vector<mojom::SiteEngagementDetails> @@ -256,7 +258,7 @@ return GetAllDetailsImpl( time_period, clock_, - HostContentSettingsMapFactory::GetForProfile(browser_context_)); + permissions::PermissionsClient::Get()->GetSettingsMap(browser_context_)); } void SiteEngagementService::HandleNotificationInteraction(const GURL& url) { @@ -267,7 +269,7 @@ MaybeRecordMetrics(); OnEngagementEvent(nullptr /* web_contents */, url, - ENGAGEMENT_NOTIFICATION_INTERACTION); + EngagementType::kNotificationInteraction); } bool SiteEngagementService::IsBootstrapped() const { @@ -331,7 +333,7 @@ score.set_last_shortcut_launch_time(now); score.Commit(); - OnEngagementEvent(web_contents, url, ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH); + OnEngagementEvent(web_contents, url, EngagementType::kWebappShortcutLaunch); } double SiteEngagementService::GetScore(const GURL& url) const { @@ -347,7 +349,7 @@ return GetDetailsImpl( clock_, url, - HostContentSettingsMapFactory::GetForProfile(browser_context_)); + permissions::PermissionsClient::Get()->GetSettingsMap(browser_context_)); } double SiteEngagementService::GetTotalEngagementPoints() const { @@ -423,7 +425,7 @@ last_engagement_time = now; HostContentSettingsMap* settings_map = - HostContentSettingsMapFactory::GetForProfile(browser_context_); + permissions::PermissionsClient::Get()->GetSettingsMap(browser_context_); for (const auto& site : GetContentSettingsFromBrowserContext( browser_context_, ContentSettingsType::SITE_ENGAGEMENT)) { GURL origin(site.primary_pattern.ToString()); @@ -503,10 +505,10 @@ FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, - base::BindOnce( - &GetAllDetailsInBackground, now, - base::WrapRefCounted( - HostContentSettingsMapFactory::GetForProfile(browser_context_))), + base::BindOnce(&GetAllDetailsInBackground, now, + base::WrapRefCounted( + permissions::PermissionsClient::Get()->GetSettingsMap( + browser_context_))), base::BindOnce(&SiteEngagementService::RecordMetrics, weak_factory_.GetWeakPtr())); } @@ -607,7 +609,7 @@ MaybeRecordMetrics(); OnEngagementEvent( web_contents, url, - is_hidden ? ENGAGEMENT_MEDIA_HIDDEN : ENGAGEMENT_MEDIA_VISIBLE); + is_hidden ? EngagementType::kMediaHidden : EngagementType::kMediaVisible); } void SiteEngagementService::HandleNavigation(content::WebContents* web_contents, @@ -619,7 +621,7 @@ AddPoints(url, SiteEngagementScore::GetNavigationPoints()); MaybeRecordMetrics(); - OnEngagementEvent(web_contents, url, ENGAGEMENT_NAVIGATION); + OnEngagementEvent(web_contents, url, EngagementType::kNavigation); } void SiteEngagementService::HandleUserInput(content::WebContents* web_contents, @@ -667,7 +669,7 @@ // will be initialised to the values from the original profile. return CreateEngagementScoreImpl( clock_, origin, - HostContentSettingsMapFactory::GetForProfile(browser_context_)); + permissions::PermissionsClient::Get()->GetSettingsMap(browser_context_)); } int SiteEngagementService::OriginsWithMaxDailyEngagement() const {
diff --git a/chrome/browser/engagement/site_engagement_service.h b/chrome/browser/engagement/site_engagement_service.h index b672b68..143a7fb0 100644 --- a/chrome/browser/engagement/site_engagement_service.h +++ b/chrome/browser/engagement/site_engagement_service.h
@@ -42,6 +42,7 @@ namespace site_engagement { +enum class EngagementType; class SiteEngagementObserver; class SiteEngagementScore; @@ -90,25 +91,6 @@ content::BrowserContext* browser_context) = 0; }; - // This is used to back a UMA histogram, so it should be treated as - // append-only. Any new values should be inserted immediately prior to - // ENGAGEMENT_LAST and added to SiteEngagementServiceEngagementType in - // tools/metrics/histograms/enums.xml. - // TODO(calamity): Document each of these engagement types. - enum EngagementType { - ENGAGEMENT_NAVIGATION, - ENGAGEMENT_KEYPRESS, - ENGAGEMENT_MOUSE, - ENGAGEMENT_TOUCH_GESTURE, - ENGAGEMENT_SCROLL, - ENGAGEMENT_MEDIA_HIDDEN, - ENGAGEMENT_MEDIA_VISIBLE, - ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, - ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, - ENGAGEMENT_NOTIFICATION_INTERACTION, - ENGAGEMENT_LAST, - }; - // WebContentsObserver that detects engagement triggering events and notifies // the service of them. class Helper;
diff --git a/chrome/browser/engagement/site_engagement_service_android.cc b/chrome/browser/engagement/site_engagement_service_android.cc index 955569e..e28b1c9 100644 --- a/chrome/browser/engagement/site_engagement_service_android.cc +++ b/chrome/browser/engagement/site_engagement_service_android.cc
@@ -7,8 +7,9 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "chrome/browser/engagement/android/jni_headers/SiteEngagementService_jni.h" -#include "chrome/browser/engagement/site_engagement_score.h" -#include "chrome/browser/profiles/profile_android.h" +#include "chrome/browser/engagement/site_engagement_service.h" +#include "components/embedder_support/android/browser_context/browser_context_handle.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "url/gurl.h" namespace site_engagement { @@ -70,11 +71,11 @@ } base::android::ScopedJavaLocalRef<jobject> -JNI_SiteEngagementService_SiteEngagementServiceForProfile( +JNI_SiteEngagementService_SiteEngagementServiceForBrowserContext( JNIEnv* env, - const JavaParamRef<jobject>& jprofile) { - Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile); - SiteEngagementService* service = SiteEngagementService::Get(profile); + const base::android::JavaParamRef<jobject>& jhandle) { + SiteEngagementService* service = SiteEngagementService::Get( + browser_context::BrowserContextFromJavaHandle(jhandle)); DCHECK(service); return base::android::ScopedJavaLocalRef<jobject>(
diff --git a/chrome/browser/engagement/site_engagement_service_android.h b/chrome/browser/engagement/site_engagement_service_android.h index fb25b09b..491ef8e7 100644 --- a/chrome/browser/engagement/site_engagement_service_android.h +++ b/chrome/browser/engagement/site_engagement_service_android.h
@@ -6,14 +6,14 @@ #define CHROME_BROWSER_ENGAGEMENT_SITE_ENGAGEMENT_SERVICE_ANDROID_H_ #include "base/android/scoped_java_ref.h" -#include "base/macros.h" -#include "chrome/browser/engagement/site_engagement_service.h" namespace site_engagement { +class SiteEngagementService; + // Wrapper class to expose the Site Engagement Service to Java. This object is -// owned by the |service_| which it wraps, and is lazily created when -// a Java-side SiteEngagementService is constructed. Once created, all future +// owned by the |service_| which it wraps, and is lazily created when a +// Java-side SiteEngagementService is constructed. Once created, all future // Java-side requests for a SiteEngagementService will use the same native // object. // @@ -27,6 +27,9 @@ SiteEngagementService* service); SiteEngagementServiceAndroid(JNIEnv* env, SiteEngagementService* service); + SiteEngagementServiceAndroid(const SiteEngagementServiceAndroid&) = delete; + SiteEngagementServiceAndroid& operator=( + const SiteEngagementServiceAndroid& other) = delete; ~SiteEngagementServiceAndroid(); @@ -42,8 +45,6 @@ private: base::android::ScopedJavaGlobalRef<jobject> java_service_; SiteEngagementService* service_; - - DISALLOW_COPY_AND_ASSIGN(SiteEngagementServiceAndroid); }; } // namespace site_engagement
diff --git a/chrome/browser/engagement/site_engagement_service_unittest.cc b/chrome/browser/engagement/site_engagement_service_unittest.cc index 1acd79a..1775aae 100644 --- a/chrome/browser/engagement/site_engagement_service_unittest.cc +++ b/chrome/browser/engagement/site_engagement_service_unittest.cc
@@ -23,9 +23,7 @@ #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/engagement/history_aware_site_engagement_service.h" #include "chrome/browser/engagement/site_engagement_helper.h" -#include "chrome/browser/engagement/site_engagement_metrics.h" #include "chrome/browser/engagement/site_engagement_observer.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/common/chrome_switches.h" @@ -40,6 +38,9 @@ #include "components/history/core/browser/history_service.h" #include "components/history/core/test/test_history_database.h" #include "components/prefs/pref_service.h" +#include "components/site_engagement/content/engagement_type.h" +#include "components/site_engagement/content/site_engagement_metrics.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_entry.h" @@ -123,7 +124,7 @@ content::WebContents* web_contents, const GURL& url, double score, - SiteEngagementService::EngagementType type) + EngagementType type) : SiteEngagementObserver(service), web_contents_(web_contents), url_(url), @@ -135,7 +136,7 @@ void OnEngagementEvent(content::WebContents* web_contents, const GURL& url, double score, - SiteEngagementService::EngagementType type) override { + EngagementType type) override { EXPECT_EQ(web_contents_, web_contents); EXPECT_EQ(url_, url); EXPECT_DOUBLE_EQ(score_, score); @@ -155,7 +156,7 @@ content::WebContents* web_contents_; GURL url_; double score_; - SiteEngagementService::EngagementType type_; + EngagementType type_; bool callback_called_; base::RunLoop run_loop_; @@ -384,39 +385,31 @@ EXPECT_EQ(0, service->GetScore(url3)); NavigateAndCommit(url1); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_MOUSE); + service->HandleUserInput(web_contents(), EngagementType::kMouse); EXPECT_DOUBLE_EQ(0.05, service->GetScore(url1)); EXPECT_DOUBLE_EQ(0.05, service->GetTotalEngagementPoints()); NavigateAndCommit(url2); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_MOUSE); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_KEYPRESS); + service->HandleUserInput(web_contents(), EngagementType::kMouse); + service->HandleUserInput(web_contents(), EngagementType::kKeypress); EXPECT_DOUBLE_EQ(0.1, service->GetScore(url2)); EXPECT_DOUBLE_EQ(0.15, service->GetTotalEngagementPoints()); NavigateAndCommit(url3); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_KEYPRESS); + service->HandleUserInput(web_contents(), EngagementType::kKeypress); EXPECT_DOUBLE_EQ(0.05, service->GetScore(url3)); EXPECT_DOUBLE_EQ(0.2, service->GetTotalEngagementPoints()); NavigateAndCommit(url1); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_KEYPRESS); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_MOUSE); + service->HandleUserInput(web_contents(), EngagementType::kKeypress); + service->HandleUserInput(web_contents(), EngagementType::kMouse); EXPECT_DOUBLE_EQ(0.15, service->GetScore(url1)); EXPECT_DOUBLE_EQ(0.3, service->GetTotalEngagementPoints()); NavigateAndCommit(url2); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_SCROLL); + service->HandleUserInput(web_contents(), EngagementType::kScroll); NavigateAndCommit(url3); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE); + service->HandleUserInput(web_contents(), EngagementType::kTouchGesture); EXPECT_DOUBLE_EQ(0.15, service->GetScore(url2)); EXPECT_DOUBLE_EQ(0.1, service->GetScore(url3)); EXPECT_DOUBLE_EQ(0.4, service->GetTotalEngagementPoints()); @@ -439,30 +432,26 @@ service->HandleNotificationInteraction(url1); EXPECT_DOUBLE_EQ(1.0, service->GetScore(url1)); EXPECT_DOUBLE_EQ(1.0, service->GetTotalEngagementPoints()); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NOTIFICATION_INTERACTION, 1); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kNotificationInteraction, 1); service->HandleNotificationInteraction(url2); EXPECT_DOUBLE_EQ(1.0, service->GetScore(url2)); EXPECT_DOUBLE_EQ(2.0, service->GetTotalEngagementPoints()); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NOTIFICATION_INTERACTION, 2); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kNotificationInteraction, 2); service->HandleNotificationInteraction(url1); EXPECT_DOUBLE_EQ(2.0, service->GetScore(url1)); EXPECT_DOUBLE_EQ(3.0, service->GetTotalEngagementPoints()); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NOTIFICATION_INTERACTION, 3); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kNotificationInteraction, 3); service->HandleNotificationInteraction(url3); EXPECT_DOUBLE_EQ(1.0, service->GetScore(url3)); EXPECT_DOUBLE_EQ(4.0, service->GetTotalEngagementPoints()); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NOTIFICATION_INTERACTION, 4); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kNotificationInteraction, 4); } TEST_F(SiteEngagementServiceTest, RestrictedToHTTPAndHTTPS) { @@ -476,8 +465,7 @@ GURL url4("chrome://config"); NavigateAndCommit(url1); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_MOUSE); + service->HandleUserInput(web_contents(), EngagementType::kMouse); EXPECT_EQ(0, service->GetScore(url1)); NavigateAndCommit(url2); @@ -489,8 +477,7 @@ EXPECT_EQ(0, service->GetScore(url3)); NavigateAndCommit(url4); - service->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_KEYPRESS); + service->HandleUserInput(web_contents(), EngagementType::kKeypress); EXPECT_EQ(0, service->GetScore(url4)); } @@ -513,9 +500,8 @@ service_->SetLastShortcutLaunchTime(web_contents(), url2); histograms.ExpectTotalCount( SiteEngagementMetrics::kDaysSinceLastShortcutLaunchHistogram, 0); - histograms.ExpectUniqueSample( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, 1); + histograms.ExpectUniqueSample(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kWebappShortcutLaunch, 1); service_->AddPoints(url1, 2.0); service_->AddPoints(url2, 2.0); @@ -526,12 +512,10 @@ SiteEngagementMetrics::kDaysSinceLastShortcutLaunchHistogram, 1); histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 4); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, 2); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 2); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kWebappShortcutLaunch, 2); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 2); EXPECT_DOUBLE_EQ(2.0, service_->GetScore(url1)); EXPECT_DOUBLE_EQ(7.0, service_->GetScore(url2)); @@ -618,10 +602,8 @@ NavigateAndCommit(url1); service_->HandleNavigation(web_contents(), ui::PAGE_TRANSITION_TYPED); - service_->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_KEYPRESS); - service_->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_MOUSE); + service_->HandleUserInput(web_contents(), EngagementType::kKeypress); + service_->HandleUserInput(web_contents(), EngagementType::kMouse); NavigateAndCommit(url2); service_->HandleMediaPlaying(web_contents(), true); @@ -649,17 +631,15 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 6); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, 1); + EngagementType::kNavigation, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_KEYPRESS, 1); + EngagementType::kKeypress, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MOUSE, 1); + EngagementType::kMouse, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MEDIA_HIDDEN, - 1); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 2); + EngagementType::kMediaHidden, 1); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 2); // Navigations are still logged within the 1 hour refresh period clock_.SetNow(clock_.Now() + base::TimeDelta::FromMinutes(59)); @@ -671,17 +651,15 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 8); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, 3); + EngagementType::kNavigation, 3); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_KEYPRESS, 1); + EngagementType::kKeypress, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MOUSE, 1); + EngagementType::kMouse, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MEDIA_HIDDEN, - 1); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 2); + EngagementType::kMediaHidden, 1); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 2); // Update the hourly histograms again. clock_.SetNow(clock_.Now() + base::TimeDelta::FromMinutes(1)); @@ -690,8 +668,7 @@ service_->HandleNavigation(web_contents(), ui::PAGE_TRANSITION_TYPED); service_->HandleMediaPlaying(web_contents(), false); NavigateAndCommit(url2); - service_->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE); + service_->HandleUserInput(web_contents(), EngagementType::kTouchGesture); // Wait until the background metrics recording happens. content::RunAllTasksUntilIdle(); @@ -718,53 +695,44 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 12); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, 4); + EngagementType::kNavigation, 4); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_KEYPRESS, 1); + EngagementType::kKeypress, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MOUSE, 1); + EngagementType::kMouse, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE, - 1); + EngagementType::kTouchGesture, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MEDIA_VISIBLE, - 1); + EngagementType::kMediaVisible, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MEDIA_HIDDEN, - 1); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 3); + EngagementType::kMediaHidden, 1); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 3); NavigateAndCommit(url1); service_->HandleNavigation(web_contents(), ui::PAGE_TRANSITION_GENERATED); service_->HandleNavigation(web_contents(), ui::PAGE_TRANSITION_TYPED); NavigateAndCommit(url2); - service_->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_SCROLL); + service_->HandleUserInput(web_contents(), EngagementType::kScroll); NavigateAndCommit(url1); - service_->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_KEYPRESS); + service_->HandleUserInput(web_contents(), EngagementType::kKeypress); NavigateAndCommit(url3); - service_->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_MOUSE); + service_->HandleUserInput(web_contents(), EngagementType::kMouse); histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 17); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, 6); + EngagementType::kNavigation, 6); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_KEYPRESS, 2); + EngagementType::kKeypress, 2); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_MOUSE, 2); + EngagementType::kMouse, 2); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_TOUCH_GESTURE, - 1); + EngagementType::kTouchGesture, 1); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_SCROLL, 1); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 3); + EngagementType::kScroll, 1); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 3); // Advance an origin to the max for a day and advance the clock an hour before // the last increment before max. Expect the histogram to be updated. @@ -801,11 +769,9 @@ histograms.ExpectTotalCount(SiteEngagementMetrics::kEngagementTypeHistogram, 24); histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_NAVIGATION, - 13); - histograms.ExpectBucketCount( - SiteEngagementMetrics::kEngagementTypeHistogram, - SiteEngagementService::ENGAGEMENT_FIRST_DAILY_ENGAGEMENT, 3); + EngagementType::kNavigation, 13); + histograms.ExpectBucketCount(SiteEngagementMetrics::kEngagementTypeHistogram, + EngagementType::kFirstDailyEngagement, 3); for (const std::string& histogram_name : engagement_bucket_histogram_names) histograms.ExpectTotalCount(histogram_name, 3); @@ -1380,8 +1346,7 @@ // Create an observer and Observe(nullptr). ObserverTester tester_not_called(service_.get(), web_contents(), - url_not_called, 1, - SiteEngagementService::ENGAGEMENT_LAST); + url_not_called, 1, EngagementType::kLast); tester_not_called.Observe(nullptr); base::Time current_day = GetReferenceTime(); @@ -1390,7 +1355,7 @@ { // Create an observer for navigation. ObserverTester tester(service_.get(), web_contents(), url_score_1, 0.5, - SiteEngagementService::ENGAGEMENT_NAVIGATION); + EngagementType::kNavigation); NavigateAndCommit(url_score_1); service_->HandleNavigation(web_contents(), ui::PAGE_TRANSITION_TYPED); tester.Wait(); @@ -1402,10 +1367,9 @@ { // Update observer for a user input. ObserverTester tester(service_.get(), web_contents(), url_score_2, 0.55, - SiteEngagementService::ENGAGEMENT_MOUSE); + EngagementType::kMouse); NavigateAndCommit(url_score_2); - service_->HandleUserInput(web_contents(), - SiteEngagementService::ENGAGEMENT_MOUSE); + service_->HandleUserInput(web_contents(), EngagementType::kMouse); tester.Wait(); EXPECT_TRUE(tester.callback_called()); EXPECT_FALSE(tester_not_called.callback_called()); @@ -1415,9 +1379,9 @@ // Add two observers for media playing in the foreground. { ObserverTester tester_1(service_.get(), web_contents(), url_score_3, 0.57, - SiteEngagementService::ENGAGEMENT_MEDIA_VISIBLE); + EngagementType::kMediaVisible); ObserverTester tester_2(service_.get(), web_contents(), url_score_3, 0.57, - SiteEngagementService::ENGAGEMENT_MEDIA_VISIBLE); + EngagementType::kMediaVisible); NavigateAndCommit(url_score_3); service_->HandleMediaPlaying(web_contents(), false); tester_1.Wait(); @@ -1433,7 +1397,7 @@ // Add an observer for media playing in the background. { ObserverTester tester(service_.get(), web_contents(), url_score_3, 0.58, - SiteEngagementService::ENGAGEMENT_MEDIA_HIDDEN); + EngagementType::kMediaHidden); service_->HandleMediaPlaying(web_contents(), true); tester.Wait(); @@ -1444,9 +1408,8 @@ // Add an observer for notifications. { - ObserverTester tester( - service_.get(), nullptr, url_score_4, 1.0, - SiteEngagementService::ENGAGEMENT_NOTIFICATION_INTERACTION); + ObserverTester tester(service_.get(), nullptr, url_score_4, 1.0, + EngagementType::kNotificationInteraction); service_->HandleNotificationInteraction(url_score_4); tester.Wait(); @@ -1457,9 +1420,8 @@ // Add an observer for web app launch. { - ObserverTester tester( - service_.get(), web_contents(), url_score_5, 5.0, - SiteEngagementService::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH); + ObserverTester tester(service_.get(), web_contents(), url_score_5, 5.0, + EngagementType::kWebappShortcutLaunch); service_->SetLastShortcutLaunchTime(web_contents(), url_score_5); tester.Wait();
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc index fd797c7..ebe78fb8 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc
@@ -43,7 +43,13 @@ // TODO(hcarmona): Investigate converting these tests to unittests. -IN_PROC_BROWSER_TEST_F(AutofillPrivateApiTest, GetCountryList) { +// TODO(crbug.com/1162474): Disabled on Mac for flakiness. +#if defined(OS_MAC) +#define MAYBE_GetCountryList DISABLED_GetCountryList +#else +#define MAYBE_GetCountryList GetCountryList +#endif +IN_PROC_BROWSER_TEST_F(AutofillPrivateApiTest, MAYBE_GetCountryList) { EXPECT_TRUE(RunAutofillSubtest("getCountryList")) << message_; }
diff --git a/chrome/browser/extensions/api/tabs/tabs_event_router.cc b/chrome/browser/extensions/api/tabs/tabs_event_router.cc index f805d36..c0f7e78 100644 --- a/chrome/browser/extensions/api/tabs/tabs_event_router.cc +++ b/chrome/browser/extensions/api/tabs/tabs_event_router.cc
@@ -453,8 +453,7 @@ tab_strip_model->selection_model().selected_indices(); std::unique_ptr<base::ListValue> all_tabs(new base::ListValue); - for (size_t i = 0; i < new_selection.size(); ++i) { - int index = new_selection[i]; + for (int index : new_selection) { WebContents* contents = tab_strip_model->GetWebContentsAt(index); if (!contents) break;
diff --git a/chrome/browser/extensions/calculator_app_browsertest.cc b/chrome/browser/extensions/calculator_app_browsertest.cc new file mode 100644 index 0000000..ce4a7bd --- /dev/null +++ b/chrome/browser/extensions/calculator_app_browsertest.cc
@@ -0,0 +1,35 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "net/base/filename_util.h" + +class CalculatorBrowserTest : public InProcessBrowserTest {}; + +IN_PROC_BROWSER_TEST_F(CalculatorBrowserTest, Model) { + base::FilePath test_file; + base::PathService::Get(chrome::DIR_TEST_DATA, &test_file); + test_file = + test_file.AppendASCII("extensions/calculator_app/tests/automatic.html"); + + ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_file)); + + bool success; + bool executed = content::ExecuteScriptAndExtractBool( + browser()->tab_strip_model()->GetActiveWebContents(), + "window.domAutomationController.send(window.runTests().success)", + &success); + + ASSERT_TRUE(executed); + ASSERT_TRUE(success); +}
diff --git a/chrome/browser/extensions/docs/examples/apps/calculator_browsertest.cc b/chrome/browser/extensions/docs/examples/apps/calculator_browsertest.cc deleted file mode 100644 index 3969068..0000000 --- a/chrome/browser/extensions/docs/examples/apps/calculator_browsertest.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/files/file_path.h" -#include "base/path_service.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "chrome/test/base/ui_test_utils.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/browser_test.h" -#include "content/public/test/browser_test_utils.h" -#include "net/base/filename_util.h" - -class CalculatorBrowserTest : public InProcessBrowserTest { -}; - -IN_PROC_BROWSER_TEST_F(CalculatorBrowserTest, Model) { - base::FilePath test_file; - base::PathService::Get(chrome::DIR_TEST_DATA, &test_file); - test_file = test_file.DirName().DirName() - .AppendASCII("common").AppendASCII("extensions").AppendASCII("docs") - .AppendASCII("examples").AppendASCII("apps").AppendASCII("calculator") - .AppendASCII("tests").AppendASCII("automatic.html"); - - ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(test_file)); - - bool success; - bool executed = content::ExecuteScriptAndExtractBool( - browser()->tab_strip_model()->GetActiveWebContents(), - "window.domAutomationController.send(window.runTests().success)", - &success); - - ASSERT_TRUE(executed); - ASSERT_TRUE(success); -}
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index f406550..6da32f0 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1511,6 +1511,11 @@ "expiry_milestone": 91 }, { + "name": "enable-desktop-pwas-link-capturing", + "owners": [ "alancutter@chromium.org", "desktop-pwas-team@google.com" ], + "expiry_milestone": 93 + }, + { "name": "enable-desktop-pwas-run-on-os-login", "owners": [ "mjackson@microsoft.com", "desktop-pwas-team@google.com" ], "expiry_milestone": 90 @@ -2323,7 +2328,7 @@ { "name": "enable-touch-drag-drop", "owners": [ "nzolghadr", "input-dev" ], - "expiry_milestone": 88 + "expiry_milestone": 93 }, { "name": "enable-touchscreen-calibration", @@ -3782,11 +3787,6 @@ "expiry_milestone": 90 }, { - "name": "overlay-scrollbars", - "owners": [ "chaopeng", "bokan", "input-dev" ], - "expiry_milestone": 76 - }, - { "name": "overlay-strategies", "owners": [ "chromeos-gfx@google.com" ], // This flag is used for QA & debugging on ChromeOS, which has no way to @@ -4978,8 +4978,8 @@ }, { "name": "web-share", - "owners": [ "mhochk@microsoft.com", "ericwilligers@google.com" ], - "expiry_milestone": 89 + "owners": [ "mhochk@microsoft.com", "ericwilligers@google.com", "hatalat@microsoft.com" ], + "expiry_milestone": 95 }, { "name": "web-view-native-context-menu",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 730766a..f43ce9b 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -682,6 +682,14 @@ "Replaces the origin flash with an app name flash when launching a web app " "window."; +const char kDesktopPWAsLinkCapturingName[] = + "Desktop PWA declarative link capturing"; +const char kDesktopPWAsLinkCapturingDescription[] = + "Enable web app manifests to declare link capturing behavior. Prototype " + "implementation of: " + "https://github.com/WICG/sw-launch/blob/master/" + "declarative_link_capturing.md"; + const char kDesktopPWAsTabStripName[] = "Desktop PWA tab strips"; const char kDesktopPWAsTabStripDescription[] = "Experimental UI for exploring what PWA windows would look like with a tab " @@ -1725,11 +1733,6 @@ "Enables a unique URL for each path in CrOS settings. " "This allows deep linking to individual settings, i.e. in settings search."; -const char kOverlayScrollbarsName[] = "Overlay Scrollbars"; -const char kOverlayScrollbarsDescription[] = - "Enable the experimental overlay scrollbars implementation. You must also " - "enable threaded compositing to have the scrollbars animate."; - const char kOverlayStrategiesName[] = "Select HW overlay strategies"; const char kOverlayStrategiesDescription[] = "Select strategies used to promote quads to HW overlays."; @@ -4792,12 +4795,12 @@ "update and restoring them after a version rollback."; #endif // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) -#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC) const char kWebShareName[] = "Web Share"; const char kWebShareDescription[] = "Enables the Web Share (navigator.share) APIs on experimentally supported " "platforms."; -#endif // defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) +#endif // defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC) // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete.
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index d956d9f..093904e 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -418,6 +418,9 @@ extern const char kDesktopPWAsFlashAppNameInsteadOfOriginName[]; extern const char kDesktopPWAsFlashAppNameInsteadOfOriginDescription[]; +extern const char kDesktopPWAsLinkCapturingName[]; +extern const char kDesktopPWAsLinkCapturingDescription[]; + extern const char kDesktopPWAsTabStripName[]; extern const char kDesktopPWAsTabStripDescription[]; @@ -1005,9 +1008,6 @@ extern const char kEnableDeJellyName[]; extern const char kEnableDeJellyDescription[]; -extern const char kOverlayScrollbarsName[]; -extern const char kOverlayScrollbarsDescription[]; - extern const char kOverlayStrategiesName[]; extern const char kOverlayStrategiesDescription[]; extern const char kOverlayStrategiesDefault[]; @@ -2810,10 +2810,10 @@ extern const char kUserDataSnapshotDescription[]; #endif // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) -#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC) extern const char kWebShareName[]; extern const char kWebShareDescription[]; -#endif // defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) +#endif // defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC) // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete.
diff --git a/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc index 2cf1f2c..5e951f6a 100644 --- a/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc +++ b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc
@@ -187,14 +187,9 @@ } // namespace -// Flaky on ChromeOS and Lacros (https://crbug.com/1033009) -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_GuestDevToolsReloadsEmbedder DISABLED_GuestDevToolsReloadsEmbedder -#else -#define MAYBE_GuestDevToolsReloadsEmbedder GuestDevToolsReloadsEmbedder -#endif +// Flaky (https://crbug.com/1033009) IN_PROC_BROWSER_TEST_F(ChromeMimeHandlerViewTest, - MAYBE_GuestDevToolsReloadsEmbedder) { + DISABLED_GuestDevToolsReloadsEmbedder) { GURL data_url("data:application/pdf,foo"); ui_test_utils::NavigateToURL(browser(), data_url); auto* embedder_web_contents =
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc index 044faa4..e4194e3 100644 --- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
@@ -11,7 +11,6 @@ #include "base/test/scoped_feature_list.h" #include "base/test/simple_test_clock.h" #include "build/build_config.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/history/history_test_utils.h" @@ -33,6 +32,7 @@ #include "components/security_interstitials/content/security_interstitial_page.h" #include "components/security_interstitials/content/security_interstitial_tab_helper.h" #include "components/security_interstitials/core/metrics_helper.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h"
diff --git a/chrome/browser/media/media_engagement_score.cc b/chrome/browser/media/media_engagement_score.cc index c63b705..3c2b33f 100644 --- a/chrome/browser/media/media_engagement_score.cc +++ b/chrome/browser/media/media_engagement_score.cc
@@ -7,10 +7,10 @@ #include <utility> #include "base/metrics/field_trial_params.h" -#include "chrome/browser/engagement/site_engagement_metrics.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" +#include "components/site_engagement/content/site_engagement_metrics.h" #include "media/base/media_switches.h" const char MediaEngagementScore::kVisitsKey[] = "visits";
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc index a9ee1e1..be5b586e 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.cc +++ b/chrome/browser/metrics/chrome_feature_list_creator.cc
@@ -20,6 +20,7 @@ #include "cc/base/switches.h" #include "chrome/browser/about_flags.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/chrome_metrics_services_manager_client.h" #include "chrome/browser/prefs/browser_prefs.h"
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.h b/chrome/browser/metrics/chrome_feature_list_creator.h index a4b5477..ecae6429 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.h +++ b/chrome/browser/metrics/chrome_feature_list_creator.h
@@ -12,7 +12,6 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/chrome_browser_field_trials.h" -#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/installer/util/initial_preferences.h" #include "components/metrics_services_manager/metrics_services_manager.h"
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 9b14c4e..68ada4a 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -183,7 +183,7 @@ #endif // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) #if defined(OS_MAC) -#include "chrome/browser/metrics/power_metrics_provider_mac.h" +#include "chrome/browser/metrics/power/power_metrics_provider_mac.h" #endif namespace {
diff --git a/chrome/browser/metrics/perf/metric_provider.cc b/chrome/browser/metrics/perf/metric_provider.cc index cd23b21..3d6a84b 100644 --- a/chrome/browser/metrics/perf/metric_provider.cc +++ b/chrome/browser/metrics/perf/metric_provider.cc
@@ -53,30 +53,6 @@ } } -// Check if App Sync is enabled for a given user profile. -bool IsAppSyncEnabledForUserProfile(Profile* profile) { - syncer::SyncService* sync_service = - ProfileSyncServiceFactory::GetForProfile(profile); - if (!sync_service) - return false; - syncer::SyncUserSettings* sync_settings = sync_service->GetUserSettings(); - - // Chrome versions >= M78 have a feature that splits the sync settings between - // Chrome and ChromeOS. The App Sync toggle is moved under the ChromeOS - // settings. If the split sync setting is enabled, we will directly read from - // the OS settings. Otherwise, we read from Chrome settings. We then check if - // the sync feature is enabled and the App Sync toggle is on. - if (chromeos::features::IsSplitSettingsSyncEnabled()) { - return sync_settings->IsOsSyncFeatureEnabled() && - sync_settings->GetSelectedOsTypes().Has( - syncer::UserSelectableOsType::kOsApps); - } - // Read chrome settings if split sync is disabled. - return sync_service->IsSyncFeatureEnabled() && - sync_settings->GetSelectedTypes().Has( - syncer::UserSelectableType::kApps); -} - } // namespace using MetricCollector = internal::MetricCollector; @@ -212,6 +188,35 @@ recording_enabled_ = false; } +MetricProvider::RecordAttemptStatus MetricProvider::AppSyncStateForUserProfile( + Profile* profile) { + syncer::SyncService* sync_service = + ProfileSyncServiceFactory::GetForProfile(profile); + if (!sync_service) + return RecordAttemptStatus::kSyncServiceUnavailable; + syncer::SyncUserSettings* sync_settings = sync_service->GetUserSettings(); + + // Chrome versions >= M78 have a feature that splits the sync settings between + // Chrome and ChromeOS. The App Sync toggle is moved under the ChromeOS + // settings. If the split sync setting is enabled, we will directly read from + // the OS settings. Otherwise, we read from Chrome settings. We then check if + // the sync feature is enabled and the App Sync toggle is on. + if (chromeos::features::IsSplitSettingsSyncEnabled()) { + if (!sync_settings->IsOsSyncFeatureEnabled()) + return RecordAttemptStatus::kOSSyncFeatureDisabled; + if (!sync_settings->GetSelectedOsTypes().Has( + syncer::UserSelectableOsType::kOsApps)) + return RecordAttemptStatus::kOSAppSyncDisabled; + return RecordAttemptStatus::kAppSyncEnabled; + } + // Read chrome settings if split sync is disabled. + if (!sync_service->IsSyncFeatureEnabled()) + return RecordAttemptStatus::kChromeSyncFeatureDisabled; + if (!sync_settings->GetSelectedTypes().Has(syncer::UserSelectableType::kApps)) + return RecordAttemptStatus::kChromeAppSyncDisabled; + return RecordAttemptStatus::kAppSyncEnabled; +} + // Check the current state of App Sync in the settings. This is done by getting // all currently fully initialized profiles and reading the sync settings from // them. @@ -230,8 +235,9 @@ // sync settings of user profiles. if (chromeos::ProfileHelper::IsSigninProfile(profile)) continue; - if (!IsAppSyncEnabledForUserProfile(profile)) - return RecordAttemptStatus::kAppSyncDisabled; + auto app_sync_state = AppSyncStateForUserProfile(profile); + if (app_sync_state != RecordAttemptStatus::kAppSyncEnabled) + return app_sync_state; user_profile_count++; }
diff --git a/chrome/browser/metrics/perf/metric_provider.h b/chrome/browser/metrics/perf/metric_provider.h index 0f0aac15..39a968b8 100644 --- a/chrome/browser/metrics/perf/metric_provider.h +++ b/chrome/browser/metrics/perf/metric_provider.h
@@ -20,6 +20,7 @@ } // namespace base class ProfileManager; +class Profile; namespace metrics { @@ -75,7 +76,12 @@ kNoLoadedProfile = 2, kAppSyncDisabled = 3, kAppSyncEnabled = 4, - kMaxValue = kAppSyncEnabled, + kSyncServiceUnavailable = 5, + kChromeSyncFeatureDisabled = 6, + kChromeAppSyncDisabled = 7, + kOSSyncFeatureDisabled = 8, + kOSAppSyncDisabled = 9, + kMaxValue = kOSAppSyncDisabled, }; // For testing. @@ -89,6 +95,9 @@ static void OnProfileDone(base::WeakPtr<MetricProvider> provider, std::unique_ptr<SampledProfile> sampled_profile); + // Check the state of App Sync for the given user profile. + RecordAttemptStatus AppSyncStateForUserProfile(Profile* profile); + // Check the state of App Sync in the current session. RecordAttemptStatus GetAppSyncState();
diff --git a/chrome/browser/metrics/perf/metric_provider_unittest.cc b/chrome/browser/metrics/perf/metric_provider_unittest.cc index 33837dc..80688d7 100644 --- a/chrome/browser/metrics/perf/metric_provider_unittest.cc +++ b/chrome/browser/metrics/perf/metric_provider_unittest.cc
@@ -454,7 +454,7 @@ SerializeMessageToVector(profile.perf_data())); histogram_tester.ExpectUniqueSample( "ChromeOS.CWP.RecordTest", - TestMetricProvider::RecordAttemptStatus::kAppSyncDisabled, 1); + TestMetricProvider::RecordAttemptStatus::kOSAppSyncDisabled, 1); } TEST_F(MetricProviderSyncSettingsTest, UnifiedSettingsAppSyncEnabled) { @@ -512,7 +512,7 @@ SerializeMessageToVector(profile.perf_data())); histogram_tester.ExpectUniqueSample( "ChromeOS.CWP.RecordTest", - TestMetricProvider::RecordAttemptStatus::kAppSyncDisabled, 1); + TestMetricProvider::RecordAttemptStatus::kChromeAppSyncDisabled, 1); } } // namespace metrics
diff --git a/chrome/browser/metrics/power/OWNERS b/chrome/browser/metrics/power/OWNERS new file mode 100644 index 0000000..61d6db73 --- /dev/null +++ b/chrome/browser/metrics/power/OWNERS
@@ -0,0 +1,3 @@ +etiennep@chromium.org +fdoray@chromium.org +olivierli@chromium.org
diff --git a/chrome/browser/metrics/power/battery_level_provider.h b/chrome/browser/metrics/power/battery_level_provider.h new file mode 100644 index 0000000..62e5748 --- /dev/null +++ b/chrome/browser/metrics/power/battery_level_provider.h
@@ -0,0 +1,47 @@ +// Copyright 2020 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_METRICS_POWER_BATTERY_LEVEL_PROVIDER_H_ +#define CHROME_BROWSER_METRICS_POWER_BATTERY_LEVEL_PROVIDER_H_ + +#include "base/callback.h" +#include "base/optional.h" + +// BatteryLevelProvider provides an interface for querrying battery state. +// A platform specific implementation is obtained with +// BatteryLevelProvider::Create(). +class BatteryLevelProvider { + public: + // Represents the state of the battery at a certain point in time. + struct BatteryState { + // A fraction of the maximal battery capacity of the system, in the range + // [0.00, 1.00]. + double charge_level = 0; + + // True if the system is running on battery power, false if the system is + // drawing power from an external power source. + bool on_battery = false; + + // The time at which the battery state capture took place. + base::TimeTicks capture_time; + }; + + // Creates a platform specific BatteryLevelProvider able to retrieve battery + // state. + static std::unique_ptr<BatteryLevelProvider> Create(); + + virtual ~BatteryLevelProvider() = default; + + BatteryLevelProvider(const BatteryLevelProvider& other) = delete; + BatteryLevelProvider& operator=(const BatteryLevelProvider& other) = delete; + + // Returns the current battery state, or nullopt if no battery is present or + // querying battery information failed. + virtual base::Optional<BatteryState> GetBatteryState() = 0; + + protected: + BatteryLevelProvider() = default; +}; + +#endif // CHROME_BROWSER_METRICS_POWER_BATTERY_LEVEL_PROVIDER_H_
diff --git a/chrome/browser/metrics/power/battery_level_provider_mac.mm b/chrome/browser/metrics/power/battery_level_provider_mac.mm new file mode 100644 index 0000000..2b989364 --- /dev/null +++ b/chrome/browser/metrics/power/battery_level_provider_mac.mm
@@ -0,0 +1,110 @@ +// Copyright 2020 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/metrics/power/battery_level_provider.h" + +#import <Foundation/Foundation.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/ps/IOPSKeys.h> + +#include "base/mac/foundation_util.h" +#include "base/mac/scoped_cftyperef.h" +#include "base/mac/scoped_ioobject.h" + +namespace { + +// Returns the value corresponding to |key| in the dictionary |description|. +// Returns |default_value| if the dictionary does not contain |key|, the +// corresponding value is nullptr or it could not be converted to SInt64. +base::Optional<SInt64> GetValueAsSInt64(CFDictionaryRef description, + CFStringRef key) { + CFNumberRef number_ref = + base::mac::GetValueFromDictionary<CFNumberRef>(description, key); + + SInt64 value; + if (number_ref && CFNumberGetValue(number_ref, kCFNumberSInt64Type, &value)) + return value; + + return base::nullopt; +} + +base::Optional<bool> GetValueAsBoolean(CFDictionaryRef description, + CFStringRef key) { + CFBooleanRef boolean = + base::mac::GetValueFromDictionary<CFBooleanRef>(description, key); + if (!boolean) + return base::nullopt; + return CFBooleanGetValue(boolean); +} + +} // namespace + +class BatteryLevelProviderMac : public BatteryLevelProvider { + public: + BatteryLevelProviderMac() = default; + ~BatteryLevelProviderMac() override = default; + + base::Optional<BatteryState> GetBatteryState() override; +}; + +std::unique_ptr<BatteryLevelProvider> BatteryLevelProvider::Create() { + return std::make_unique<BatteryLevelProviderMac>(); +} + +base::Optional<BatteryLevelProvider::BatteryState> +BatteryLevelProviderMac::GetBatteryState() { + const base::TimeTicks capture_time = base::TimeTicks::Now(); + + // Retrieve the IOPMPowerSource service. + const base::mac::ScopedIOObject<io_service_t> service( + IOServiceGetMatchingService(kIOMasterPortDefault, + IOServiceMatching("IOPMPowerSource"))); + + // Gather a dictionary containing the power information. + base::ScopedCFTypeRef<CFMutableDictionaryRef> dict; + kern_return_t result = IORegistryEntryCreateCFProperties( + service.get(), dict.InitializeInto(), 0, 0); + + // Retrieving dictionary failed. Cannot proceed. + if (result != KERN_SUCCESS) + return base::nullopt; + + base::Optional<bool> external_connected = + GetValueAsBoolean(dict, CFSTR("ExternalConnected")); + // Value was not available. + if (!external_connected.has_value()) + return base::nullopt; + + CFStringRef capacity_key; + CFStringRef max_capacity_key; + + // Use the correct key depending on macOS version. + if (@available(macOS 10.14.0, *)) { + capacity_key = CFSTR("AppleRawCurrentCapacity"); + max_capacity_key = CFSTR("AppleRawMaxCapacity"); + } else { + capacity_key = CFSTR("CurrentCapacity"); + max_capacity_key = CFSTR("RawMaxCapacity"); + } + + // Extract the information from the dictionary. + base::Optional<SInt64> current_capacity = + GetValueAsSInt64(dict, capacity_key); + base::Optional<SInt64> max_capacity = + GetValueAsSInt64(dict, max_capacity_key); + + // If any of the values were not available. + if (!current_capacity.has_value() || !max_capacity.has_value()) + return base::nullopt; + + // Avoid invalid division. + if (*max_capacity == 0) + return base::nullopt; + + // |ratio| is the result of dividing |current_capacity| by |max_capacity|. + double charge_level = static_cast<double>(current_capacity.value()) / + static_cast<double>(max_capacity.value()); + + return BatteryState{charge_level, !(*external_connected), capture_time}; +}
diff --git a/chrome/browser/metrics/power/power_metrics_provider_mac.h b/chrome/browser/metrics/power/power_metrics_provider_mac.h new file mode 100644 index 0000000..55df68d --- /dev/null +++ b/chrome/browser/metrics/power/power_metrics_provider_mac.h
@@ -0,0 +1,104 @@ +// Copyright 2018 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_METRICS_POWER_POWER_METRICS_PROVIDER_MAC_H_ +#define CHROME_BROWSER_METRICS_POWER_POWER_METRICS_PROVIDER_MAC_H_ + +#include "components/metrics/metrics_provider.h" + +#include "base/bind.h" +#include "base/macros.h" +#include "base/time/time.h" +#include "chrome/browser/metrics/power/battery_level_provider.h" + +// Records battery power drain in a histogram. To use, repeatedly call +// RecordBatteryDischarge() at regular intervals. The implementation tries to +// correct for cases where the function was called too late or too early to +// avoid recording faulty measurements. +// Example use: +// +// class UserClass { +// public: +// static constexpr base::TimeDelta kRecordingInterval = +// base::TimeDelta::FromMinutes(1); +// +// UserClass(){ +// power_drain_recorder_ = +// std::make_unique<PowerDrainRecorder>(kRecordingInterval); +// } +// +// void StartRecording() { +// timer_.Start(FROM_HERE, kRecordingInterval, +// power_drain_recorder_.get(), +// &PowerDrainRecorder::RecordBatteryDischarge); +// } +// +// private: +// std::unique_ptr<PowerDrainRecorder> power_drain_recorder_; +// base::RepeatingTimer timer_; +// }; +// +class PowerDrainRecorder { + public: + // |recording_interval| is the time that is supposed to elapse between calls + // to RecordBatteryDischarge(). + explicit PowerDrainRecorder(base::TimeDelta recording_interval); + ~PowerDrainRecorder(); + + PowerDrainRecorder(const PowerDrainRecorder& other) = delete; + PowerDrainRecorder& operator=(const PowerDrainRecorder& other) = delete; + + // Calling this function repeatedly will store the battery discharge that + // happened between calls in a histogram. + void RecordBatteryDischarge(); + + // Replace the function used to get BatteryState values. Use only for testing + // to not depend on actual system information. + void SetBatteryLevelProviderForTesting( + std::unique_ptr<BatteryLevelProvider> provider); + + private: + // Used to get the current battery state. + std::unique_ptr<BatteryLevelProvider> battery_level_provider_ = + BatteryLevelProvider::Create(); + + // Latest battery state provided by |battery_level_provider_|. + base::Optional<BatteryLevelProvider::BatteryState> battery_state_; + + // Time that should elapse between calls to RecordBatteryDischarge. + const base::TimeDelta recording_interval_; + + friend class PowerMetricsProviderTest; + FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, BatteryDischargeOnPower); + FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, BatteryDischargeOnBattery); + FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, + BatteryDischargeCapacityGrew); + FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, + BatteryDischargeCaptureIsTooEarly); + FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, + BatteryDischargeCaptureIsEarly); + FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, + BatteryDischargeCaptureIsTooLate); + FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, + BatteryDischargeCaptureIsLate); +}; + +class PowerMetricsProvider : public metrics::MetricsProvider { + public: + PowerMetricsProvider(); + ~PowerMetricsProvider() override; + + PowerMetricsProvider(const PowerMetricsProvider& other) = delete; + PowerMetricsProvider& operator=(const PowerMetricsProvider& other) = delete; + + // metrics::MetricsProvider overrides + void OnRecordingEnabled() override; + void OnRecordingDisabled() override; + + private: + class Impl; + scoped_refptr<Impl> impl_; +}; + +#endif // CHROME_BROWSER_METRICS_POWER_POWER_METRICS_PROVIDER_MAC_H_
diff --git a/chrome/browser/metrics/power/power_metrics_provider_mac.mm b/chrome/browser/metrics/power/power_metrics_provider_mac.mm new file mode 100644 index 0000000..857126d --- /dev/null +++ b/chrome/browser/metrics/power/power_metrics_provider_mac.mm
@@ -0,0 +1,385 @@ +// Copyright 2018 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/metrics/power/power_metrics_provider_mac.h" + +#include <utility> + +#import <Foundation/Foundation.h> +#include <libkern/OSByteOrder.h> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/mac/scoped_ioobject.h" +#include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" +#include "base/optional.h" +#include "base/power_monitor/power_monitor.h" +#include "base/process/process.h" +#include "base/sequenced_task_runner.h" +#include "base/task/post_task.h" +#include "base/task/thread_pool.h" +#include "base/time/time.h" +#include "chrome/browser/ui/browser_finder.h" + +namespace { +constexpr base::TimeDelta kStartupPowerMetricsCollectionDuration = + base::TimeDelta::FromSeconds(30); +constexpr base::TimeDelta kStartupPowerMetricsCollectionInterval = + base::TimeDelta::FromSeconds(1); +constexpr base::TimeDelta kPostStartupPowerMetricsCollectionInterval = + base::TimeDelta::FromSeconds(60); + +// This API is undocumented. It can read hardware sensors including +// temperature, voltage, and power. A useful tool for discovering new keys is +// <https://github.com/theopolis/smc-fuzzer>. The following definitions are +// from +// <https://opensource.apple.com/source/PowerManagement/PowerManagement-271.1.1/pmconfigd/PrivateLib.c.auto.html>. +struct SMCParamStruct { + enum { + kSMCUserClientOpen = 0, + kSMCUserClientClose = 1, + kSMCHandleYPCEvent = 2, + kSMCReadKey = 5, + kSMCGetKeyInfo = 9, + }; + + enum class SMCKey : uint32_t { + TotalPower = 'PSTR', // Power: System Total Rail (watts) + CPUPower = 'PCPC', // Power: CPU Package CPU (watts) + iGPUPower = 'PCPG', // Power: CPU Package GPU (watts) + GPU0Power = 'PG0R', // Power: GPU 0 Rail (watts) + GPU1Power = 'PG1R', // Power: GPU 1 Rail (watts) + }; + + // SMC keys are typed, and there are a number of numeric types. Support for + // decoding the ones in this enum is implemented below, but there are more + // types (and more may appear in future hardware). Implement as needed. + enum class DataType : uint32_t { + flt = 'flt ', // Floating point + sp78 = 'sp78', // Fixed point: SIIIIIIIFFFFFFFF + sp87 = 'sp87', // Fixed point: SIIIIIIIIFFFFFFF + spa5 = 'spa5', // Fixed point: SIIIIIIIIIIFFFFF + }; + + struct SMCVersion { + unsigned char major; + unsigned char minor; + unsigned char build; + unsigned char reserved; + unsigned short release; + }; + + struct SMCPLimitData { + uint16_t version; + uint16_t length; + uint32_t cpuPLimit; + uint32_t gpuPLimit; + uint32_t memPLimit; + }; + + struct SMCKeyInfoData { + IOByteCount dataSize; + DataType dataType; + uint8_t dataAttributes; + }; + + SMCKey key; + SMCVersion vers; + SMCPLimitData pLimitData; + SMCKeyInfoData keyInfo; + uint8_t result; + uint8_t status; + uint8_t data8; + uint32_t data32; + uint8_t bytes[32]; +}; + +float FromSMCFixedPoint(uint8_t* bytes, size_t fraction_bits) { + return static_cast<int16_t>(OSReadBigInt16(bytes, 0)) / + static_cast<float>(1 << fraction_bits); +} + +class SMCKey { + public: + SMCKey(base::mac::ScopedIOObject<io_object_t> connect, + SMCParamStruct::SMCKey key) + : connect_(std::move(connect)), key_(key) { + SMCParamStruct out{}; + if (CallSMCFunction(SMCParamStruct::kSMCGetKeyInfo, &out)) + keyInfo_ = out.keyInfo; + } + + bool Exists() { return keyInfo_.dataSize > 0; } + + float Read() { + if (!Exists()) + return 0; + + SMCParamStruct out{}; + if (!CallSMCFunction(SMCParamStruct::kSMCReadKey, &out)) + return 0; + switch (keyInfo_.dataType) { + case SMCParamStruct::DataType::flt: + return *reinterpret_cast<float*>(out.bytes); + case SMCParamStruct::DataType::sp78: + return FromSMCFixedPoint(out.bytes, 8); + case SMCParamStruct::DataType::sp87: + return FromSMCFixedPoint(out.bytes, 7); + case SMCParamStruct::DataType::spa5: + return FromSMCFixedPoint(out.bytes, 5); + default: + break; + } + return 0; + } + + private: + bool CallSMCFunction(uint8_t which, SMCParamStruct* out) { + if (!connect_) + return false; + if (IOConnectCallMethod(connect_, SMCParamStruct::kSMCUserClientOpen, + nullptr, 0, nullptr, 0, nullptr, nullptr, nullptr, + nullptr)) { + connect_.reset(); + return false; + } + + SMCParamStruct in{}; + in.key = key_; + in.keyInfo.dataSize = keyInfo_.dataSize; + in.data8 = which; + + size_t out_size = sizeof(*out); + bool success = IOConnectCallStructMethod( + connect_, SMCParamStruct::kSMCHandleYPCEvent, &in, + sizeof(in), out, &out_size) == kIOReturnSuccess; + + if (IOConnectCallMethod(connect_, SMCParamStruct::kSMCUserClientClose, + nullptr, 0, nullptr, 0, nullptr, nullptr, nullptr, + nullptr)) + connect_.reset(); + + // Even if the close failed, report whether the actual call succeded. + return success; + } + + base::mac::ScopedIOObject<io_object_t> connect_; + SMCParamStruct::SMCKey key_; + SMCParamStruct::SMCKeyInfoData keyInfo_{}; +}; + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class ThermalStateUMA { + kNominal = 0, + kFair = 1, + kSerious = 2, + kCritical = 3, + kMaxValue = kCritical, +}; + +ThermalStateUMA ThermalStateToUmaEnumValue(NSProcessInfoThermalState state) { + switch (state) { + case NSProcessInfoThermalStateNominal: + return ThermalStateUMA::kNominal; + case NSProcessInfoThermalStateFair: + return ThermalStateUMA::kFair; + case NSProcessInfoThermalStateSerious: + return ThermalStateUMA::kSerious; + case NSProcessInfoThermalStateCritical: + return ThermalStateUMA::kCritical; + } +} + +} // namespace + +PowerDrainRecorder::PowerDrainRecorder(base::TimeDelta recording_interval) + : recording_interval_(recording_interval) {} +PowerDrainRecorder::~PowerDrainRecorder() = default; + +void PowerDrainRecorder::RecordBatteryDischarge() { + base::Optional<BatteryLevelProvider::BatteryState> previous_battery_state = + std::exchange(battery_state_, battery_level_provider_->GetBatteryState()); + + // Missing battery values. + if (!battery_state_.has_value() || !previous_battery_state.has_value()) + return; + + // Not discharging. + if (!battery_state_->on_battery || !previous_battery_state->on_battery) + return; + + if (battery_state_->charge_level > previous_battery_state->charge_level) { + // Charge level went up since last measurement. It's suspected the computer + // was charged for less than the collection interval. Consider this time + // slice as not even "on battery". + return; + } + + const base::TimeDelta time_since_last_record = + battery_state_->capture_time - previous_battery_state->capture_time; + + // Ratio by which the time elapsed can deviate from |recording_interval| + // without invalidating this sample. + constexpr double kTolerableTimeElapsedRatio = 0.10; + constexpr double kTolerablePositiveDrift = 1 + kTolerableTimeElapsedRatio; + constexpr double kTolerableNegativeDrift = 1 - kTolerableTimeElapsedRatio; + + if (time_since_last_record > + (recording_interval_ * kTolerablePositiveDrift)) { + // Too much time passed since the last record. Either the task took + // too long to get executed or system sleep took place. + return; + } + + if (time_since_last_record < + (recording_interval_ * kTolerableNegativeDrift)) { + // The recording task executed too early after the previous one, possibly + // because the previous task took too long to execute. + return; + } + + // |time_elapsed_ratio| is used to normalize discharge rate measurements to + // the expected recording period. + const double time_elapsed_ratio = + recording_interval_.InSeconds() / time_since_last_record.InSecondsF(); + + // The charge_level is a ratio in range [0.00, 1.00]. The difference between + // two of these values is what will be stored in a histogram. This histogram + // will have a bucket of size 1000 so the value is multiplied by 10000 to + // bring it in the range of [0, 10000]. + constexpr int kScalingFactor = 10000; + int discharge = + kScalingFactor * time_elapsed_ratio * + (previous_battery_state->charge_level - battery_state_->charge_level); + base::UmaHistogramCounts1000("Power.Mac.BatteryDischarge", discharge); +} + +void PowerDrainRecorder::SetBatteryLevelProviderForTesting( + std::unique_ptr<BatteryLevelProvider> provider) { + battery_level_provider_ = std::move(provider); +} + +class PowerMetricsProvider::Impl : public base::RefCountedThreadSafe<Impl> { + public: + static scoped_refptr<Impl> Create( + base::mac::ScopedIOObject<io_object_t> connect) { + scoped_refptr<Impl> impl = new Impl(std::move(connect)); + impl->ScheduleCollection(); + return impl; + } + + private: + friend class base::RefCountedThreadSafe<Impl>; + Impl(base::mac::ScopedIOObject<io_object_t> connect) + : task_runner_(base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), + system_total_power_key_(connect, SMCParamStruct::SMCKey::TotalPower), + cpu_package_cpu_power_key_(connect, SMCParamStruct::SMCKey::CPUPower), + cpu_package_gpu_power_key_(connect, SMCParamStruct::SMCKey::iGPUPower), + gpu_0_power_key_(connect, SMCParamStruct::SMCKey::GPU0Power), + gpu_1_power_key_(connect, SMCParamStruct::SMCKey::GPU0Power), + power_drain_calculator_(kPostStartupPowerMetricsCollectionInterval) {} + + ~Impl() = default; + + bool IsInStartup() { + if (could_be_in_startup_) { + const base::TimeDelta process_uptime = + base::Time::Now() - base::Process::Current().CreationTime(); + if (process_uptime >= kStartupPowerMetricsCollectionDuration) + could_be_in_startup_ = false; + } + return could_be_in_startup_; + } + + void ScheduleCollection() { + task_runner_->PostDelayedTask( + FROM_HERE, base::BindOnce(&Impl::Collect, this), + IsInStartup() ? kStartupPowerMetricsCollectionInterval + : kPostStartupPowerMetricsCollectionInterval); + } + + void Collect() { + ScheduleCollection(); + + if (IsInStartup()) { + RecordSMC("DuringStartup"); + } else { + RecordSMC("All"); + RecordIsOnBattery(); + power_drain_calculator_.RecordBatteryDischarge(); + RecordThermal(); + } + } + + void RecordSMC(const std::string& name) { + const struct { + const char* uma_prefix; + SMCKey& smc_key; + } sensors[] = { + {"Power.Mac.Total.", system_total_power_key_}, + {"Power.Mac.CPU.", cpu_package_cpu_power_key_}, + {"Power.Mac.GPUi.", cpu_package_gpu_power_key_}, + {"Power.Mac.GPU0.", gpu_0_power_key_}, + {"Power.Mac.GPU1.", gpu_1_power_key_}, + }; + for (const auto& sensor : sensors) { + if (sensor.smc_key.Exists()) { + if (auto power_mw = sensor.smc_key.Read() * 1000) + base::UmaHistogramCounts100000(sensor.uma_prefix + name, power_mw); + } + } + } + + void RecordIsOnBattery() { + bool is_on_battery = false; + if (base::PowerMonitor::IsInitialized()) + is_on_battery = base::PowerMonitor::IsOnBatteryPower(); + UMA_HISTOGRAM_BOOLEAN("Power.Mac.IsOnBattery2", is_on_battery); + } + + void RecordThermal() { + UMA_HISTOGRAM_ENUMERATION( + "Power.Mac.ThermalState", + ThermalStateToUmaEnumValue([[NSProcessInfo processInfo] thermalState])); + } + + scoped_refptr<base::SequencedTaskRunner> task_runner_; + bool could_be_in_startup_ = true; + + SMCKey system_total_power_key_; + SMCKey cpu_package_cpu_power_key_; + SMCKey cpu_package_gpu_power_key_; + SMCKey gpu_0_power_key_; + SMCKey gpu_1_power_key_; + + PowerDrainRecorder power_drain_calculator_; + + DISALLOW_COPY_AND_ASSIGN(Impl); +}; + +PowerMetricsProvider::PowerMetricsProvider() = default; +PowerMetricsProvider::~PowerMetricsProvider() = default; + +void PowerMetricsProvider::OnRecordingEnabled() { + const base::mac::ScopedIOObject<io_service_t> smc_service( + IOServiceGetMatchingService(kIOMasterPortDefault, + IOServiceMatching("AppleSMC"))); + io_object_t connect; + bool service_opened = IOServiceOpen(smc_service, mach_task_self(), 1, + &connect) == kIOReturnSuccess; + UMA_HISTOGRAM_BOOLEAN("Power.Mac.AppleSMCOpened", service_opened); + if (!service_opened) + return; + impl_ = Impl::Create(base::mac::ScopedIOObject<io_object_t>(connect)); +} + +void PowerMetricsProvider::OnRecordingDisabled() { + impl_.reset(); +}
diff --git a/chrome/browser/metrics/power/power_metrics_provider_mac_unittest.cc b/chrome/browser/metrics/power/power_metrics_provider_mac_unittest.cc new file mode 100644 index 0000000..17c0969 --- /dev/null +++ b/chrome/browser/metrics/power/power_metrics_provider_mac_unittest.cc
@@ -0,0 +1,212 @@ +// Copyright 2020 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/metrics/power/power_metrics_provider_mac.h" + +#include <queue> + +#include "base/callback.h" +#include "base/metrics/histogram.h" +#include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/time/time.h" +#include "chrome/browser/metrics/power/battery_level_provider.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +constexpr const char* kHistogramName = "Power.Mac.BatteryDischarge"; +constexpr base::TimeDelta kMetricsCollectionInterval = + base::TimeDelta::FromSeconds(60); +constexpr double kTolerableTimeElapsedRatio = 0.10; +constexpr double kTolerablePositiveDrift = 1 + kTolerableTimeElapsedRatio; +constexpr double kTolerableNegativeDrift = 1 - kTolerableTimeElapsedRatio; +} // namespace + +class PowerMetricsProviderTest : public testing::Test { + public: + class FakeBatteryLevelProvider : public BatteryLevelProvider { + public: + FakeBatteryLevelProvider( + std::queue<BatteryLevelProvider::BatteryState>* battery_states) + : battery_states_(battery_states) {} + + base::Optional<BatteryState> GetBatteryState() override { + DCHECK(!battery_states_->empty()); + BatteryLevelProvider::BatteryState state = battery_states_->front(); + battery_states_->pop(); + return state; + } + + private: + std::queue<BatteryLevelProvider::BatteryState>* battery_states_; + }; + + PowerMetricsProviderTest() + : power_drain_recorder_(kMetricsCollectionInterval) {} + void SetUp() override { + // Setup |power_drain_recorder_| to use use the BatteryState values + // provided by the tests instead of querying the system to build them. + power_drain_recorder_.SetBatteryLevelProviderForTesting( + std::make_unique<FakeBatteryLevelProvider>(&battery_states_)); + } + + void TearDown() override { + // All values should have been used in the test. + ASSERT_TRUE(battery_states_.empty()); + } + + void ConsumeBatteryStates() { + const size_t number_of_test_states = battery_states_.size(); + for (size_t i = 0; i < number_of_test_states; ++i) { + power_drain_recorder_.RecordBatteryDischarge(); + } + } + + protected: + static constexpr int kScalingFactor = 10000; + + PowerDrainRecorder power_drain_recorder_; + base::HistogramTester histogram_tester_; + std::queue<BatteryLevelProvider::BatteryState> battery_states_; + base::TimeTicks now_; +}; + +TEST_F(PowerMetricsProviderTest, BatteryDischargeOnPower) { + // Two consecutive readings on power should not record a battery discharge. + battery_states_.push(BatteryLevelProvider::BatteryState{1.00, false, now_}); + battery_states_.push(BatteryLevelProvider::BatteryState{ + 1.000, false, now_ + base::TimeDelta::FromMinutes(1)}); + + ConsumeBatteryStates(); + histogram_tester_.ExpectTotalCount(kHistogramName, 0); +} + +TEST_F(PowerMetricsProviderTest, BatteryDischargeOnBattery) { + constexpr double kFirstReading = 0.100; + constexpr double kSecondReading = 0.098; + + // Two consecutive readings on battery should record a battery discharge. + battery_states_.push( + BatteryLevelProvider::BatteryState{kFirstReading, true, now_}); + battery_states_.push(BatteryLevelProvider::BatteryState{ + kSecondReading, true, now_ + base::TimeDelta::FromMinutes(1)}); + + ConsumeBatteryStates(); + histogram_tester_.ExpectUniqueSample( + kHistogramName, (kFirstReading - kSecondReading) * kScalingFactor, 1); +} + +TEST_F(PowerMetricsProviderTest, BatteryDischargeCapacityGrew) { + // Capacity that grew between measurements means no discharge. No value should + // be recorded. + constexpr double kFirstReading = 0.098; + constexpr double kSecondReading = 0.100; + + battery_states_.push( + BatteryLevelProvider::BatteryState{kFirstReading, true, now_}); + battery_states_.push(BatteryLevelProvider::BatteryState{ + kSecondReading, true, now_ + base::TimeDelta::FromMinutes(1)}); + + ConsumeBatteryStates(); + histogram_tester_.ExpectTotalCount(kHistogramName, 0); +} + +TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsTooEarly) { + constexpr double kFirstReading = 0.100; + constexpr double kSecondReading = 0.098; + + const base::TimeTicks first_capture_time = + now_ + base::TimeDelta::FromSeconds(60); + const base::TimeTicks second_capture_time = + first_capture_time + + (kMetricsCollectionInterval * kTolerableNegativeDrift) - + base::TimeDelta::FromSeconds(1); + + // If it took too long to record a value no recoding takes place. + battery_states_.push(BatteryLevelProvider::BatteryState{kFirstReading, true, + first_capture_time}); + battery_states_.push(BatteryLevelProvider::BatteryState{kSecondReading, true, + second_capture_time}); + + ConsumeBatteryStates(); + histogram_tester_.ExpectTotalCount(kHistogramName, 0); +} + +TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsEarly) { + constexpr double kFirstReading = 0.100; + constexpr double kSecondReading = 0.098; + + const base::TimeTicks first_capture_time = + now_ + base::TimeDelta::FromSeconds(60); + const base::TimeTicks second_capture_time = + first_capture_time + + (kMetricsCollectionInterval * kTolerableNegativeDrift) + + base::TimeDelta::FromSeconds(1); + + // The second recording came in just in time to not be counted as too early. + battery_states_.push(BatteryLevelProvider::BatteryState{kFirstReading, true, + first_capture_time}); + battery_states_.push(BatteryLevelProvider::BatteryState{kSecondReading, true, + second_capture_time}); + + ConsumeBatteryStates(); + + // The discharge rate is normalized to be representative over + // |kMetricsCollectionInterval|. + int discharge = + base::ClampFloor((kFirstReading - kSecondReading) * kScalingFactor * + (kMetricsCollectionInterval / + (second_capture_time - first_capture_time))); + histogram_tester_.ExpectUniqueSample(kHistogramName, discharge, 1); +} + +TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsTooLate) { + constexpr double kFirstReading = 0.100; + constexpr double kSecondReading = 0.098; + + const base::TimeTicks first_capture_time = now_; + + // Go just slightly over the acceptable drift. + const base::TimeTicks second_capture_time = + first_capture_time + + (kMetricsCollectionInterval * kTolerablePositiveDrift) + + base::TimeDelta::FromSeconds(1); + + // If it took too long to record a value no recoding takes place. + battery_states_.push(BatteryLevelProvider::BatteryState{kFirstReading, true, + first_capture_time}); + battery_states_.push(BatteryLevelProvider::BatteryState{kSecondReading, true, + second_capture_time}); + + ConsumeBatteryStates(); + histogram_tester_.ExpectTotalCount(kHistogramName, 0); +} + +TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsLate) { + constexpr double kFirstReading = 0.100; + constexpr double kSecondReading = 0.098; + + const base::TimeTicks first_capture_time = now_; + const base::TimeTicks second_capture_time = + first_capture_time + + (kMetricsCollectionInterval * kTolerablePositiveDrift) - + base::TimeDelta::FromSeconds(1); + + // If it took longer to record the metric the value recorded is scaled to + // normalize to one minute. + battery_states_.push(BatteryLevelProvider::BatteryState{kFirstReading, true, + first_capture_time}); + battery_states_.push(BatteryLevelProvider::BatteryState{kSecondReading, true, + second_capture_time}); + + ConsumeBatteryStates(); + + // The discharge rate is normalized to be representative over + // |kMetricsCollectionInterval|. + int discharge = + base::ClampFloor((kFirstReading - kSecondReading) * kScalingFactor * + (kMetricsCollectionInterval / + (second_capture_time - first_capture_time))); + histogram_tester_.ExpectUniqueSample(kHistogramName, discharge, 1); +}
diff --git a/chrome/browser/metrics/power_metrics_provider_mac.h b/chrome/browser/metrics/power_metrics_provider_mac.h deleted file mode 100644 index f860431..0000000 --- a/chrome/browser/metrics/power_metrics_provider_mac.h +++ /dev/null
@@ -1,147 +0,0 @@ -// Copyright 2018 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_METRICS_POWER_METRICS_PROVIDER_MAC_H_ -#define CHROME_BROWSER_METRICS_POWER_METRICS_PROVIDER_MAC_H_ - -#include "components/metrics/metrics_provider.h" - -#include "base/bind.h" -#include "base/macros.h" -#include "base/time/time.h" - -// Records battery power drain in a histogram. To use, repeatedly call -// RecordBatteryDischarge() at regular intervals. The implementation tries to -// correct for cases where the function was called too late or too early to -// avoid recording faulty measurements. -// Example use: -// -// class UserClass { -// public: -// static constexpr base::TimeDelta kRecordingInterval = -// base::TimeDelta::FromMinutes(1); -// -// UserClass(){ -// power_drain_recorder_ = -// std::make_unique<PowerDrainRecorder>(kRecordingInterval); -// } -// -// void StartRecording() { -// timer_.Start(FROM_HERE, kRecordingInterval, -// power_drain_recorder_.get(), -// &PowerDrainRecorder::RecordBatteryDischarge); -// } -// -// private: -// std::unique_ptr<PowerDrainRecorder> power_drain_recorder_; -// base::RepeatingTimer timer_; -// }; -// -class PowerDrainRecorder { - private: - // Represents the state of the battery at a certain point in time. - class BatteryState { - public: - // Use this constructor to extract the actual battery information using - // system functions. - BatteryState(); - - // Use this constructor to control the value of all the members. - BatteryState(int capacity, bool on_battery, base::TimeTicks creation_time); - - // Returns the battery capacity at the time of capture. - int capacity() const { return capacity_; } - - // Returns true if the system ran on battery power at the time of capture. - bool on_battery() const { return on_battery_; } - - // Explicitly mark the state object as on battery on not. - void SetIsOnBattery(bool on_battery); - - // Return the time at which the object was created. - base::TimeTicks creation_time() const { return creation_time_; } - - private: - // A portion of the maximal battery capacity of the system. Units are - // hundredths of a percent. ie: 99.8742% capacity --> 998742. - int capacity_ = 0; - - // For the purpose of this class not being on battery power is considered - // equivalent to charging. - bool on_battery_ = false; - - // The time at which the battery state capture took place. - base::TimeTicks creation_time_; - }; - - public: - // |recording_interval| is the time that is supposed to elapse between calls - // to RecordBatteryDischarge(). - explicit PowerDrainRecorder(base::TimeDelta recording_interval); - ~PowerDrainRecorder(); - - PowerDrainRecorder(const PowerDrainRecorder& other) = delete; - PowerDrainRecorder& operator=(const PowerDrainRecorder& other) = delete; - - // Calling this function repeatedly will store the battery discharge that - // happened between calls in a histogram. - void RecordBatteryDischarge(); - - // Replace the function used to get BatteryState values. Use only for testing - // to not depend on actual system information. - void SetGetBatteryStateCallBackForTesting( - base::RepeatingCallback<BatteryState()>); - - private: - // Simply creates a BatteryState() object and returns it. Stand-in that can - // replaced in tests. - BatteryState GetCurrentBatteryState(); - - // Use this callback to get the current battery state. Override in tests to - // provide test values. - base::RepeatingCallback<BatteryState()> battery_state_callback_ = - base::BindRepeating(&PowerDrainRecorder::GetCurrentBatteryState, - base::Unretained(this)); - - // Default battery state value that makes sure it will not be used towards the - // first discharge calculation that will happen at some point in the future. - BatteryState previous_battery_state_ = - BatteryState(0, false, base::TimeTicks{}); - - // Time that should elapse between calls to RecordBatteryDischarge. - const base::TimeDelta recording_interval_; - - friend class PowerMetricsProviderTest; - FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, BatteryDischargeOnPower); - FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, BatteryDischargeOnBattery); - FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, - BatteryDischargeCapacityGrew); - FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, - BatteryDischargeCaptureIsTooEarly); - FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, - BatteryDischargeCaptureIsEarly); - FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, - BatteryDischargeCaptureIsTooLate); - FRIEND_TEST_ALL_PREFIXES(PowerMetricsProviderTest, - BatteryDischargeCaptureIsLate); -}; - -class PowerMetricsProvider : public metrics::MetricsProvider { - public: - PowerMetricsProvider(); - ~PowerMetricsProvider() override; - - PowerMetricsProvider(const PowerMetricsProvider& other) = delete; - PowerMetricsProvider& operator=(const PowerMetricsProvider& other) = delete; - - // metrics::MetricsProvider overrides - void OnRecordingEnabled() override; - void OnRecordingDisabled() override; - - private: - class Impl; - scoped_refptr<Impl> impl_; -}; - -#endif // CHROME_BROWSER_METRICS_POWER_METRICS_PROVIDER_MAC_H_
diff --git a/chrome/browser/metrics/power_metrics_provider_mac.mm b/chrome/browser/metrics/power_metrics_provider_mac.mm deleted file mode 100644 index 2f69eaa..0000000 --- a/chrome/browser/metrics/power_metrics_provider_mac.mm +++ /dev/null
@@ -1,475 +0,0 @@ -// Copyright 2018 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/metrics/power_metrics_provider_mac.h" - -#import <Foundation/Foundation.h> -#include <IOKit/IOKitLib.h> -#include <libkern/OSByteOrder.h> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_ioobject.h" -#include "base/macros.h" -#include "base/memory/scoped_refptr.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/optional.h" -#include "base/power_monitor/power_monitor.h" -#include "base/process/process.h" -#include "base/sequenced_task_runner.h" -#include "base/task/post_task.h" -#include "base/task/thread_pool.h" -#include "base/time/time.h" -#include "chrome/browser/ui/browser_finder.h" - -namespace { -constexpr base::TimeDelta kStartupPowerMetricsCollectionDuration = - base::TimeDelta::FromSeconds(30); -constexpr base::TimeDelta kStartupPowerMetricsCollectionInterval = - base::TimeDelta::FromSeconds(1); -constexpr base::TimeDelta kPostStartupPowerMetricsCollectionInterval = - base::TimeDelta::FromSeconds(60); - -// Returns the value corresponding to |key| in the dictionary |description|. -// Returns an unpopulated value if the dictionary does not contain |key|, the -// corresponding value is nullptr or it could not be converted to SInt64. -base::Optional<SInt64> GetValueAsSInt64(CFDictionaryRef description, - CFStringRef key) { - base::Optional<SInt64> value; - - CFNumberRef number = - base::mac::GetValueFromDictionary<CFNumberRef>(description, key); - - SInt64 v; - if (number && CFNumberGetValue(number, kCFNumberSInt64Type, &v)) { - value.emplace(v); - } - - return value; -} - -// This API is undocumented. It can read hardware sensors including -// temperature, voltage, and power. A useful tool for discovering new keys is -// <https://github.com/theopolis/smc-fuzzer>. The following definitions are -// from -// <https://opensource.apple.com/source/PowerManagement/PowerManagement-271.1.1/pmconfigd/PrivateLib.c.auto.html>. -struct SMCParamStruct { - enum { - kSMCUserClientOpen = 0, - kSMCUserClientClose = 1, - kSMCHandleYPCEvent = 2, - kSMCReadKey = 5, - kSMCGetKeyInfo = 9, - }; - - enum class SMCKey : uint32_t { - TotalPower = 'PSTR', // Power: System Total Rail (watts) - CPUPower = 'PCPC', // Power: CPU Package CPU (watts) - iGPUPower = 'PCPG', // Power: CPU Package GPU (watts) - GPU0Power = 'PG0R', // Power: GPU 0 Rail (watts) - GPU1Power = 'PG1R', // Power: GPU 1 Rail (watts) - }; - - // SMC keys are typed, and there are a number of numeric types. Support for - // decoding the ones in this enum is implemented below, but there are more - // types (and more may appear in future hardware). Implement as needed. - enum class DataType : uint32_t { - flt = 'flt ', // Floating point - sp78 = 'sp78', // Fixed point: SIIIIIIIFFFFFFFF - sp87 = 'sp87', // Fixed point: SIIIIIIIIFFFFFFF - spa5 = 'spa5', // Fixed point: SIIIIIIIIIIFFFFF - }; - - struct SMCVersion { - unsigned char major; - unsigned char minor; - unsigned char build; - unsigned char reserved; - unsigned short release; - }; - - struct SMCPLimitData { - uint16_t version; - uint16_t length; - uint32_t cpuPLimit; - uint32_t gpuPLimit; - uint32_t memPLimit; - }; - - struct SMCKeyInfoData { - IOByteCount dataSize; - DataType dataType; - uint8_t dataAttributes; - }; - - SMCKey key; - SMCVersion vers; - SMCPLimitData pLimitData; - SMCKeyInfoData keyInfo; - uint8_t result; - uint8_t status; - uint8_t data8; - uint32_t data32; - uint8_t bytes[32]; -}; - -float FromSMCFixedPoint(uint8_t* bytes, size_t fraction_bits) { - return static_cast<int16_t>(OSReadBigInt16(bytes, 0)) / - static_cast<float>(1 << fraction_bits); -} - -class SMCKey { - public: - SMCKey(base::mac::ScopedIOObject<io_object_t> connect, - SMCParamStruct::SMCKey key) - : connect_(std::move(connect)), key_(key) { - SMCParamStruct out{}; - if (CallSMCFunction(SMCParamStruct::kSMCGetKeyInfo, &out)) - keyInfo_ = out.keyInfo; - } - - bool Exists() { return keyInfo_.dataSize > 0; } - - float Read() { - if (!Exists()) - return 0; - - SMCParamStruct out{}; - if (!CallSMCFunction(SMCParamStruct::kSMCReadKey, &out)) - return 0; - switch (keyInfo_.dataType) { - case SMCParamStruct::DataType::flt: - return *reinterpret_cast<float*>(out.bytes); - case SMCParamStruct::DataType::sp78: - return FromSMCFixedPoint(out.bytes, 8); - case SMCParamStruct::DataType::sp87: - return FromSMCFixedPoint(out.bytes, 7); - case SMCParamStruct::DataType::spa5: - return FromSMCFixedPoint(out.bytes, 5); - default: - break; - } - return 0; - } - - private: - bool CallSMCFunction(uint8_t which, SMCParamStruct* out) { - if (!connect_) - return false; - if (IOConnectCallMethod(connect_, SMCParamStruct::kSMCUserClientOpen, - nullptr, 0, nullptr, 0, nullptr, nullptr, nullptr, - nullptr)) { - connect_.reset(); - return false; - } - - SMCParamStruct in{}; - in.key = key_; - in.keyInfo.dataSize = keyInfo_.dataSize; - in.data8 = which; - - size_t out_size = sizeof(*out); - bool success = IOConnectCallStructMethod( - connect_, SMCParamStruct::kSMCHandleYPCEvent, &in, - sizeof(in), out, &out_size) == kIOReturnSuccess; - - if (IOConnectCallMethod(connect_, SMCParamStruct::kSMCUserClientClose, - nullptr, 0, nullptr, 0, nullptr, nullptr, nullptr, - nullptr)) - connect_.reset(); - - // Even if the close failed, report whether the actual call succeded. - return success; - } - - base::mac::ScopedIOObject<io_object_t> connect_; - SMCParamStruct::SMCKey key_; - SMCParamStruct::SMCKeyInfoData keyInfo_{}; -}; - -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. -enum class ThermalStateUMA { - kNominal = 0, - kFair = 1, - kSerious = 2, - kCritical = 3, - kMaxValue = kCritical, -}; - -ThermalStateUMA ThermalStateToUmaEnumValue(NSProcessInfoThermalState state) { - switch (state) { - case NSProcessInfoThermalStateNominal: - return ThermalStateUMA::kNominal; - case NSProcessInfoThermalStateFair: - return ThermalStateUMA::kFair; - case NSProcessInfoThermalStateSerious: - return ThermalStateUMA::kSerious; - case NSProcessInfoThermalStateCritical: - return ThermalStateUMA::kCritical; - } -} - -} // namespace - -PowerDrainRecorder::BatteryState::BatteryState(int capacity, - bool on_battery, - base::TimeTicks creation_time) - : capacity_(capacity), - on_battery_(on_battery), - creation_time_(creation_time) {} - -PowerDrainRecorder::BatteryState::BatteryState() - : on_battery_(base::PowerMonitor::IsOnBatteryPower()), - creation_time_(base::TimeTicks::Now()) { - // Retrieve the IOPMPowerSource service. - const base::mac::ScopedIOObject<io_service_t> service( - IOServiceGetMatchingService(kIOMasterPortDefault, - IOServiceMatching("IOPMPowerSource"))); - - // Gather a dictionary containing the power information. - base::ScopedCFTypeRef<CFMutableDictionaryRef> dict; - kern_return_t result = IORegistryEntryCreateCFProperties( - service.get(), dict.InitializeInto(), 0, 0); - - // Retrieving dictionary failed. Cannot proceed. - if (result != KERN_SUCCESS) { - // Mark this recording as not on battery so it does not get used in - // calculations. - on_battery_ = false; - return; - } - - CFStringRef capacity_key; - CFStringRef max_capacity_key; - - // Use the correct key depending on macOS version. - if (@available(macOS 10.14.0, *)) { - capacity_key = CFSTR("AppleRawCurrentCapacity"); - max_capacity_key = CFSTR("AppleRawMaxCapacity"); - } else { - capacity_key = CFSTR("CurrentCapacity"); - max_capacity_key = CFSTR("RawMaxCapacity"); - } - - // Extract the information from the dictionary. - base::Optional<SInt64> current_capacity = - GetValueAsSInt64(dict, capacity_key); - base::Optional<SInt64> max_capacity = - GetValueAsSInt64(dict, max_capacity_key); - - // If any of the values were not available. - if (!current_capacity.has_value() || !max_capacity.has_value()) { - // Mark this recording as not on battery so it does not get used in - // calculations. - on_battery_ = false; - return; - } - - double ratio = static_cast<double>(current_capacity.value()) / - static_cast<double>(max_capacity.value()); - - // |ratio| is a the result of dividing |current_capacity| by |max_capacity|. - // |current_capacity| is smaller or equal to |max_capacity| so the ratio is - // in range [0.00, 1.00]. The difference between two of these values is what - // will be stored in a histogram. This histogram will have a bucket of size - // 1000 so the value is multiplied by 10000 to bring it in the range of - // [0, 10000]. - constexpr int kScalingFactor = 10000; - capacity_ = kScalingFactor * ratio; -} - -void PowerDrainRecorder::BatteryState::SetIsOnBattery(bool on_battery) { - on_battery_ = on_battery; -} - -PowerDrainRecorder::PowerDrainRecorder(base::TimeDelta recording_interval) - : recording_interval_(recording_interval) {} -PowerDrainRecorder::~PowerDrainRecorder() = default; - -void PowerDrainRecorder::RecordBatteryDischarge() { - BatteryState current_state = battery_state_callback_.Run(); - - bool should_record = true; - - // Not discharging. - if (!current_state.on_battery() || !previous_battery_state_.on_battery()) { - should_record = false; - } - - if (current_state.capacity() > previous_battery_state_.capacity()) { - // Capacity went up since last measurement. It's suspected the computer - // was charged for less than the collection interval. Consider this time - // slice as not even "on battery". - should_record = false; - } - - const base::TimeDelta time_since_last_record = - current_state.creation_time() - previous_battery_state_.creation_time(); - - // Ratio by which the time elapsed can deviate from |recording_interval| - // without invalidating this sample. - constexpr double kTolerableTimeElapsedRatio = 0.10; - constexpr double kTolerablePositiveDrift = 1 + kTolerableTimeElapsedRatio; - constexpr double kTolerableNegativeDrift = 1 - kTolerableTimeElapsedRatio; - - if (time_since_last_record > - (recording_interval_ * kTolerablePositiveDrift)) { - // Too much time passed since the last record. Either the task took - // too long to get executed or system sleep took place. - should_record = false; - } - - if (time_since_last_record < - (recording_interval_ * kTolerableNegativeDrift)) { - // The recording task executed too early after the previous one, possibly - // because the previous task took too long to execute. - should_record = false; - } - - if (should_record) { - // Use this to normalize all measurements to to recording period. - const double time_elapsed_ratio = - recording_interval_.InSeconds() / time_since_last_record.InSecondsF(); - - int discharge = time_elapsed_ratio * (previous_battery_state_.capacity() - - current_state.capacity()); - base::UmaHistogramCounts1000("Power.Mac.BatteryDischarge", discharge); - } - - // Update the battery state. - previous_battery_state_ = current_state; -} - -void PowerDrainRecorder::SetGetBatteryStateCallBackForTesting( - base::RepeatingCallback<BatteryState()> callback) { - battery_state_callback_ = callback; -} - -// static -PowerDrainRecorder::BatteryState PowerDrainRecorder::GetCurrentBatteryState() { - return PowerDrainRecorder::BatteryState{}; -} - -class PowerMetricsProvider::Impl : public base::RefCountedThreadSafe<Impl> { - public: - static scoped_refptr<Impl> Create( - base::mac::ScopedIOObject<io_object_t> connect) { - scoped_refptr<Impl> impl = new Impl(std::move(connect)); - impl->ScheduleCollection(); - return impl; - } - - private: - friend class base::RefCountedThreadSafe<Impl>; - Impl(base::mac::ScopedIOObject<io_object_t> connect) - : task_runner_(base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), - system_total_power_key_(connect, SMCParamStruct::SMCKey::TotalPower), - cpu_package_cpu_power_key_(connect, SMCParamStruct::SMCKey::CPUPower), - cpu_package_gpu_power_key_(connect, SMCParamStruct::SMCKey::iGPUPower), - gpu_0_power_key_(connect, SMCParamStruct::SMCKey::GPU0Power), - gpu_1_power_key_(connect, SMCParamStruct::SMCKey::GPU0Power), - power_drain_calculator_(kPostStartupPowerMetricsCollectionInterval) {} - - ~Impl() = default; - - bool IsInStartup() { - if (could_be_in_startup_) { - const base::TimeDelta process_uptime = - base::Time::Now() - base::Process::Current().CreationTime(); - if (process_uptime >= kStartupPowerMetricsCollectionDuration) - could_be_in_startup_ = false; - } - return could_be_in_startup_; - } - - void ScheduleCollection() { - task_runner_->PostDelayedTask( - FROM_HERE, base::BindOnce(&Impl::Collect, this), - IsInStartup() ? kStartupPowerMetricsCollectionInterval - : kPostStartupPowerMetricsCollectionInterval); - } - - void Collect() { - ScheduleCollection(); - - if (IsInStartup()) { - RecordSMC("DuringStartup"); - } else { - RecordSMC("All"); - RecordIsOnBattery(); - power_drain_calculator_.RecordBatteryDischarge(); - RecordThermal(); - } - } - - void RecordSMC(const std::string& name) { - const struct { - const char* uma_prefix; - SMCKey& smc_key; - } sensors[] = { - {"Power.Mac.Total.", system_total_power_key_}, - {"Power.Mac.CPU.", cpu_package_cpu_power_key_}, - {"Power.Mac.GPUi.", cpu_package_gpu_power_key_}, - {"Power.Mac.GPU0.", gpu_0_power_key_}, - {"Power.Mac.GPU1.", gpu_1_power_key_}, - }; - for (const auto& sensor : sensors) { - if (sensor.smc_key.Exists()) { - if (auto power_mw = sensor.smc_key.Read() * 1000) - base::UmaHistogramCounts100000(sensor.uma_prefix + name, power_mw); - } - } - } - - void RecordIsOnBattery() { - bool is_on_battery = false; - if (base::PowerMonitor::IsInitialized()) - is_on_battery = base::PowerMonitor::IsOnBatteryPower(); - UMA_HISTOGRAM_BOOLEAN("Power.Mac.IsOnBattery2", is_on_battery); - } - - void RecordThermal() { - UMA_HISTOGRAM_ENUMERATION( - "Power.Mac.ThermalState", - ThermalStateToUmaEnumValue([[NSProcessInfo processInfo] thermalState])); - } - - scoped_refptr<base::SequencedTaskRunner> task_runner_; - bool could_be_in_startup_ = true; - - SMCKey system_total_power_key_; - SMCKey cpu_package_cpu_power_key_; - SMCKey cpu_package_gpu_power_key_; - SMCKey gpu_0_power_key_; - SMCKey gpu_1_power_key_; - - PowerDrainRecorder power_drain_calculator_; - - DISALLOW_COPY_AND_ASSIGN(Impl); -}; - -PowerMetricsProvider::PowerMetricsProvider() = default; -PowerMetricsProvider::~PowerMetricsProvider() = default; - -void PowerMetricsProvider::OnRecordingEnabled() { - const base::mac::ScopedIOObject<io_service_t> smc_service( - IOServiceGetMatchingService(kIOMasterPortDefault, - IOServiceMatching("AppleSMC"))); - io_object_t connect; - bool service_opened = IOServiceOpen(smc_service, mach_task_self(), 1, - &connect) == kIOReturnSuccess; - UMA_HISTOGRAM_BOOLEAN("Power.Mac.AppleSMCOpened", service_opened); - if (!service_opened) - return; - impl_ = Impl::Create(base::mac::ScopedIOObject<io_object_t>(connect)); -} - -void PowerMetricsProvider::OnRecordingDisabled() { - impl_.reset(); -}
diff --git a/chrome/browser/metrics/power_metrics_provider_mac_unittest.cc b/chrome/browser/metrics/power_metrics_provider_mac_unittest.cc deleted file mode 100644 index 0f7c6dc..0000000 --- a/chrome/browser/metrics/power_metrics_provider_mac_unittest.cc +++ /dev/null
@@ -1,197 +0,0 @@ -// Copyright 2020 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/metrics/power_metrics_provider_mac.h" - -#include <queue> - -#include "base/callback.h" -#include "base/metrics/histogram.h" -#include "base/test/bind.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/time/time.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { -constexpr const char* kHistogramName = "Power.Mac.BatteryDischarge"; -constexpr base::TimeDelta kMetricsCollectionInterval = - base::TimeDelta::FromSeconds(60); -constexpr double kTolerableTimeElapsedRatio = 0.10; -constexpr double kTolerablePositiveDrift = 1 + kTolerableTimeElapsedRatio; -constexpr double kTolerableNegativeDrift = 1 - kTolerableTimeElapsedRatio; -} // namespace - -class PowerMetricsProviderTest : public testing::Test { - public: - PowerMetricsProviderTest() - : power_drain_recorder_(kMetricsCollectionInterval) {} - void SetUp() override { - // Setup |power_drain_recorder_| to use use the BatteryState values - // provided by the tests instead of querying the system to build them. - power_drain_recorder_.SetGetBatteryStateCallBackForTesting( - base::BindLambdaForTesting([this]() { - DCHECK(!battery_states_.empty()); - PowerDrainRecorder::BatteryState state = battery_states_.front(); - battery_states_.pop(); - return state; - })); - } - - void TearDown() override { - // All values should have been used in the test. - ASSERT_TRUE(battery_states_.empty()); - } - - void ConsumeBatteryStates() { - const size_t number_of_test_states = battery_states_.size(); - for (size_t i = 0; i < number_of_test_states; ++i) { - power_drain_recorder_.RecordBatteryDischarge(); - } - } - - protected: - PowerDrainRecorder power_drain_recorder_; - base::HistogramTester histogram_tester_; - std::queue<PowerDrainRecorder::BatteryState> battery_states_; - base::TimeTicks now_; -}; - -TEST_F(PowerMetricsProviderTest, BatteryDischargeOnPower) { - // Two consecutive readings on power should not record a battery discharge. - battery_states_.push(PowerDrainRecorder::BatteryState{1000, false, now_}); - battery_states_.push(PowerDrainRecorder::BatteryState{ - 1000, false, now_ + base::TimeDelta::FromMinutes(1)}); - - ConsumeBatteryStates(); - histogram_tester_.ExpectTotalCount(kHistogramName, 0); -} - -TEST_F(PowerMetricsProviderTest, BatteryDischargeOnBattery) { - constexpr int kFirstReading = 1000; - constexpr int kSecondReading = 980; - - // Two consecutive readings on battery should record a battery discharge. - battery_states_.push( - PowerDrainRecorder::BatteryState{kFirstReading, true, now_}); - battery_states_.push(PowerDrainRecorder::BatteryState{ - kSecondReading, true, now_ + base::TimeDelta::FromMinutes(1)}); - - ConsumeBatteryStates(); - histogram_tester_.ExpectUniqueSample(kHistogramName, - kFirstReading - kSecondReading, 1); -} - -TEST_F(PowerMetricsProviderTest, BatteryDischargeCapacityGrew) { - // Capacity that grew between measurements means no discharge. No value should - // be recorded. - constexpr int kFirstReading = 980; - constexpr int kSecondReading = 1000; - - battery_states_.push( - PowerDrainRecorder::BatteryState{kFirstReading, true, now_}); - battery_states_.push(PowerDrainRecorder::BatteryState{ - kSecondReading, true, now_ + base::TimeDelta::FromMinutes(1)}); - - ConsumeBatteryStates(); - histogram_tester_.ExpectTotalCount(kHistogramName, 0); -} - -TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsTooEarly) { - constexpr int kFirstReading = 1000; - constexpr int kSecondReading = 980; - - const base::TimeTicks first_capture_time = - now_ + base::TimeDelta::FromSeconds(60); - const base::TimeTicks second_capture_time = - first_capture_time + - (kMetricsCollectionInterval * kTolerableNegativeDrift) - - base::TimeDelta::FromSeconds(1); - - // If it took too long to record a value no recoding takes place. - battery_states_.push(PowerDrainRecorder::BatteryState{kFirstReading, true, - first_capture_time}); - battery_states_.push(PowerDrainRecorder::BatteryState{kSecondReading, true, - second_capture_time}); - - ConsumeBatteryStates(); - histogram_tester_.ExpectTotalCount(kHistogramName, 0); -} - -TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsEarly) { - constexpr int kFirstReading = 1000; - constexpr int kSecondReading = 980; - - const base::TimeTicks first_capture_time = - now_ + base::TimeDelta::FromSeconds(60); - const base::TimeTicks second_capture_time = - first_capture_time + - (kMetricsCollectionInterval * kTolerableNegativeDrift) + - base::TimeDelta::FromSeconds(1); - - // The second recording came in just in time to not be counted as too early. - battery_states_.push(PowerDrainRecorder::BatteryState{kFirstReading, true, - first_capture_time}); - battery_states_.push(PowerDrainRecorder::BatteryState{kSecondReading, true, - second_capture_time}); - - ConsumeBatteryStates(); - - // The discharge rate is normalized to be representative over - // |kMetricsCollectionInterval|. - int discharge = - base::ClampFloor((kFirstReading - kSecondReading) * - (kMetricsCollectionInterval / - (second_capture_time - first_capture_time))); - histogram_tester_.ExpectUniqueSample(kHistogramName, discharge, 1); -} - -TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsTooLate) { - constexpr int kFirstReading = 1000; - constexpr int kSecondReading = 980; - - const base::TimeTicks first_capture_time = now_; - - // Go just slightly over the acceptable drift. - const base::TimeTicks second_capture_time = - first_capture_time + - (kMetricsCollectionInterval * kTolerablePositiveDrift) + - base::TimeDelta::FromSeconds(1); - - // If it took too long to record a value no recoding takes place. - battery_states_.push(PowerDrainRecorder::BatteryState{kFirstReading, true, - first_capture_time}); - battery_states_.push(PowerDrainRecorder::BatteryState{kSecondReading, true, - second_capture_time}); - - ConsumeBatteryStates(); - histogram_tester_.ExpectTotalCount(kHistogramName, 0); -} - -TEST_F(PowerMetricsProviderTest, BatteryDischargeCaptureIsLate) { - constexpr int kFirstReading = 1000; - constexpr int kSecondReading = 980; - - const base::TimeTicks first_capture_time = now_; - const base::TimeTicks second_capture_time = - first_capture_time + - (kMetricsCollectionInterval * kTolerablePositiveDrift) - - base::TimeDelta::FromSeconds(1); - - // If it took longer to record the metric the value recorded is scaled to - // normalize to one minute. - battery_states_.push(PowerDrainRecorder::BatteryState{kFirstReading, true, - first_capture_time}); - battery_states_.push(PowerDrainRecorder::BatteryState{kSecondReading, true, - second_capture_time}); - - ConsumeBatteryStates(); - - // The discharge rate is normalized to be representative over - // |kMetricsCollectionInterval|. - int discharge = - base::ClampFloor((kFirstReading - kSecondReading) * - (kMetricsCollectionInterval / - (second_capture_time - first_capture_time))); - histogram_tester_.ExpectUniqueSample(kHistogramName, discharge, 1); -}
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index df78d52..1c7fb14 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -20,7 +20,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/notifications/notification_common.h" #include "chrome/browser/notifications/notification_display_service_impl.h" @@ -43,6 +42,7 @@ #include "components/permissions/permission_manager.h" #include "components/permissions/permission_request_manager.h" #include "components/permissions/permission_result.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h"
diff --git a/chrome/browser/optimization_guide/android/BUILD.gn b/chrome/browser/optimization_guide/android/BUILD.gn index 5942beb1..661c244 100644 --- a/chrome/browser/optimization_guide/android/BUILD.gn +++ b/chrome/browser/optimization_guide/android/BUILD.gn
@@ -11,12 +11,14 @@ android_library("java") { sources = [ "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridge.java", + "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactory.java", "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationMetadata.java", ] deps = [ "//base:base_java", "//base:jni_java", + "//chrome/browser/profiles/android:java", "//components/optimization_guide/proto:optimization_guide_proto_java", "//content/public/android:content_java", "//third_party/android_deps:androidx_annotation_annotation_java", @@ -54,12 +56,17 @@ android_library("javatests") { testonly = true - sources = [ "javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java" ] + sources = [ + "javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactoryUnitTest.java", + "javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java", + ] deps = [ ":java", "//base:base_java_test_support", "//chrome/android:chrome_test_util_java", + "//chrome/browser/profiles/android:java", + "//chrome/test/android:chrome_java_test_support", "//components/optimization_guide/proto:optimization_guide_proto_java", "//content/public/android:content_java", "//third_party/android_deps:androidx_test_core_java",
diff --git a/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridge.java b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridge.java index c98da8cc..2b5a096 100644 --- a/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridge.java +++ b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridge.java
@@ -41,6 +41,7 @@ * Initializes the C++ side of this class, using the Optimization Guide Decider for the last * used Profile. */ + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) public OptimizationGuideBridge() { ThreadUtils.assertOnUiThread(); @@ -91,16 +92,27 @@ */ public void canApplyOptimization(NavigationHandle navigationHandle, OptimizationType optimizationType, OptimizationGuideCallback callback) { - ThreadUtils.assertOnUiThread(); assert navigationHandle.isInMainFrame(); + canApplyOptimization(navigationHandle.getUrl(), optimizationType, callback); + } + + /** + * @param url main frame navigation URL an optimization decision is being made for. + * @param optimizationType {@link OptimizationType} decision is being made for + * @param callback {@link OptimizationGuideCallback} optimization decision is passed in + */ + public void canApplyOptimization( + GURL url, OptimizationType optimizationType, OptimizationGuideCallback callback) { + ThreadUtils.assertOnUiThread(); + if (mNativeOptimizationGuideBridge == 0) { - callback.onOptimizationGuideDecision(OptimizationGuideDecision.FALSE, null); + callback.onOptimizationGuideDecision(OptimizationGuideDecision.UNKNOWN, null); return; } - OptimizationGuideBridgeJni.get().canApplyOptimization(mNativeOptimizationGuideBridge, - navigationHandle.getUrl(), optimizationType.getNumber(), callback); + OptimizationGuideBridgeJni.get().canApplyOptimization( + mNativeOptimizationGuideBridge, url, optimizationType.getNumber(), callback); } @CalledByNative @@ -123,8 +135,9 @@ return optimizationMetadata; } + @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @NativeMethods - interface Natives { + public interface Natives { long init(); void destroy(long nativeOptimizationGuideBridge); void registerOptimizationTypes(long nativeOptimizationGuideBridge, int[] optimizationTypes);
diff --git a/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactory.java b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactory.java new file mode 100644 index 0000000..f7bec5e8 --- /dev/null +++ b/chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactory.java
@@ -0,0 +1,64 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.optimization_guide; + +import androidx.annotation.VisibleForTesting; + +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.profiles.ProfileManager; +import org.chromium.components.optimization_guide.proto.HintsProto; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * OptimizationGuideBridge cached by profile. + */ +public class OptimizationGuideBridgeFactory { + @VisibleForTesting + protected final Map<Profile, OptimizationGuideBridge> mProfileToOptimizationGuideBridgeMap = + new HashMap<>(); + private final List<HintsProto.OptimizationType> mOptimizationTypes; + private ProfileManager.Observer mProfileManagerObserver; + + /** + * @param optimizationTypes list of {@link HintsProto.OptimizationType} the {@link + * OptimizationGuideBridge} is initialized with. + */ + public OptimizationGuideBridgeFactory(List<HintsProto.OptimizationType> optimizationTypes) { + mOptimizationTypes = optimizationTypes; + if (mProfileManagerObserver == null) { + mProfileManagerObserver = new ProfileManager.Observer() { + @Override + public void onProfileAdded(Profile profile) {} + + @Override + public void onProfileDestroyed(Profile destroyedProfile) { + if (mProfileToOptimizationGuideBridgeMap.containsKey(destroyedProfile)) { + mProfileToOptimizationGuideBridgeMap.get(destroyedProfile).destroy(); + mProfileToOptimizationGuideBridgeMap.remove(destroyedProfile); + } + } + }; + ProfileManager.addObserver(mProfileManagerObserver); + } + } + + /** + * @return {@link OptimizationGuideBridge} for the current last used regular profile + */ + public OptimizationGuideBridge create() { + Profile profile = Profile.getLastUsedRegularProfile(); + OptimizationGuideBridge optimizationGuideBridge = + mProfileToOptimizationGuideBridgeMap.get(profile); + if (optimizationGuideBridge == null) { + optimizationGuideBridge = new OptimizationGuideBridge(); + optimizationGuideBridge.registerOptimizationTypes(mOptimizationTypes); + mProfileToOptimizationGuideBridgeMap.put(profile, optimizationGuideBridge); + } + return optimizationGuideBridge; + } +}
diff --git a/chrome/browser/optimization_guide/android/javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactoryUnitTest.java b/chrome/browser/optimization_guide/android/javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactoryUnitTest.java new file mode 100644 index 0000000..41806f3 --- /dev/null +++ b/chrome/browser/optimization_guide/android/javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeFactoryUnitTest.java
@@ -0,0 +1,109 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.optimization_guide; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; + +import androidx.test.filters.SmallTest; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.UiThreadTest; +import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.profiles.ProfileManager; +import org.chromium.chrome.test.ChromeBrowserTestRule; +import org.chromium.components.optimization_guide.proto.HintsProto; + +import java.util.Arrays; + +/** + * Unit tests for OptimizationGuideBridgeFactory + */ +@RunWith(BaseJUnit4ClassRunner.class) +@Batch(Batch.UNIT_TESTS) +public class OptimizationGuideBridgeFactoryUnitTest { + @Rule + public JniMocker mocker = new JniMocker(); + + @Rule + public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); + + @Mock + OptimizationGuideBridge.Natives mOptimizationGuideBridgeJniMock; + + @Mock + private Profile mProfile1; + + @Mock + private Profile mProfile2; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mocker.mock(OptimizationGuideBridgeJni.TEST_HOOKS, mOptimizationGuideBridgeJniMock); + } + + @Test + @SmallTest + @UiThreadTest + @Feature({"OptimizationHints"}) + public void testFactoryMethod() { + OptimizationGuideBridgeFactory bridgeFactory = new OptimizationGuideBridgeFactory( + Arrays.asList(HintsProto.OptimizationType.SHOPPING_PAGE_PREDICTOR)); + OptimizationGuideBridge bridgeRegularProfile = bridgeFactory.create(); + Assert.assertEquals(bridgeRegularProfile, bridgeFactory.create()); + + Profile.setLastUsedProfileForTesting(mProfile1); + OptimizationGuideBridge bridgeRegularMockProfile1 = bridgeFactory.create(); + Assert.assertNotEquals(bridgeRegularProfile, bridgeRegularMockProfile1); + Assert.assertEquals(bridgeRegularMockProfile1, bridgeFactory.create()); + + Profile.setLastUsedProfileForTesting(mProfile2); + OptimizationGuideBridge bridgeRegularMockProfile2 = bridgeFactory.create(); + Assert.assertNotEquals(bridgeRegularProfile, bridgeRegularMockProfile2); + Assert.assertEquals(bridgeRegularMockProfile2, bridgeFactory.create()); + + // Back to regular profile + Profile.setLastUsedProfileForTesting(null); + Assert.assertEquals(bridgeRegularProfile, bridgeFactory.create()); + + // Mock profile 1 again + Profile.setLastUsedProfileForTesting(mProfile1); + Assert.assertEquals(bridgeRegularMockProfile1, bridgeFactory.create()); + + // Mock profile 2 again + Profile.setLastUsedProfileForTesting(mProfile2); + Assert.assertEquals(bridgeRegularMockProfile2, bridgeFactory.create()); + } + + @UiThreadTest + @SmallTest + @Test + public void testBridgeDestroyedWhenProfileDestroyed() { + Profile.setLastUsedProfileForTesting(null); + Profile profile = Profile.getLastUsedRegularProfile(); + OptimizationGuideBridgeFactory bridgeFactory = new OptimizationGuideBridgeFactory( + Arrays.asList(HintsProto.OptimizationType.SHOPPING_PAGE_PREDICTOR)); + OptimizationGuideBridge bridge = bridgeFactory.create(); + Assert.assertEquals(1, bridgeFactory.mProfileToOptimizationGuideBridgeMap.size()); + OptimizationGuideBridge spyBridge = spy(bridge); + bridgeFactory.mProfileToOptimizationGuideBridgeMap.put(profile, spyBridge); + ProfileManager.onProfileDestroyed(profile); + Mockito.verify(spyBridge, times(1)).destroy(); + Assert.assertTrue(bridgeFactory.mProfileToOptimizationGuideBridgeMap.isEmpty()); + } +}
diff --git a/chrome/browser/optimization_guide/android/javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java b/chrome/browser/optimization_guide/android/javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java index 9f280c29..cb6b26d8 100644 --- a/chrome/browser/optimization_guide/android/javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java +++ b/chrome/browser/optimization_guide/android/javatests/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java
@@ -108,7 +108,7 @@ .canApplyOptimization(anyLong(), anyObject(), anyInt(), any(OptimizationGuideBridge.OptimizationGuideCallback.class)); verify(mCallbackMock) - .onOptimizationGuideDecision(eq(OptimizationGuideDecision.FALSE), isNull()); + .onOptimizationGuideDecision(eq(OptimizationGuideDecision.UNKNOWN), isNull()); } @Test
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc index e651c7f..72bba86 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
@@ -51,6 +51,7 @@ #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/browser/network_service_instance.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "services/metrics/public/cpp/ukm_source.h" @@ -272,7 +273,8 @@ url_loader_factory, optimization_guide::features:: GetOptimizationGuideServiceGetHintsURL(), - pref_service)), + pref_service, + content::GetNetworkConnectionTracker())), external_app_packages_approved_for_fetch_( optimization_guide::features:: ExternalAppPackageNamesApprovedForFetch()),
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc index bbc532c..99726a1 100644 --- a/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc +++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager_unittest.cc
@@ -43,6 +43,7 @@ #include "services/metrics/public/cpp/ukm_source.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "services/network/test/test_network_connection_tracker.h" #include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -187,10 +188,12 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GURL optimization_guide_service_url, PrefService* pref_service, + network::NetworkConnectionTracker* network_connection_tracker, const std::vector<HintsFetcherEndState>& fetch_states) : HintsFetcher(url_loader_factory, optimization_guide_service_url, - pref_service), + pref_service, + network_connection_tracker), fetch_states_(fetch_states) { DCHECK(!fetch_states_.empty()); } @@ -251,16 +254,18 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, GURL optimization_guide_service_url, PrefService* pref_service, + network::NetworkConnectionTracker* network_connection_tracker, std::vector<HintsFetcherEndState> fetch_states) : HintsFetcherFactory(url_loader_factory, optimization_guide_service_url, - pref_service), + pref_service, + network_connection_tracker), fetch_states_(fetch_states) {} std::unique_ptr<optimization_guide::HintsFetcher> BuildInstance() override { - return std::make_unique<TestHintsFetcher>(url_loader_factory_, - optimization_guide_service_url_, - pref_service_, fetch_states_); + return std::make_unique<TestHintsFetcher>( + url_loader_factory_, optimization_guide_service_url_, pref_service_, + network_connection_tracker_, fetch_states_); } private: @@ -379,7 +384,7 @@ const std::vector<HintsFetcherEndState>& fetch_states) { return std::make_unique<TestHintsFetcherFactory>( url_loader_factory_, GURL("https://hintsserver.com"), pref_service(), - fetch_states); + network::TestNetworkConnectionTracker::GetInstance(), fetch_states); } void MoveClockForwardBy(base::TimeDelta time_delta) {
diff --git a/chrome/browser/optimization_guide/optimization_guide_top_host_provider.cc b/chrome/browser/optimization_guide/optimization_guide_top_host_provider.cc index 5b64807d..a8ef766 100644 --- a/chrome/browser/optimization_guide/optimization_guide_top_host_provider.cc +++ b/chrome/browser/optimization_guide/optimization_guide_top_host_provider.cc
@@ -9,7 +9,6 @@ #include "base/metrics/histogram_macros.h" #include "base/time/default_clock.h" #include "base/values.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/optimization_guide/optimization_guide_permissions_util.h" #include "chrome/browser/profiles/profile.h" @@ -18,6 +17,7 @@ #include "components/optimization_guide/optimization_guide_prefs.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "components/site_engagement/core/mojom/site_engagement_details.mojom.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/optimization_guide/optimization_guide_top_host_provider_unittest.cc b/chrome/browser/optimization_guide/optimization_guide_top_host_provider_unittest.cc index db340ff8..cf9f128 100644 --- a/chrome/browser/optimization_guide/optimization_guide_top_host_provider_unittest.cc +++ b/chrome/browser/optimization_guide/optimization_guide_top_host_provider_unittest.cc
@@ -8,7 +8,6 @@ #include "base/test/simple_test_clock.h" #include "base/time/default_clock.h" #include "base/values.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/previews/previews_https_notification_infobar_decider.h" #include "chrome/browser/previews/previews_service.h" @@ -22,6 +21,7 @@ #include "components/optimization_guide/optimization_guide_prefs.h" #include "components/optimization_guide/optimization_guide_switches.h" #include "components/prefs/pref_service.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/test/mock_navigation_handle.h" #include "content/public/test/web_contents_tester.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/page_load_metrics/integration_tests/total_input_delay_browsertest.cc b/chrome/browser/page_load_metrics/integration_tests/total_input_delay_browsertest.cc index b93b49c26..8c1e91c 100644 --- a/chrome/browser/page_load_metrics/integration_tests/total_input_delay_browsertest.cc +++ b/chrome/browser/page_load_metrics/integration_tests/total_input_delay_browsertest.cc
@@ -61,7 +61,9 @@ PageLoad::kInteractiveTiming_TotalAdjustedInputDelayName, int64_t(0), 0); } -IN_PROC_BROWSER_TEST_F(TotalInputDelayIntegrationTest, MultipleInputEvents) { +// Flaky: crbug.com/1163677 +IN_PROC_BROWSER_TEST_F(TotalInputDelayIntegrationTest, + DISABLED_MultipleInputEvents) { LoadHTML(R"HTML( <p>Sample website</p> )HTML");
diff --git a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc index 73eec419..a22c4bf 100644 --- a/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/translate_page_load_metrics_observer_unittest.cc
@@ -89,6 +89,10 @@ mock_translate_metrics_logger_->LogTargetLanguage(target_language_code); } + void LogUIInteraction(translate::UIInteraction ui_interaction) override { + mock_translate_metrics_logger_->LogUIInteraction(ui_interaction); + } + private: translate::testing::MockTranslateMetricsLogger* mock_translate_metrics_logger_; // Weak.
diff --git a/chrome/browser/paint_preview/paint_preview_browsertest.cc b/chrome/browser/paint_preview/paint_preview_browsertest.cc index 5fcdefb..c5ab507b 100644 --- a/chrome/browser/paint_preview/paint_preview_browsertest.cc +++ b/chrome/browser/paint_preview/paint_preview_browsertest.cc
@@ -24,44 +24,17 @@ #include "components/paint_preview/common/test_utils.h" #include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/render_process_host.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/metrics/public/cpp/ukm_builders.h" -#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkStream.h" #include "url/gurl.h" namespace paint_preview { -class NoOpPaintPreviewRecorder : public mojom::PaintPreviewRecorder { - public: - NoOpPaintPreviewRecorder() = default; - ~NoOpPaintPreviewRecorder() override = default; - - NoOpPaintPreviewRecorder(const NoOpPaintPreviewRecorder&) = delete; - NoOpPaintPreviewRecorder& operator=(const NoOpPaintPreviewRecorder&) = delete; - - void CapturePaintPreview( - mojom::PaintPreviewCaptureParamsPtr params, - mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback) - override { - callback_ = std::move(callback); - } - - void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) { - binding_.Bind(mojo::PendingAssociatedReceiver<mojom::PaintPreviewRecorder>( - std::move(handle))); - } - - private: - mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback_; - mojo::AssociatedReceiver<mojom::PaintPreviewRecorder> binding_{this}; -}; - // Test harness for a integration test of paint previews. In this test: // - Each RenderFrame has an instance of PaintPreviewRecorder attached. // - Each WebContents has an instance of PaintPreviewClient attached. @@ -69,10 +42,6 @@ class PaintPreviewBrowserTest : public InProcessBrowserTest, public testing::WithParamInterface<RecordingPersistence> { - public: - PaintPreviewBrowserTest(const PaintPreviewBrowserTest&) = delete; - PaintPreviewBrowserTest& operator=(const PaintPreviewBrowserTest&) = delete; - protected: PaintPreviewBrowserTest() = default; ~PaintPreviewBrowserTest() override = default; @@ -123,15 +92,6 @@ return params; } - void OverrideInterface(NoOpPaintPreviewRecorder* service) { - blink::AssociatedInterfaceProvider* remote_interfaces = - GetWebContents()->GetMainFrame()->GetRemoteAssociatedInterfaces(); - remote_interfaces->OverrideBinderForTesting( - mojom::PaintPreviewRecorder::Name_, - base::BindRepeating(&NoOpPaintPreviewRecorder::BindRequest, - base::Unretained(service))); - } - void WaitForLoadStopWithoutSuccessCheck() { // In many cases, the load may have finished before we get here. Only wait // if the tab still has a pending navigation. @@ -174,6 +134,10 @@ base::ScopedTempDir temp_dir_; net::EmbeddedTestServer http_server_; net::EmbeddedTestServer http_server_different_origin_; + + private: + PaintPreviewBrowserTest(const PaintPreviewBrowserTest&) = delete; + PaintPreviewBrowserTest& operator=(const PaintPreviewBrowserTest&) = delete; }; IN_PROC_BROWSER_TEST_P(PaintPreviewBrowserTest, CaptureFrame) { @@ -360,72 +324,6 @@ loop.Run(); } -// https://crbug.com/1146573 reproduction. If a renderer crashes, -// WebContentsObserver::RenderFrameDeleted. Paint preview implements this in an -// observer which in turn calls DecrementCapturerCount which can cause the -// WebContents to be reloaded on Android where we have auto-reload. This reload -// occurs *during* crash handling, leaving the frame in an invalid state and -// leading to a crash when it subsequently unloaded. -// This is fixed by deferring it to a PostTask. -// This also -IN_PROC_BROWSER_TEST_P(PaintPreviewBrowserTest, DontReloadInRenderProcessExit) { - LoadPage(http_server_.GetURL("a.com", "/title1.html")); - - content::WebContents* web_contents = GetWebContents(); - - // Override remote interfaces with a no-op. - NoOpPaintPreviewRecorder noop_recorder; - OverrideInterface(&noop_recorder); - - CreateClient(); - auto* client = PaintPreviewClient::FromWebContents(web_contents); - // Do this twice to simulate conditions for crash. - web_contents->IncrementCapturerCount(gfx::Size(), true); - web_contents->IncrementCapturerCount(gfx::Size(), true); - - // A callback that causes the frame to reload and end up in an invalid state - // if it is allowed to run during crash handling. - base::RunLoop loop; - auto params = MakeParams(); - bool did_run = false; - client->CapturePaintPreview( - params, web_contents->GetMainFrame(), - // This callback is now posted so it shouldn't cause a crash. - base::BindOnce( - [](content::WebContents* web_contents, bool* did_run_ptr, - base::UnguessableToken guid, mojom::PaintPreviewStatus status, - std::unique_ptr<CaptureResult> result) { - EXPECT_EQ(status, mojom::PaintPreviewStatus::kFailed); - EXPECT_EQ(result, nullptr); - // On Android crashed frames are marked as needing reload. - web_contents->GetController().SetNeedsReload(); - web_contents->DecrementCapturerCount(true); - web_contents->DecrementCapturerCount(true); - *did_run_ptr = true; - }, - web_contents, &did_run) - .Then(loop.QuitClosure())); - - // Crash the renderer. - { - base::ScopedAllowBlockingForTesting scope; - content::RenderProcessHost* process = - GetWebContents()->GetMainFrame()->GetProcess(); - content::RenderProcessHostWatcher crash_observer( - process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); - process->Shutdown(0); - crash_observer.Wait(); - } - - // The browser would have crashed before the loop exited if the callback was - // not posted. - if (!did_run) - loop.Run(); - - // Now navigate away and ensure that the frame unloads successfully. - LoadPage(http_server_.GetURL("a.com", "/title2.html")); -} - INSTANTIATE_TEST_SUITE_P(All, PaintPreviewBrowserTest, testing::Values(RecordingPersistence::kFileSystem,
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 3118283..b0abe2a 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -473,8 +473,10 @@ // for https://crbug.com/536637. The original implementation checked that the // BrowserPlugin hosting the pdf extension was focused; in this re-write, we // make sure the guest view's WebContents has focus. +// +// Flaky: crbug.com/1126876 IN_PROC_BROWSER_TEST_P(PDFExtensionTestWithTestGuestViewManager, - PdfInMainFrameHasFocus) { + DISABLED_PdfInMainFrameHasFocus) { // Load test HTML, and verify the text area has focus. GURL main_url(embedded_test_server()->GetURL("/pdf/test.pdf")); ui_test_utils::NavigateToURL(browser(), main_url); @@ -914,6 +916,11 @@ RunTestsInJsModule("viewer_pdf_sidenav_test.js", "test.pdf"); } +IN_PROC_BROWSER_TEST_F(PDFExtensionJSUpdatesEnabledTest, + ViewerPropertiesDialogTest) { + RunTestsInJsModule("viewer_properties_dialog_test.js", "test.pdf"); +} + IN_PROC_BROWSER_TEST_F(PDFExtensionJSUpdatesEnabledTest, ViewerThumbnailBar) { // Although this test file does not require a PDF to be loaded, loading the // elements without loading a PDF is difficult.
diff --git a/chrome/browser/pdf/pdf_extension_util.cc b/chrome/browser/pdf/pdf_extension_util.cc index 713afc0..e8d79477 100644 --- a/chrome/browser/pdf/pdf_extension_util.cc +++ b/chrome/browser/pdf/pdf_extension_util.cc
@@ -65,6 +65,22 @@ {"passwordPrompt", IDS_PDF_NEED_PASSWORD}, {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT}, {"present", IDS_PDF_PRESENT}, + {"propertiesApplication", IDS_PDF_PROPERTIES_APPLICATION}, + {"propertiesAuthor", IDS_PDF_PROPERTIES_AUTHOR}, + {"propertiesCreated", IDS_PDF_PROPERTIES_CREATED}, + {"propertiesDialogClose", IDS_CLOSE}, + {"propertiesDialogTitle", IDS_PDF_PROPERTIES_DIALOG_TITLE}, + {"propertiesFastWebView", IDS_PDF_PROPERTIES_FAST_WEB_VIEW}, + {"propertiesFileName", IDS_PDF_PROPERTIES_FILE_NAME}, + {"propertiesFileSize", IDS_PDF_PROPERTIES_FILE_SIZE}, + {"propertiesKeywords", IDS_PDF_PROPERTIES_KEYWORDS}, + {"propertiesModified", IDS_PDF_PROPERTIES_MODIFIED}, + {"propertiesPageCount", IDS_PDF_PROPERTIES_PAGE_COUNT}, + {"propertiesPageSize", IDS_PDF_PROPERTIES_PAGE_SIZE}, + {"propertiesPdfProducer", IDS_PDF_PROPERTIES_PDF_PRODUCER}, + {"propertiesPdfVersion", IDS_PDF_PROPERTIES_PDF_VERSION}, + {"propertiesSubject", IDS_PDF_PROPERTIES_SUBJECT}, + {"propertiesTitle", IDS_PDF_PROPERTIES_TITLE}, {"thumbnailPageAriaLabel", IDS_PDF_THUMBNAIL_PAGE_ARIA_LABEL}, {"tooltipDocumentOutline", IDS_PDF_TOOLTIP_DOCUMENT_OUTLINE}, {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java index 06a9627e..48502cba 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -469,7 +469,7 @@ * details. */ public static final String ISOLATED_SPLITS_DEX_COMPILE_VERSION = - "Chrome.IsolatedSplits.DexCompileVersion"; + "Chrome.IsolatedSplits.VersionCode"; /** * When the user is shown a badge that the current Android OS version is unsupported, and they
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 485e4312..66378ab 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -410,17 +410,7 @@ namespace { -// Deprecated 9/2019 -const char kGoogleServicesUsername[] = "google.services.username"; -const char kGoogleServicesUserAccountId[] = "google.services.user_account_id"; -const char kDataReductionNetworkProperties[] = - "data_reduction.network_properties"; - #if BUILDFLAG(IS_CHROMEOS_ASH) -// Deprecated 10/2019 -const char kDisplayRotationAcceleratorDialogHasBeenAccepted[] = - "settings.a11y.display_rotation_accelerator_dialog_has_been_accepted"; - // Deprecated 12/2020 const char kLocalSearchServiceSyncMetricsDailySample[] = "local_search_service_sync.metrics.daily_sample"; @@ -431,10 +421,6 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) -// Deprecated 11/2019 -const char kBlacklistedCredentialsNormalized[] = - "profile.blacklisted_credentials_normalized"; - // Deprecated 1/2020 #if defined(OS_MAC) const char kKeyCreated[] = "os_crypt.key_created"; @@ -449,6 +435,10 @@ const char kInvalidatorInvalidationState[] = "invalidator.invalidation_state"; const char kInvalidatorSavedInvalidations[] = "invalidator.saved_invalidations"; +// Deprecated 3/2020 +const char kDataReductionNetworkProperties[] = + "data_reduction.network_properties"; + #if BUILDFLAG(IS_CHROMEOS_ASH) // Deprecated 4/2020 const char kAmbientModeTopicSource[] = "settings.ambient_mode.topic_source"; @@ -564,18 +554,12 @@ // Register prefs used only for migration (clearing or moving to a new key). void RegisterProfilePrefsForMigration( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref(kGoogleServicesUsername, std::string()); - registry->RegisterStringPref(kGoogleServicesUserAccountId, std::string()); registry->RegisterDictionaryPref(kDataReductionNetworkProperties); #if BUILDFLAG(IS_CHROMEOS_ASH) - registry->RegisterBooleanPref( - kDisplayRotationAcceleratorDialogHasBeenAccepted, false); registry->RegisterDictionaryPref(kSupervisedUserAllowlists); #endif // BUILDFLAG(IS_CHROMEOS_ASH) - registry->RegisterBooleanPref(kBlacklistedCredentialsNormalized, false); - registry->RegisterBooleanPref(kGCMChannelStatus, true); registry->RegisterIntegerPref(kGCMChannelPollIntervalSeconds, 0); registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0); @@ -1192,18 +1176,6 @@ // disable sync. syncer::MigrateSyncSuppressedPref(profile_prefs); - // Added 9/2019 - profile_prefs->ClearPref(kGoogleServicesUsername); - profile_prefs->ClearPref(kGoogleServicesUserAccountId); - -#if BUILDFLAG(IS_CHROMEOS_ASH) - // Added 10/2019. - profile_prefs->ClearPref(kDisplayRotationAcceleratorDialogHasBeenAccepted); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - - // Added 11/2019. - profile_prefs->ClearPref(kBlacklistedCredentialsNormalized); - // Added 1/2020. profile_prefs->ClearPref(kGCMChannelStatus); profile_prefs->ClearPref(kGCMChannelPollIntervalSeconds);
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc index fe05d39..39cfb8b 100644 --- a/chrome/browser/profiles/profiles_state.cc +++ b/chrome/browser/profiles/profiles_state.cc
@@ -83,7 +83,6 @@ registry->RegisterIntegerPref( prefs::kBrowserProfilePickerAvailabilityOnStartup, static_cast<int>(ProfilePicker::AvailabilityOnStartup::kEnabled)); - registry->RegisterBooleanPref(prefs::kBrowserProfilePickerShown, false); } void SetLastUsedProfile(const std::string& profile_dir) {
diff --git a/chrome/browser/push_messaging/budget_database.cc b/chrome/browser/push_messaging/budget_database.cc index 1a239896..400d8f7 100644 --- a/chrome/browser/push_messaging/budget_database.cc +++ b/chrome/browser/push_messaging/budget_database.cc
@@ -11,11 +11,11 @@ #include "base/task/thread_pool.h" #include "base/time/clock.h" #include "base/time/default_clock.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/push_messaging/budget.pb.h" #include "components/leveldb_proto/public/proto_database_provider.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "url/gurl.h"
diff --git a/chrome/browser/push_messaging/budget_database_unittest.cc b/chrome/browser/push_messaging/budget_database_unittest.cc index 8070ca7..7d714e7 100644 --- a/chrome/browser/push_messaging/budget_database_unittest.cc +++ b/chrome/browser/push_messaging/budget_database_unittest.cc
@@ -12,12 +12,12 @@ #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/push_messaging/budget.pb.h" #include "chrome/test/base/testing_profile.h" #include "components/leveldb_proto/public/proto_database.h" #include "components/leveldb_proto/public/proto_database_provider.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc index 56239da3..a6ffbd8 100644 --- a/chrome/browser/push_messaging/push_messaging_browsertest.cc +++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/gcm/gcm_profile_service_factory.h" #include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h" @@ -59,6 +58,7 @@ #include "components/keep_alive_registry/keep_alive_types.h" #include "components/network_session_configurator/common/network_switches.h" #include "components/permissions/permission_request_manager.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/browsing_data_remover.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/reading_list/android/reading_list_manager.h b/chrome/browser/reading_list/android/reading_list_manager.h index efa7e53..28b589a3 100644 --- a/chrome/browser/reading_list/android/reading_list_manager.h +++ b/chrome/browser/reading_list/android/reading_list_manager.h
@@ -47,7 +47,7 @@ // Adds a reading list article to the unread section, and return the bookmark // node representation. The bookmark node is owned by this class. If there is // a duplicate URL, a new bookmark node will be created, and the old bookmark - // node pointer will be invalidated. + // node pointer will be invalidated. May return nullptr on error. virtual const bookmarks::BookmarkNode* Add(const GURL& url, const std::string& title) = 0;
diff --git a/chrome/browser/reading_list/android/reading_list_manager_impl.cc b/chrome/browser/reading_list/android/reading_list_manager_impl.cc index 98b8bcc..b2bf08d 100644 --- a/chrome/browser/reading_list/android/reading_list_manager_impl.cc +++ b/chrome/browser/reading_list/android/reading_list_manager_impl.cc
@@ -132,13 +132,13 @@ const BookmarkNode* ReadingListManagerImpl::Add(const GURL& url, const std::string& title) { DCHECK(reading_list_model_->loaded()); + if (!reading_list_model_->IsUrlSupported(url)) + return nullptr; // Add or swap the reading list entry. const auto& new_entry = reading_list_model_->AddEntry( url, title, reading_list::ADDED_VIA_CURRENT_APP); const auto* node = FindBookmarkByURL(new_entry.URL()); - DCHECK(node) - << "Bookmark node should have been create in ReadingListDidAddEntry()."; return node; }
diff --git a/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc b/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc index 1ca6a98..57670f5 100644 --- a/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc +++ b/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc
@@ -32,6 +32,7 @@ constexpr char kReadStatusKey[] = "read_status"; constexpr char kReadStatusRead[] = "true"; constexpr char kReadStatusUnread[] = "false"; +constexpr char kInvalidUTF8[] = "\xc3\x28"; class MockObserver : public ReadingListManager::Observer { public: @@ -228,6 +229,31 @@ EXPECT_EQ(url, new_node->url()); } +// If Add() with an invalid title, nullptr will be returned. +TEST_F(ReadingListManagerImplTest, AddInvalidTitle) { + GURL url(kURL); + + // Use an invalid UTF8 string. + base::string16 dummy; + EXPECT_FALSE( + base::UTF8ToUTF16(kInvalidUTF8, base::size(kInvalidUTF8), &dummy)); + const auto* new_node = Add(url, std::string(kInvalidUTF8)); + EXPECT_EQ(nullptr, new_node) + << "Should return nullptr when failed to parse the title."; +} + +// If Add() with an invalid URL, nullptr will be returned. +TEST_F(ReadingListManagerImplTest, AddInvalidURL) { + GURL invalid_url("chrome://flags"); + EXPECT_FALSE(reading_list_model()->IsUrlSupported(invalid_url)); + + // Use an invalid URL, the observer method ReadingListDidAddEntry() won't be + // invoked. + const auto* new_node = manager()->Add(invalid_url, kTitle); + EXPECT_EQ(nullptr, new_node) + << "Should return nullptr when the URL scheme is not supported."; +} + // Verifes SetReadStatus()/GetReadStatus() API. TEST_F(ReadingListManagerImplTest, ReadStatus) { GURL url(kURL);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index aa1a27f..0542492 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1740,6 +1740,9 @@ menu_model_.AddItemWithStringId( IDC_CONTENT_CLIPBOARD_HISTORY_MENU, IDS_CONTEXT_MENU_SHOW_CLIPBOARD_HISTORY_MENU); + menu_model_.SetIsNewFeatureAt( + menu_model_.GetIndexOfCommandId(IDC_CONTENT_CLIPBOARD_HISTORY_MENU), + chromeos::features::IsClipboardHistoryContextMenuNudgeEnabled()); } #endif
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 12960dc..b879b701 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -283,8 +283,8 @@ ] if (is_android) { - sources += [ "$root_gen_dir/chrome/webapks_ui_resources.pak" ] - deps += [ "//chrome/browser/resources/webapks:webapks_ui_resources" ] + sources += [ "$root_gen_dir/chrome/webapks_resources.pak" ] + deps += [ "//chrome/browser/resources/webapks:webapks_resources" ] } }
diff --git a/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn b/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn index d2dde425..1903bc3 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn +++ b/chrome/browser/resources/chromeos/emoji_picker/BUILD.gn
@@ -10,6 +10,7 @@ component_js_files = [ "emoji_picker.js", "emoji_group.js", + "icons.js", ] polymer_deps = @@ -56,6 +57,7 @@ js_library("emoji_picker") { deps = [ ":types", + ":icons", ":emoji_group", "//ui/webui/resources/js:load_time_data.m", "//third_party/polymer/v3_0/components-chromium/iron-icon", @@ -66,6 +68,11 @@ deps = [ ":types" ] + polymer_deps } +js_library("icons") { + deps = [ "//third_party/polymer/v3_0/components-chromium/iron-iconset-svg" ] + + polymer_deps +} + js_library("types") { } @@ -74,6 +81,7 @@ deps = [ ":emoji_group", ":emoji_picker", + ":icons", ":types", ] }
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html index d0f9681..20f790d8 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html
@@ -12,21 +12,22 @@ <div class="emoji-picker"> - <input - id="search" class="w-100" + <input + id="search" class="w-100" type="text" value="{{search::input}}" ></input> <div class="emoji-tabs"> - <iron-icon icon="device:access-time"></iron-icon> - <iron-icon icon="image:tag-faces"></iron-icon> - <iron-icon icon="device:access-time"></iron-icon> - <iron-icon icon="device:access-time"></iron-icon> - <iron-icon icon="device:access-time"></iron-icon> - <iron-icon icon="device:access-time"></iron-icon> - <iron-icon icon="device:access-time"></iron-icon> - <iron-icon icon="device:access-time"></iron-icon> - <iron-icon icon="device:access-time"></iron-icon> + <iron-icon icon="emoji_picker:schedule"></iron-icon> + <iron-icon icon="emoji_picker:insert_emoticon"></iron-icon> + <iron-icon icon="emoji_picker:emoji_people"></iron-icon> + <iron-icon icon="emoji_picker:emoji_nature"></iron-icon> + <iron-icon icon="emoji_picker:emoji_food_beverage"></iron-icon> + <iron-icon icon="emoji_picker:emoji_transportation"></iron-icon> + <iron-icon icon="emoji_picker:emoji_events"></iron-icon> + <iron-icon icon="emoji_picker:emoji_objects"></iron-icon> + <iron-icon icon="emoji_picker:emoji_symbols"></iron-icon> + <iron-icon icon="emoji_picker:flag"></iron-icon> </div> <div class="emoji-groups w-100">
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js index 8ab6535..0527ede 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js
@@ -4,6 +4,7 @@ import './strings.m.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; +import './icons.js'; import './emoji_group.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
diff --git a/chrome/browser/resources/chromeos/emoji_picker/icons.html b/chrome/browser/resources/chromeos/emoji_picker/icons.html new file mode 100644 index 0000000..8b5a7325 --- /dev/null +++ b/chrome/browser/resources/chromeos/emoji_picker/icons.html
@@ -0,0 +1,18 @@ +<iron-iconset-svg name="emoji_picker" size="24"> + <defs> + <!-- + These icons are copied from Material Design's icons and kept in sorted order. + See http://goo.gl/Y1OdAq for instructions on adding additional icons. + --> + <svg id="emoji_events" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M19 5h-2V3H7v2H5c-1.1 0-2 .9-2 2v1c0 2.55 1.92 4.63 4.39 4.94A5.01 5.01 0 0011 15.9V19H7v2h10v-2h-4v-3.1a5.01 5.01 0 003.61-2.96C19.08 12.63 21 10.55 21 8V7c0-1.1-.9-2-2-2zM5 8V7h2v3.82C5.84 10.4 5 9.3 5 8zm14 0c0 1.3-.84 2.4-2 2.82V7h2v1z"/></svg> + <svg id="emoji_food_beverage" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M20 3H9v2.4l1.81 1.45c.12.09.19.24.19.39v4.26c0 .28-.22.5-.5.5h-4c-.28 0-.5-.22-.5-.5V7.24c0-.15.07-.3.19-.39L8 5.4V3H4v10c0 2.21 1.79 4 4 4h6c2.21 0 4-1.79 4-4v-3h2a2 2 0 002-2V5c0-1.11-.89-2-2-2zm0 5h-2V5h2v3zM4 19h16v2H4z"/></svg> + <svg id="emoji_nature" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M21.94 4.88A1.32 1.32 0 0020.68 4H19.6l-.31-.97C19.15 2.43 18.61 2 18 2s-1.15.43-1.29 1.04L16.4 4h-1.07c-.57 0-1.08.35-1.26.88-.19.56.04 1.17.56 1.48l.87.52-.4 1.24c-.23.58-.04 1.25.45 1.62.23.17.51.26.78.26.31 0 .61-.11.86-.32l.81-.7.81.7c.25.21.55.32.86.32.27 0 .55-.09.78-.26.5-.37.68-1.04.45-1.62l-.39-1.24.87-.52c.51-.31.74-.92.56-1.48zM18 7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zM13.49 10.51c-.43-.43-.94-.73-1.49-.93V8h-1v1.38c-.11-.01-.23-.03-.34-.03-1.02 0-2.05.39-2.83 1.17-.16.16-.3.34-.43.53L6 10.52a3.01 3.01 0 00-3.83 1.82c-.27.75-.23 1.57.12 2.29.23.48.58.87 1 1.16-.38 1.35-.06 2.85 1 3.91a3.981 3.981 0 003.91 1c.29.42.68.77 1.16 1 .42.2.85.3 1.29.3.34 0 .68-.06 1.01-.17a3.007 3.007 0 001.82-3.85l-.52-1.37c.18-.13.36-.27.53-.43.87-.87 1.24-2.04 1.14-3.17H16v-1h-1.59c-.19-.55-.49-1.06-.92-1.5zm-8.82 3.78c-.25-.09-.45-.27-.57-.51s-.13-.51-.04-.76c.19-.52.76-.79 1.26-.61l3.16 1.19c-1.15.6-2.63 1.11-3.81.69zm6.32 5.65c-.25.09-.52.08-.76-.04a.989.989 0 01-.51-.57c-.42-1.18.09-2.65.7-3.8l1.18 3.13c.18.52-.09 1.1-.61 1.28zm1.21-5.34l-.61-1.61c0-.01-.01-.02-.02-.03l-.06-.12a.673.673 0 00-.07-.11l-.09-.09-.09-.09c-.03-.03-.07-.05-.11-.07-.04-.02-.07-.05-.12-.06-.01 0-.02-.01-.03-.02l-1.6-.6a1.966 1.966 0 012.67.13c.73.73.77 1.88.13 2.67z"/></svg> + <svg id="emoji_objects" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 3c-.46 0-.93.04-1.4.14-2.76.53-4.96 2.76-5.48 5.52-.48 2.61.48 5.01 2.22 6.56.43.38.66.91.66 1.47V19c0 1.1.9 2 2 2h.28a1.98 1.98 0 003.44 0H14c1.1 0 2-.9 2-2v-2.31c0-.55.22-1.09.64-1.46A6.956 6.956 0 0019 10c0-3.87-3.13-7-7-7zm2 16h-4v-1h4v1zm0-2h-4v-1h4v1zm-1.5-5.59V14h-1v-2.59L9.67 9.59l.71-.71L12 10.5l1.62-1.62.71.71-1.83 1.82z"/></svg> + <svg id="emoji_people" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><circle cx="12" cy="4" r="2"/><path d="M15.89 8.11C15.5 7.72 14.83 7 13.53 7h-2.54C8.24 6.99 6 4.75 6 2H4c0 3.16 2.11 5.84 5 6.71V22h2v-6h2v6h2V10.05L18.95 14l1.41-1.41-4.47-4.48z"/></svg> + <svg id="emoji_symbols" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 2h8v2H3zM6 11h2V7h3V5H3v2h3z"/><path transform="rotate(-45.001 17 17)" d="M11.5 16h11v2h-11z"/><circle cx="14.5" cy="14.5" r="1.5"/><circle cx="19.5" cy="19.5" r="1.5"/><path d="M15.5 11A2.5 2.5 0 0018 8.5V4h3V2h-4v4.51c-.42-.32-.93-.51-1.5-.51a2.5 2.5 0 000 5zM9.74 15.96l-1.41 1.41-.71-.71.35-.35a2.499 2.499 0 00-1.77-4.27 2.499 2.499 0 00-1.77 4.27l.35.35-1.06 1.06c-.98.98-.98 2.56 0 3.54.5.5 1.14.74 1.78.74s1.28-.24 1.77-.73l1.06-1.06 1.41 1.41 1.41-1.41-1.41-1.41 1.41-1.41-1.41-1.43zM5.85 14.2c.12-.12.26-.15.35-.15s.23.03.35.15c.19.2.19.51 0 .71l-.35.35-.35-.36a.501.501 0 010-.7zm0 5.65c-.12.12-.26.15-.35.15s-.23-.03-.35-.15a.513.513 0 010-.71l1.06-1.06.71.71-1.07 1.06z"/></svg> + <svg id="emoji_transportation" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M20.57 10.66c-.14-.4-.52-.66-.97-.66h-7.19c-.46 0-.83.26-.98.66L10 14.77l.01 5.51c0 .38.31.72.69.72h.62c.38 0 .68-.38.68-.76V19h8v1.24c0 .38.31.76.69.76h.61c.38 0 .69-.34.69-.72l.01-1.37v-4.14l-1.43-4.11zm-8.16.34h7.19l1.03 3h-9.25l1.03-3zM12 17c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm8 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/><path d="M14 9h1V3H7v5H2v13h1V9h5V4h6z"/><path d="M5 11h2v2H5zM10 5h2v2h-2zM5 15h2v2H5zM5 19h2v2H5z"/></svg> + <svg id="flag" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></svg> + <svg id="insert_emoticon" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></svg> + <svg id="schedule" xmlns="http://www.w3.org/2000/svg" height="24" width="24"><path d="M0 0h24v24H0z" fill="none"/><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg> + </defs> +</iron-iconset-svg>
diff --git a/chrome/browser/resources/chromeos/emoji_picker/icons.js b/chrome/browser/resources/chromeos/emoji_picker/icons.js new file mode 100644 index 0000000..701f58e --- /dev/null +++ b/chrome/browser/resources/chromeos/emoji_picker/icons.js
@@ -0,0 +1,9 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/polymer/v3_0/iron-iconset-svg/iron-iconset-svg.js'; +import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +const template = html`{__html_template__}`; +document.head.appendChild(template.content); \ No newline at end of file
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index 547f79d6..28a0803 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -169,6 +169,7 @@ "elements:viewer-pdf-sidenav", "elements:viewer-pdf-toolbar", "elements:viewer-pdf-toolbar-new", + "elements:viewer-properties-dialog", "elements:viewer-zoom-toolbar", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js:event_tracker.m",
diff --git a/chrome/browser/resources/pdf/elements/BUILD.gn b/chrome/browser/resources/pdf/elements/BUILD.gn index 931b1300..698d8aa 100644 --- a/chrome/browser/resources/pdf/elements/BUILD.gn +++ b/chrome/browser/resources/pdf/elements/BUILD.gn
@@ -19,6 +19,7 @@ ":viewer-pdf-sidenav", ":viewer-pdf-toolbar", ":viewer-pdf-toolbar-new", + ":viewer-properties-dialog", ":viewer-thumbnail", ":viewer-thumbnail-bar", ":viewer-toolbar-dropdown", @@ -154,6 +155,13 @@ js_library("viewer-pen-options") { } +js_library("viewer-properties-dialog") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", + ] +} + js_library("viewer-thumbnail") { deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -206,6 +214,7 @@ "viewer-pdf-sidenav.js", "viewer-pdf-toolbar.js", "viewer-pdf-toolbar-new.js", + "viewer-properties-dialog.js", "viewer-thumbnail.js", "viewer-thumbnail-bar.js", "viewer-toolbar-dropdown.js",
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html index 0a886431..59dfed5 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.html
@@ -294,14 +294,21 @@ $i18n{annotationsShowToggle} </button> + <hr> + <template is="dom-if" if="[[presentationModeEnabled]]"> - <hr> <button id="present-button" class="dropdown-item" on-click="onPresentClick_"> <span class="check-container" aria-hidden="true"></span> $i18n{present} </button> </template> + + <button id="properties-button" class="dropdown-item" + on-click="onPropertiesClick_"> + <span class="check-container" aria-hidden="true"></span> + $i18n{propertiesDialogTitle} + </button> </cr-action-menu> <if expr="chromeos">
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js index 0ef7502..6235432 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js
@@ -225,6 +225,12 @@ this.dispatchEvent(new CustomEvent('present-click')); } + /** @private */ + onPropertiesClick_() { + this.getMenu_().close(); + this.dispatchEvent(new CustomEvent('properties-click')); + } + /** * @param {boolean} checked * @return {string}
diff --git a/chrome/browser/resources/pdf/elements/viewer-properties-dialog.html b/chrome/browser/resources/pdf/elements/viewer-properties-dialog.html new file mode 100644 index 0000000..bfc31ed --- /dev/null +++ b/chrome/browser/resources/pdf/elements/viewer-properties-dialog.html
@@ -0,0 +1,102 @@ +<style include="cr-shared-style"> + :host { + --break-padding: 8px; + } + + cr-dialog::part(dialog) { + width: fit-content; + } + + table { + border-spacing: 0; + } + + .break > td { + --break-color: var(--google-grey-refresh-300); + border-bottom: 1px solid var(--break-color); + padding-bottom: var(--break-padding); + } + + + .break + tr > td { + padding-top: var(--break-padding); + } + + .name { + color: var(--cr-primary-text-color); + padding-inline-end: 12px; + } + + .value { + color: var(--cr-secondary-text-color); + min-width: 200px; + } +</style> +<cr-dialog show-on-attach> + <div slot="title">$i18n{propertiesDialogTitle}</div> + <div slot="body"> + <table> + <tr> + <td class="name">$i18n{propertiesFileName}</td> + <td class="value" id="file-name">-</td> + </tr> + <tr class="break"> + <td class="name">$i18n{propertiesFileSize}</td> + <td class="value" id="file-size">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesTitle}</td> + <td class="value" id="title">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesAuthor}</td> + <td class="value" id="author">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesSubject}</td> + <td class="value" id="subject">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesKeywords}</td> + <td class="value" id="keywords">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesCreated}</td> + <td class="value" id="created">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesModified}</td> + <td class="value" id="modified">-</td> + </tr> + <tr class="break"> + <td class="name">$i18n{propertiesApplication}</td> + <td class="value" id="application">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesPdfProducer}</td> + <td class="value" id="pdf-producer">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesPdfVersion}</td> + <td class="value" id="pdf-version">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesPageCount}</td> + <td class="value" id="page-count">-</td> + </tr> + <tr class="break"> + <td class="name">$i18n{propertiesPageSize}</td> + <td class="value" id="page-size">-</td> + </tr> + <tr> + <td class="name">$i18n{propertiesFastWebView}</td> + <td class="value" id="fast-web-view">-</td> + </tr> + </table> + </div> + <div slot="button-container"> + <cr-button id="close" class="action-button" on-click="onClickClose_"> + $i18n{propertiesDialogClose} + </cr-button> + </div> +</cr-dialog>
diff --git a/chrome/browser/resources/pdf/elements/viewer-properties-dialog.js b/chrome/browser/resources/pdf/elements/viewer-properties-dialog.js new file mode 100644 index 0000000..ec71763 --- /dev/null +++ b/chrome/browser/resources/pdf/elements/viewer-properties-dialog.js
@@ -0,0 +1,36 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; +import 'chrome://resources/cr_elements/shared_style_css.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; + +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +export class ViewerPropertiesDialogElement extends PolymerElement { + static get is() { + return 'viewer-properties-dialog'; + } + + static get template() { + return html`{__html_template__}`; + } + + /** + * @return {!CrDialogElement} + * @private + */ + getDialog_() { + return /** @type {!CrDialogElement} */ ( + this.shadowRoot.querySelector('cr-dialog')); + } + + /** @private */ + onClickClose_() { + this.getDialog_().close(); + } +} + +customElements.define( + ViewerPropertiesDialogElement.is, ViewerPropertiesDialogElement);
diff --git a/chrome/browser/resources/pdf/pdf_resources.grdp b/chrome/browser/resources/pdf/pdf_resources.grdp index 4928aa7..1016c65f 100644 --- a/chrome/browser/resources/pdf/pdf_resources.grdp +++ b/chrome/browser/resources/pdf/pdf_resources.grdp
@@ -46,6 +46,7 @@ <include name="IDR_PDF_VIEWER_PDF_SIDENAV_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-sidenav.js" use_base_dir="false" type="BINDATA"/> <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js" use_base_dir="false" type="BINDATA" preprocess="true"/> <include name="IDR_PDF_VIEWER_PDF_TOOLBAR_NEW_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar-new.js" use_base_dir="false" type="BINDATA" preprocess="true"/> + <include name="IDR_PDF_VIEWER_PROPERTIES_DIALOG_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-properties-dialog.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_THUMBNAIL_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-thumbnail.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_THUMBNAIL_BAR_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-thumbnail-bar.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_PDF_VIEWER_TOOLBAR_DROPDOWN_JS" file="${root_gen_dir}/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/browser/resources/pdf/pdf_viewer.html b/chrome/browser/resources/pdf/pdf_viewer.html index 1287781..e54a03f 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.html +++ b/chrome/browser/resources/pdf/pdf_viewer.html
@@ -183,6 +183,7 @@ on-dropdown-opened="onDropdownOpened_" on-fit-to-changed="onFitToChanged" on-present-click="onPresentClick_" + on-properties-click="onPropertiesClick_" on-annotation-mode-dialog-confirmed="onResetView_" on-sidenav-toggle-click="onSidenavToggleClick_" on-two-up-view-changed="onTwoUpViewChanged_" @@ -223,6 +224,12 @@ on-password-submitted="onPasswordSubmitted_"> </viewer-password-screen> +<template is="dom-if" if="[[showPropertiesDialog_]]" restamp> + <viewer-properties-dialog id="properties-dialog" + on-close="onPropertiesDialogClose_"> + </viewer-properties-dialog> +</template> + <template is="dom-if" if="[[!pdfViewerUpdateEnabled_]]"> <viewer-zoom-toolbar id="zoom-toolbar" on-fit-to-changed="onFitToChanged"
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js index 5515ebf..ee362d9 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.js +++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -5,6 +5,7 @@ import './elements/viewer-error-screen.js'; import './elements/viewer-password-screen.js'; import './elements/viewer-pdf-toolbar.js'; +import './elements/viewer-properties-dialog.js'; import './elements/viewer-zoom-toolbar.js'; import './elements/shared-vars.js'; // <if expr="chromeos"> @@ -65,8 +66,6 @@ * @typedef {{ * type: string, * title: string, - * attachments: !Array<!Attachment>, - * bookmarks: !Array<!Bookmark>, * canSerializeDocument: boolean, * }} */ @@ -249,6 +248,12 @@ }, /** @private */ + showPropertiesDialog_: { + type: Boolean, + value: false, + }, + + /** @private */ sidenavCollapsed_: { type: Boolean, value: false, @@ -745,6 +750,19 @@ }); } + /** @private */ + onPropertiesClick_() { + assert(this.pdfViewerUpdateEnabled_); + assert(!this.showPropertiesDialog_); + this.showPropertiesDialog_ = true; + } + + /** @private */ + onPropertiesDialogClose_() { + assert(this.showPropertiesDialog_); + this.showPropertiesDialog_ = false; + } + /** * Changes two up view mode for the controller. Controller will trigger * layout update later, which will update the viewport accordingly. @@ -880,9 +898,19 @@ handlePluginMessage(e) { const data = e.detail; switch (data.type.toString()) { + case 'attachments': + this.setAttachments_( + /** @type {{ attachmentsData: !Array<!Attachment> }} */ (data) + .attachmentsData); + return; case 'beep': this.handleBeep_(); return; + case 'bookmarks': + this.setBookmarks_( + /** @type {{ bookmarksData: !Array<!Bookmark> }} */ (data) + .bookmarksData); + return; case 'documentDimensions': this.setDocumentDimensions( /** @type {!DocumentDimensionsMessageData} */ (data)); @@ -1009,6 +1037,24 @@ } /** + * Sets the document attachment data. + * @param {!Array<!Attachment>} attachments + * @private + */ + setAttachments_(attachments) { + this.attachments_ = attachments; + } + + /** + * Sets the document bookmarks data. + * @param {!Array<!Bookmark>} bookmarks + * @private + */ + setBookmarks_(bookmarks) { + this.bookmarks_ = bookmarks; + } + + /** * Sets document metadata from the current controller. * @param {!MetadataMessageData} metadata * @private @@ -1016,8 +1062,6 @@ setDocumentMetadata_(metadata) { this.title_ = metadata.title || getFilenameFromURL(this.originalUrl); document.title = this.title_; - this.attachments_ = metadata.attachments; - this.bookmarks_ = metadata.bookmarks; this.canSerializeDocument_ = metadata.canSerializeDocument; }
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.html b/chrome/browser/resources/settings/a11y_page/a11y_page.html index c050e22..b528ec7b 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.html
@@ -3,7 +3,7 @@ section="a11y" focus-config="[[focusConfig_]]"> <div route-path="default"> <if expr="chromeos"> - <cr-link-row class="hr" + <cr-link-row label="$i18n{manageAccessibilityFeatures}" on-click="onManageSystemAccessibilityFeaturesTap_" sub-label="$i18n{moreFeaturesLinkDescription}" external> @@ -11,7 +11,7 @@ </if> <if expr="not chromeos"> <template is="dom-if" if="[[captionSettingsOpensExternally_]]"> - <cr-link-row class="hr" id="captions" + <cr-link-row id="captions" label="$i18n{captionsPreferencesTitle}" sub-label="$i18n{captionsPreferencesSubtitle}" on-click="onCaptionsClick_" @@ -19,6 +19,7 @@ </cr-link-row> <template is="dom-if" if="[[enableLiveCaption_]]"> <settings-toggle-button + class="hr" pref="{{prefs.accessibility.captions.live_caption_enabled}}" on-change="onA11yLiveCaptionChange_" label="$i18n{captionsEnableLiveCaptionTitle}" @@ -27,7 +28,7 @@ </template> </template> <template is="dom-if" if="[[!captionSettingsOpensExternally_]]"> - <cr-link-row class="first" id="captions" + <cr-link-row id="captions" label="$i18n{captionsTitle}" on-click="onCaptionsClick_" role-description="$i18n{subpageArrowRoleDescription}">
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.html b/chrome/browser/resources/settings/appearance_page/appearance_page.html index e31e6b1..894b7cf 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.html +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.html
@@ -22,7 +22,7 @@ <settings-animated-pages id="pages" section="appearance" focus-config="[[focusConfig_]]"> <div route-path="default"> - <div class="settings-row continuation" id="themeRow" + <div class="settings-row first" id="themeRow" hidden="[[!pageVisibility.setTheme]]"> <cr-link-row class="first" hidden="[[!pageVisibility.setTheme]]" label="$i18n{themes}" sub-label="[[themeSublabel_]]" @@ -56,7 +56,12 @@ </div> </if> </div> - <settings-toggle-button class="hr" elide-label + <div + class="hr" + hidden="[[!showHr_( + pageVisibility.setTheme, pageVisibility.homeButton)]]"> + </div> + <settings-toggle-button elide-label hidden="[[!pageVisibility.homeButton]]" pref="{{prefs.browser.show_home_button}}" label="$i18n{showHomeButton}" @@ -94,7 +99,12 @@ </settings-radio-group> </div> </template> - <settings-toggle-button class="hr" + <div + class="hr" + hidden="[[!showHr_( + pageVisibility.homeButton, pageVisibility.bookmarksBar)]]"> + </div> + <settings-toggle-button hidden="[[!pageVisibility.bookmarksBar]]" pref="{{prefs.bookmark_bar.show_on_all_tabs}}" label="$i18n{showBookmarksBar}">
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.js b/chrome/browser/resources/settings/appearance_page/appearance_page.js index 084ad3a9..f5c5ef0 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.js +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.js
@@ -323,4 +323,13 @@ zoomValuesEqual_(zoom1, zoom2) { return Math.abs(zoom1 - zoom2) <= 0.001; }, + + /** + * @param {boolean} previousIsVisible + * @param {boolean} nextIsVisible + * @return {boolean} + */ + showHr_(previousIsVisible, nextIsVisible) { + return previousIsVisible && nextIsVisible; + }, });
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html index f90a7a4..6ec98d9e 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.html +++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -64,7 +64,7 @@ </template> <if expr="chromeos"> <template is="dom-if" if="[[showOSSettingsBanner_]]"> - <div id="osSettingsBanner" class="cr-row"> + <div id="osSettingsBanner" class="cr-row first"> <div class="flex cr-padded-text" on-click="onOSSettingsBannerClick_"> $i18nRaw{osSettingsBannerText}
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js index fe3c317e..1936245 100644 --- a/chrome/browser/resources/settings/chromeos/os_route.js +++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -207,7 +207,7 @@ if (loadTimeData.valueExists('showCrostini') && loadTimeData.getBoolean('showCrostini')) { r.CROSTINI = createSection( - r.BASIC, mojom.CROSTINI_SECTION_PATH, Section.kCrostini); + r.ADVANCED, mojom.CROSTINI_SECTION_PATH, Section.kCrostini); r.CROSTINI_DETAILS = createSubpage( r.CROSTINI, mojom.CROSTINI_DETAILS_SUBPAGE_PATH, Subpage.kCrostiniDetails);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html index 4753775e..441ef50 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
@@ -204,10 +204,6 @@ <iron-icon icon="os-settings:apps"></iron-icon> $i18n{appsPageTitle} </a> - <a href="/crostini" hidden="[[!showCrostini]]" class="item"> - <iron-icon icon="os-settings:developer-tags"></iron-icon> - $i18n{crostiniPageTitle} - </a> <a href="/onstartup" hidden="[[!showStartup]]" class="item"> <iron-icon icon="os-settings:startup"></iron-icon> $i18n{onStartupPageTitle} @@ -244,6 +240,10 @@ <iron-icon icon="os-settings:print"></iron-icon> $i18n{printingPageTitle} </a> + <a href="/crostini" hidden="[[!showCrostini]]" class="item"> + <iron-icon icon="os-settings:developer-tags"></iron-icon> + $i18n{crostiniPageTitle} + </a> <a href="/osAccessibility" class="item"> <iron-icon icon="os-settings:accessibility"></iron-icon> $i18n{a11yPageTitle}
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html index 96eef45..468bd68 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html
@@ -202,14 +202,6 @@ show-plugin-vm="[[showPluginVm]]"> </os-settings-apps-page> </settings-section> - <template is="dom-if" if="[[showCrostini]]" restamp> - <settings-section page-title="$i18n{crostiniPageTitle}" - section="crostini"> - <settings-crostini-page prefs="{{prefs}}" - allow-crostini="[[allowCrostini_]]"> - </settings-crostini-page> - </settings-section> - </template> <template is="dom-if" if="[[showStartup]]"> <settings-section page-title="$i18n{onStartupPageTitle}" section="onstartup"> @@ -268,6 +260,14 @@ <os-settings-printing-page prefs="{{prefs}}"> </os-settings-printing-page> </settings-section> + <template is="dom-if" if="[[showCrostini]]" restamp> + <settings-section page-title="$i18n{crostiniPageTitle}" + section="crostini"> + <settings-crostini-page prefs="{{prefs}}" + allow-crostini="[[allowCrostini_]]"> + </settings-crostini-page> + </settings-section> + </template> <settings-section page-title="$i18n{a11yPageTitle}" section="osAccessibility"> <os-settings-a11y-page prefs="{{prefs}}">
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index 8a013e01..73d18d0 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -30,7 +30,7 @@ focus-config="[[focusConfig_]]"> <div route-path="default"> <cr-link-row id="clearBrowsingData" - class="hr" start-icon="cr:delete" + start-icon="cr:delete" label="$i18n{clearBrowsingData}" sub-label="$i18n{clearBrowsingDataDescription}" on-click="onClearBrowsingDataTap_"></cr-link-row>
diff --git a/chrome/browser/resources/settings/system_page/system_page.html b/chrome/browser/resources/settings/system_page/system_page.html index aa850d3..8470efd1 100644 --- a/chrome/browser/resources/settings/system_page/system_page.html +++ b/chrome/browser/resources/settings/system_page/system_page.html
@@ -4,8 +4,9 @@ pref="{{prefs.background_mode.enabled}}" label="$i18n{backgroundAppsLabel}"> </settings-toggle-button> + <div class="hr"></div> </if> - <settings-toggle-button id="hardwareAcceleration" class="hr" + <settings-toggle-button id="hardwareAcceleration" pref="{{prefs.hardware_acceleration_mode.enabled}}" label="$i18n{hardwareAccelerationLabel}"> <template is="dom-if" if="[[shouldShowRestart_(
diff --git a/chrome/browser/resources/webapks/BUILD.gn b/chrome/browser/resources/webapks/BUILD.gn index 8798ad55..8d4ddac8 100644 --- a/chrome/browser/resources/webapks/BUILD.gn +++ b/chrome/browser/resources/webapks/BUILD.gn
@@ -5,6 +5,7 @@ import("//chrome/common/features.gni") import("//third_party/closure_compiler/compile_js.gni") import("//tools/grit/grit_rule.gni") +import("//ui/webui/resources/tools/generate_grd.gni") js_type_check("closure_compile") { uses_js_modules = true @@ -19,12 +20,27 @@ externs_list = [ "$externs_path/chrome_send.js" ] } -grit("webapks_ui_resources") { - source = "webapks_ui_resources.grd" +generate_grd("build_grd") { + grd_prefix = "webapks" + out_grd = "$target_gen_dir/resources.grd" + input_files = [ + "about_webapks.css", + "about_webapks.html", + "about_webapks.js", + ] + input_files_base_dir = rebase_path(".", "//") +} + +grit("webapks_resources") { + source = "$target_gen_dir/resources.grd" + deps = [ ":build_grd" ] + enable_input_discovery_for_gn_analyze = false defines = chrome_grit_defines outputs = [ - "grit/webapks_ui_resources.h", - "webapks_ui_resources.pak", + "grit/webapks_resources.h", + "grit/webapks_resources_map.cc", + "grit/webapks_resources_map.h", + "webapks_resources.pak", ] output_dir = "$root_gen_dir/chrome" }
diff --git a/chrome/browser/resources/webapks/webapks_ui_resources.grd b/chrome/browser/resources/webapks/webapks_ui_resources.grd deleted file mode 100644 index e1bae8d..0000000 --- a/chrome/browser/resources/webapks/webapks_ui_resources.grd +++ /dev/null
@@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> - <outputs> - <output filename="grit/webapks_ui_resources.h" type="rc_header"> - <emit emit_type='prepend'></emit> - </output> - <output filename="webapks_ui_resources.pak" type="data_package" /> - </outputs> - <release seq="1"> - <includes> - <include name="IDR_WEBAPKS_UI_CSS" file="about_webapks.css" type="BINDATA" /> - <include name="IDR_WEBAPKS_UI_HTML" file="about_webapks.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> - <include name="IDR_WEBAPKS_UI_JS" file="about_webapks.js" type="BINDATA" /> - </includes> - </release> -</grit>
diff --git a/chrome/browser/safe_browsing/OWNERS b/chrome/browser/safe_browsing/OWNERS index ad1f064f..3e4d613 100644 --- a/chrome/browser/safe_browsing/OWNERS +++ b/chrome/browser/safe_browsing/OWNERS
@@ -1,5 +1,6 @@ drubery@chromium.org nparker@chromium.org vakh@chromium.org +xinghuilu@chromium.org per-file *password_protection*=file://components/safe_browsing/content/password_protection/OWNERS
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index d47ad06..3167fddf 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc
@@ -72,6 +72,7 @@ #include "extensions/common/extension_set.h" #if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/public/cpp/ash_features.h" #include "chrome/browser/chromeos/boot_times_recorder.h" #endif @@ -442,9 +443,17 @@ // 5. Restore tabs in |browser|. This will also call Show() on |browser| // if its initial show state is not mimimized. + // However, with desks restore enabled, a window is restored to its parent + // desk, which can be non-active desk, and left invisible but unminimized. RestoreTabsToBrowser(*(*i), browser, initial_tab_count, created_contents); +#if BUILDFLAG(IS_CHROMEOS_ASH) + DCHECK(browser->window()->IsVisible() || + browser->window()->IsMinimized() || + ash::features::IsBentoEnabled()); +#else DCHECK(browser->window()->IsVisible() || browser->window()->IsMinimized()); +#endif // 6. Tabs will be grouped appropriately in RestoreTabsToBrowser. Now // restore the groups' visual data. @@ -784,9 +793,26 @@ // static void SessionRestore::RestoreSessionAfterCrash(Browser* browser) { + auto* profile = browser->profile(); + +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Bento restores a window to the right desk, so we should not + // reuse any browser window. Otherwise, the conflict of the parent desk + // arises because tabs created in this |browser| should remain in the + // current active desk, but the first restored window should be restored + // to its saved parent desk before a crash. This also avoids users' + // confusion of the current window disappearing from the current desk + // after pressing a restore button. + if (ash::features::IsBentoEnabled()) + browser = nullptr; +#endif + SessionRestore::BehaviorBitmask behavior = - HasSingleNewTabPage(browser) ? SessionRestore::CLOBBER_CURRENT_TAB : 0; - SessionRestore::RestoreSession(browser->profile(), browser, behavior, + browser && HasSingleNewTabPage(browser) + ? SessionRestore::CLOBBER_CURRENT_TAB + : 0; + + SessionRestore::RestoreSession(profile, browser, behavior, std::vector<GURL>()); }
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index 4c14f2ac..1587839 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -24,7 +24,6 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/defaults.h" -#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc index 7115bfe..0a5cbd0 100644 --- a/chrome/browser/sessions/session_restore_browsertest_chromeos.cc +++ b/chrome/browser/sessions/session_restore_browsertest_chromeos.cc
@@ -8,6 +8,7 @@ #include <vector> #include "base/command_line.h" +#include "base/strings/string_number_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" @@ -31,17 +32,31 @@ #include "content/public/test/test_utils.h" #include "ui/wm/core/wm_core_switches.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/public/cpp/ash_features.h" +#include "ash/public/cpp/autotest_desks_api.h" +#endif + +#if defined(USE_AURA) +#include "ui/aura/client/aura_constants.h" +#endif + namespace { const char* test_app_name1 = "TestApp1"; const char* test_app_name2 = "TestApp2"; } // namespace -class SessionRestoreTestChromeOS : public InProcessBrowserTest { +// SessionRestoreTestChromeOS with boolean test param for testing with +// Bento, which contains desks restore feature, enabled and disabled. +class SessionRestoreTestChromeOS : public InProcessBrowserTest, + public ::testing::WithParamInterface<bool> { public: ~SessionRestoreTestChromeOS() override {} protected: void SetUpDefaultCommandLine(base::CommandLine* command_line) override { + if (GetParam()) + scoped_feature_list_.InitAndEnableFeature(ash::features::kBento); base::CommandLine default_command_line(base::CommandLine::NO_PROGRAM); InProcessBrowserTest::SetUpDefaultCommandLine(&default_command_line); @@ -77,14 +92,19 @@ browser()->profile(), SessionStartupPref(SessionStartupPref::LAST)); } + bool IsBentoEnabled() const { return GetParam(); } + Profile* profile() { return browser()->profile(); } + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; // Thse tests are in pairs. The PRE_ test creates some browser windows and // the following test confirms that the correct windows are restored after a // restart. -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_RestoreBrowserWindows) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, PRE_RestoreBrowserWindows) { // One browser window is always created by default. EXPECT_TRUE(browser()); // Create a second normal browser window. @@ -95,7 +115,7 @@ TurnOnSessionRestore(); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, RestoreBrowserWindows) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, RestoreBrowserWindows) { size_t total_count = 0; size_t incognito_count = 0; for (auto* browser : *BrowserList::GetInstance()) { @@ -107,7 +127,76 @@ EXPECT_EQ(0u, incognito_count); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_RestoreAppsV1) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + +// Assigns three browser windows to three different desks. +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, + PRE_RestoreBrowserWindowsToDesks) { + // Create two more desks so we have three desks in total. + ash::AutotestDesksApi().CreateNewDesk(); + ash::AutotestDesksApi().CreateNewDesk(); + + // A browser window is always created to the current desk, which + // is the first desk by default. + EXPECT_TRUE(browser()); + browser()->SetWindowUserTitle("0"); + + // Create a second normal browser window in the second desk by + // setting window workspace property. + Browser* browser_desk1 = + CreateBrowserWithParams(Browser::CreateParams(profile(), true)); + browser_desk1->SetWindowUserTitle("1"); + if (IsBentoEnabled()) { + browser_desk1->window()->GetNativeWindow()->SetProperty( + aura::client::kWindowWorkspaceKey, 1); + } + + // Create a third normal browser window in the third desk + // specified with params.initial_workspace. + Browser::CreateParams browser_desk2_params = + Browser::CreateParams(profile(), true); + if (IsBentoEnabled()) + browser_desk2_params.initial_workspace = "2"; + Browser* browser_desk2 = CreateBrowserWithParams(browser_desk2_params); + browser_desk2->SetWindowUserTitle("2"); + + TurnOnSessionRestore(); +} + +// Verifies that three windows restored to their right desk after restored. +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, + RestoreBrowserWindowsToDesks) { + auto* browser_list = BrowserList::GetInstance(); + ASSERT_EQ(3u, browser_list->size()); + + // The first, second and third browser should restore to the first, second + // and third desk, consecutively. + for (int i = 0; i < 3; i++) { + auto* browser = browser_list->get(i); + int desk_index = 0; + if (IsBentoEnabled()) { + ASSERT_TRUE(base::StringToInt(browser->initial_workspace(), &desk_index)); + // Verify that browser i_th with title i, has initial_workspace equals + // to desk i_th. + ASSERT_EQ(i, desk_index); + ASSERT_EQ(base::NumberToString(i), browser->user_title()); + } + + // Check that a browser window is restored to the right desk, desk i_th + // if Bento desks restore is enabled. Otherwiser it should restores to the + // default first desk. + ASSERT_TRUE(ash::AutotestDesksApi().IsWindowInDesk( + browser->window()->GetNativeWindow(), + IsBentoEnabled() ? desk_index : 0)); + int workspace = browser->window()->GetNativeWindow()->GetProperty( + aura::client::kWindowWorkspaceKey); + ASSERT_EQ(desk_index, + workspace == aura::client::kUnassignedWorkspace ? 0 : workspace); + } +} +#endif + +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, PRE_RestoreAppsV1) { // Create a trusted app. CreateBrowserWithParams(CreateParamsForApp(test_app_name1, true)); // Create a second trusted app with two windows. @@ -119,7 +208,7 @@ TurnOnSessionRestore(); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, RestoreAppsV1) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, RestoreAppsV1) { size_t total_count = 0; size_t app1_count = 0; size_t app2_count = 0; @@ -135,7 +224,7 @@ EXPECT_EQ(4u, total_count); // Default browser() + 3 app windows } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_RestoreAppsPopup) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, PRE_RestoreAppsPopup) { // Create a trusted app popup. CreateBrowserWithParams(CreateParamsForAppPopup(test_app_name1, true)); // Create a second trusted app popup with two windows. @@ -147,7 +236,7 @@ TurnOnSessionRestore(); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, RestoreAppsPopup) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, RestoreAppsPopup) { size_t total_count = 0; size_t app1_count = 0; size_t app2_count = 0; @@ -163,14 +252,14 @@ EXPECT_EQ(4u, total_count); // Default browser() + 3 app windows } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_RestoreNoDevtools) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, PRE_RestoreNoDevtools) { // Create devtools. CreateBrowserWithParams(Browser::CreateParams::CreateForDevTools(profile())); TurnOnSessionRestore(); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, RestoreNoDevtools) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, RestoreNoDevtools) { size_t total_count = 0; size_t devtools_count = 0; for (auto* browser : *BrowserList::GetInstance()) { @@ -182,7 +271,7 @@ EXPECT_EQ(0u, devtools_count); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_RestoreMaximized) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, PRE_RestoreMaximized) { // One browser window is always created by default. ASSERT_TRUE(browser()); // Create a second browser window and maximize it. @@ -214,7 +303,7 @@ TurnOnSessionRestore(); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, RestoreMaximized) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, RestoreMaximized) { size_t total_count = 0; size_t app1_maximized_count = 0; size_t app2_maximized_count = 0; @@ -236,7 +325,7 @@ } // Test for crash when restoring minimized windows. http://crbug.com/679513. -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_RestoreMinimized) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, PRE_RestoreMinimized) { // One browser window is always created by default. ASSERT_TRUE(browser()); browser()->window()->Minimize(); @@ -251,7 +340,7 @@ TurnOnSessionRestore(); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, RestoreMinimized) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, RestoreMinimized) { size_t total_count = 0; size_t minimized_count = 0; for (auto* browser : *BrowserList::GetInstance()) { @@ -266,7 +355,7 @@ EXPECT_NE(2u, minimized_count); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, PRE_OmitTerminalApp) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, PRE_OmitTerminalApp) { const std::string terminal_app_name = web_app::GenerateApplicationNameFromAppId( crostini::kCrostiniTerminalSystemAppId); @@ -275,7 +364,7 @@ TurnOnSessionRestore(); } -IN_PROC_BROWSER_TEST_F(SessionRestoreTestChromeOS, OmitTerminalApp) { +IN_PROC_BROWSER_TEST_P(SessionRestoreTestChromeOS, OmitTerminalApp) { const std::string terminal_app_name = web_app::GenerateApplicationNameFromAppId( crostini::kCrostiniTerminalSystemAppId); @@ -342,3 +431,4 @@ INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_MANIFEST_INSTALL_P( SystemWebAppSessionRestoreTestChromeOS); +INSTANTIATE_TEST_SUITE_P(All, SessionRestoreTestChromeOS, ::testing::Bool());
diff --git a/chrome/browser/sessions/session_service.cc b/chrome/browser/sessions/session_service.cc index 68b7b287..6768ba04 100644 --- a/chrome/browser/sessions/session_service.cc +++ b/chrome/browser/sessions/session_service.cc
@@ -273,6 +273,11 @@ RestoreIfNecessary(std::vector<GURL>(), browser); SetWindowType(browser->session_id(), browser->type()); SetWindowAppName(browser->session_id(), browser->app_name()); + + // Save a browser workspace after window is created in `Browser()`. + // Bento desks restore feature in ash requires this line to restore correctly + // after creating a new browser window in a particular desk. + SetWindowWorkspace(browser->session_id(), browser->window()->GetWorkspace()); } void SessionService::WindowClosing(const SessionID& window_id) {
diff --git a/chrome/browser/sessions/session_service.h b/chrome/browser/sessions/session_service.h index 30fbf88..625b60640 100644 --- a/chrome/browser/sessions/session_service.h +++ b/chrome/browser/sessions/session_service.h
@@ -226,6 +226,7 @@ FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RestoreActivation2); FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, RemoveUnusedRestoreWindowsTest); FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, Workspace); + FRIEND_TEST_ALL_PREFIXES(SessionServiceTest, WorkspaceSavedOnOpened); FRIEND_TEST_ALL_PREFIXES(NoStartupWindowTest, DontInitSessionServiceForApps); typedef std::map<SessionID, std::pair<int, int>> IdToRange;
diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index bc457ec7..8a49601 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc
@@ -1257,6 +1257,35 @@ EXPECT_TRUE(found_workspace_command); } +// Tests that the workspace is saved in the browser session during +// `SessionService::WindowOpened(),` called in `Browser()` constructor to +// save the current workspace to newly created browser. +TEST_F(SessionServiceTest, WorkspaceSavedOnOpened) { + const std::string workspace = "xyz"; + auto* test_browser_window = + static_cast<TestBrowserWindow*>(browser()->window()); + test_browser_window->set_workspace(workspace); + service()->WindowOpened(browser()); + + sessions::CommandStorageManager* command_storage_manager = + service()->GetCommandStorageManagerForTest(); + const std::vector<std::unique_ptr<sessions::SessionCommand>>& + pending_commands = command_storage_manager->pending_commands(); + bool found_workspace_command = false; + std::unique_ptr<sessions::SessionCommand> workspace_command = + sessions::CreateSetWindowWorkspaceCommand(browser()->session_id(), + workspace); + for (const auto& command : pending_commands) { + if (command->id() == workspace_command->id() && + command->contents_as_string_piece() == + workspace_command->contents_as_string_piece()) { + found_workspace_command = true; + break; + } + } + EXPECT_TRUE(found_workspace_command); +} + // Functions used by GetSessionsAndDestroy. namespace {
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index 37c8d0a..2dead3f 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -56,7 +56,6 @@ #endif #if !defined(OS_ANDROID) -#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/profiles/profile_window.h" #endif
diff --git a/chrome/browser/signin/dice_intercepted_session_startup_helper.cc b/chrome/browser/signin/dice_intercepted_session_startup_helper.cc index da9e757..35538d84 100644 --- a/chrome/browser/signin/dice_intercepted_session_startup_helper.cc +++ b/chrome/browser/signin/dice_intercepted_session_startup_helper.cc
@@ -17,12 +17,9 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/common/webui_url_constants.h" -#include "components/signin/public/base/multilogin_parameters.h" #include "components/signin/public/identity_manager/accounts_cookie_mutator.h" #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" -#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h" #include "content/public/browser/web_contents.h" -#include "google_apis/gaia/gaia_auth_fetcher.h" #include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/google_service_auth_error.h" #include "url/gurl.h" @@ -40,23 +37,13 @@ }) != accounts.end(); } -void RecordSessionStartupDuration(const std::string& histogram_name, - base::TimeDelta duration) { - base::UmaHistogramCustomTimes(histogram_name, duration, - /*min=*/base::TimeDelta::FromMilliseconds(1), - /*max=*/base::TimeDelta::FromSeconds(30), 50); -} - } // namespace DiceInterceptedSessionStartupHelper::DiceInterceptedSessionStartupHelper( Profile* profile, - bool is_new_profile, CoreAccountId account_id, content::WebContents* tab_to_move) - : profile_(profile), - use_multilogin_(is_new_profile), - account_id_(account_id) { + : profile_(profile), account_id_(account_id) { Observe(tab_to_move); } @@ -77,26 +64,24 @@ identity_manager->GetAccountsInCookieJar(); if (cookie_info.accounts_are_fresh && CookieInfoContains(cookie_info, account_id_)) { - MoveTab(use_multilogin_ ? Result::kMultiloginNothingToDo - : Result::kReconcilorNothingToDo); + MoveTab(); } else { - // Set the timeout. + // TODO(https://crbug.com/1051864): cookie notifications are not triggered + // when the account is added by the reconcilor. Observe the reconcilor and + // re-trigger the cookie update when it completes. + reconcilor_observer_.Observe( + AccountReconcilorFactory::GetForProfile(profile_)); + identity_manager->GetAccountsCookieMutator()->TriggerCookieJarUpdate(); + + accounts_in_cookie_observer_.Observe(identity_manager); on_cookie_update_timeout_.Reset(base::BindOnce( - &DiceInterceptedSessionStartupHelper::MoveTab, base::Unretained(this), - use_multilogin_ ? Result::kMultiloginTimeout - : Result::kReconcilorTimeout)); + &DiceInterceptedSessionStartupHelper::MoveTab, base::Unretained(this))); // Adding accounts to the cookies can be an expensive operation. In // particular the ExternalCCResult fetch may time out after multiple seconds // (see kExternalCCResultTimeoutSeconds and https://crbug.com/750316#c37). base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, on_cookie_update_timeout_.callback(), base::TimeDelta::FromSeconds(12)); - - accounts_in_cookie_observer_.Observe(identity_manager); - if (use_multilogin_) - StartupMultilogin(identity_manager); - else - StartupReconcilor(identity_manager); } } @@ -109,14 +94,11 @@ return; if (!CookieInfoContains(accounts_in_cookie_jar_info, account_id_)) return; - - MoveTab(use_multilogin_ ? Result::kMultiloginOtherSuccess - : Result::kReconcilorSuccess); + MoveTab(); } void DiceInterceptedSessionStartupHelper::OnStateChanged( signin_metrics::AccountReconcilorState state) { - DCHECK(!use_multilogin_); if (state == signin_metrics::ACCOUNT_RECONCILOR_ERROR) { reconcile_error_encountered_ = true; return; @@ -136,57 +118,15 @@ } } -void DiceInterceptedSessionStartupHelper::StartupMultilogin( - signin::IdentityManager* identity_manager) { - // Lock the reconcilor to avoid making multiple multilogin calls. - reconcilor_lock_ = std::make_unique<AccountReconcilor::Lock>( - AccountReconcilorFactory::GetForProfile(profile_)); - - // Start the multilogin call. - signin::MultiloginParameters params = { - /*mode=*/gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, - /*accounts_to_send=*/{account_id_}}; - identity_manager->GetAccountsCookieMutator()->SetAccountsInCookie( - params, gaia::GaiaSource::kChrome, - base::BindOnce( - &DiceInterceptedSessionStartupHelper::OnSetAccountInCookieCompleted, - weak_factory_.GetWeakPtr())); -} - -void DiceInterceptedSessionStartupHelper::StartupReconcilor( - signin::IdentityManager* identity_manager) { - // TODO(https://crbug.com/1051864): cookie notifications are not triggered - // when the account is added by the reconcilor. Observe the reconcilor and - // re-trigger the cookie update when it completes. - reconcilor_observer_.Observe( - AccountReconcilorFactory::GetForProfile(profile_)); - identity_manager->GetAccountsCookieMutator()->TriggerCookieJarUpdate(); -} - -void DiceInterceptedSessionStartupHelper::OnSetAccountInCookieCompleted( - signin::SetAccountsInCookieResult result) { - DCHECK(use_multilogin_); - Result session_startup_result = Result::kMultiloginOtherSuccess; - switch (result) { - case signin::SetAccountsInCookieResult::kSuccess: - session_startup_result = Result::kMultiloginSuccess; - break; - case signin::SetAccountsInCookieResult::kTransientError: - session_startup_result = Result::kMultiloginTransientError; - break; - case signin::SetAccountsInCookieResult::kPersistentError: - session_startup_result = Result::kMultiloginPersistentError; - break; - } - - MoveTab(session_startup_result); -} - -void DiceInterceptedSessionStartupHelper::MoveTab(Result result) { +void DiceInterceptedSessionStartupHelper::MoveTab() { accounts_in_cookie_observer_.Reset(); reconcilor_observer_.Reset(); on_cookie_update_timeout_.Cancel(); - reconcilor_lock_.reset(); + + // TODO(https://crbug.com/1151313): Remove this histogram when the cause + // for the timeouts is understood. + base::UmaHistogramBoolean("Signin.Intercept.SessionStartupReconcileError", + reconcile_error_encountered_); GURL url_to_open = GURL(chrome::kChromeUINewTabURL); // If the intercepted web contents is still alive, close it now. @@ -200,20 +140,8 @@ ui::PAGE_TRANSITION_AUTO_BOOKMARK); Navigate(¶ms); - base::UmaHistogramEnumeration("Signin.Intercept.SessionStartupResult", - result); - base::TimeDelta duration = base::TimeTicks::Now() - session_startup_time_; - if (use_multilogin_) { - RecordSessionStartupDuration( - "Signin.Intercept.SessionStartupDuration.Multilogin", duration); - } else { - RecordSessionStartupDuration( - "Signin.Intercept.SessionStartupDuration.Reconcilor", duration); - // TODO(https://crbug.com/1151313): Remove this histogram when the cause - // for the timeouts is understood. - base::UmaHistogramBoolean("Signin.Intercept.SessionStartupReconcileError", - reconcile_error_encountered_); - } + base::UmaHistogramTimes("Signin.Intercept.SessionStartupDuration", + base::TimeTicks::Now() - session_startup_time_); if (callback_) std::move(callback_).Run();
diff --git a/chrome/browser/signin/dice_intercepted_session_startup_helper.h b/chrome/browser/signin/dice_intercepted_session_startup_helper.h index d3c99e17..7b1ebd63 100644 --- a/chrome/browser/signin/dice_intercepted_session_startup_helper.h +++ b/chrome/browser/signin/dice_intercepted_session_startup_helper.h
@@ -7,7 +7,6 @@ #include "base/callback_forward.h" #include "base/cancelable_callback.h" -#include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "base/time/time.h" #include "components/signin/core/browser/account_reconcilor.h" @@ -21,8 +20,6 @@ namespace signin { struct AccountsInCookieJarInfo; -class IdentityManager; -enum class SetAccountsInCookieResult; } class GoogleServiceAuthError; @@ -38,28 +35,12 @@ public signin::IdentityManager::Observer, public AccountReconcilor::Observer { public: - // Used in UMA histograms, do not reorder or remove values. - enum class Result { - kReconcilorNothingToDo = 0, - kMultiloginNothingToDo = 1, - kReconcilorSuccess = 2, // The account was added by the reconcilor. - kMultiloginSuccess = 3, // The account was added by this object. - kMultiloginOtherSuccess = 4, // The account was added by something else. - kMultiloginTimeout = 5, - kReconcilorTimeout = 6, - kMultiloginTransientError = 7, - kMultiloginPersistentError = 8, - - kMaxValue = kMultiloginPersistentError - }; - // |profile| is the new profile that was created after signin interception. // |account_id| is the main account for the profile, it's already in the // profile. // |tab_to_move| is the tab where the interception happened, in the source // profile. DiceInterceptedSessionStartupHelper(Profile* profile, - bool is_new_profile, CoreAccountId account_id, content::WebContents* tab_to_move); @@ -82,22 +63,11 @@ void OnStateChanged(signin_metrics::AccountReconcilorState state) override; private: - // For new profiles, the account is added directly using multilogin. - void StartupMultilogin(signin::IdentityManager* identity_manager); - - // For existing profiles, simply wait for the reconcilor to update the - // accounts. - void StartupReconcilor(signin::IdentityManager* identity_manager); - - // Called when multilogin completes. - void OnSetAccountInCookieCompleted(signin::SetAccountsInCookieResult result); - // Creates a browser with a new tab, and closes the intercepted tab if it's // still open. - void MoveTab(Result result); + void MoveTab(); Profile* const profile_; - bool use_multilogin_; CoreAccountId account_id_; base::OnceClosure callback_; bool reconcile_error_encountered_ = false; @@ -106,13 +76,10 @@ accounts_in_cookie_observer_{this}; base::ScopedObservation<AccountReconcilor, AccountReconcilor::Observer> reconcilor_observer_{this}; - std::unique_ptr<AccountReconcilor::Lock> reconcilor_lock_; base::TimeTicks session_startup_time_; // Timeout while waiting for the account to be added to the cookies in the new // profile. base::CancelableOnceCallback<void()> on_cookie_update_timeout_; - - base::WeakPtrFactory<DiceInterceptedSessionStartupHelper> weak_factory_{this}; }; #endif // CHROME_BROWSER_SIGNIN_DICE_INTERCEPTED_SESSION_STARTUP_HELPER_H_
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc index 03ab3d0d..9f9e6de 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -271,16 +271,16 @@ CoreAccountId account_id, content::WebContents* intercepted_contents, std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> bubble_handle, - bool is_new_profile) { + bool show_customization_bubble) { DCHECK(!session_startup_helper_); DCHECK(bubble_handle); interception_bubble_handle_ = std::move(bubble_handle); session_startup_helper_ = std::make_unique<DiceInterceptedSessionStartupHelper>( - profile_, is_new_profile, account_id, intercepted_contents); + profile_, account_id, intercepted_contents); session_startup_helper_->Startup( base::BindOnce(&DiceWebSigninInterceptor::OnNewBrowserCreated, - base::Unretained(this), is_new_profile)); + base::Unretained(this), show_customization_bubble)); } void DiceWebSigninInterceptor::Shutdown() { @@ -477,22 +477,21 @@ return; } - // The profile color is defined only when the profile has just been created - // (with interception type kMultiUser or kEnterprise). If the profile is not - // new (kProfileSwitch) or if it is a guest profile, then the color is not - // updated. - bool is_new_profile = profile_color.has_value(); - if (is_new_profile) { + bool show_customization_bubble = false; + if (profile_color.has_value()) { + // The profile color is defined only when the profile has just been created + // (with interception type kMultiUser or kEnterprise). If the profile is not + // new (kProfileSwitch), then the color is not updated. base::UmaHistogramTimes( "Signin.Intercept.ProfileCreationDuration", base::TimeTicks::Now() - profile_creation_start_time_); ProfileMetrics::LogProfileAddNewUser( ProfileMetrics::ADD_NEW_USER_SIGNIN_INTERCEPTION); - if (!new_profile->IsEphemeralGuestProfile()) { - // Apply the new color to the profile. - ThemeServiceFactory::GetForProfile(new_profile) - ->BuildAutogeneratedThemeFromColor(*profile_color); - } + // Apply the new color to the profile. + ThemeServiceFactory::GetForProfile(new_profile) + ->BuildAutogeneratedThemeFromColor(*profile_color); + // Show the customization UI to allow changing the color. + show_customization_bubble = !new_profile->IsEphemeralGuestProfile(); } else { base::UmaHistogramTimes( "Signin.Intercept.ProfileSwitchDuration", @@ -504,15 +503,16 @@ DiceWebSigninInterceptorFactory::GetForProfile(new_profile) ->CreateBrowserAfterSigninInterception( account_id_, web_contents(), std::move(interception_bubble_handle_), - is_new_profile); + show_customization_bubble); Reset(); } -void DiceWebSigninInterceptor::OnNewBrowserCreated(bool is_new_profile) { +void DiceWebSigninInterceptor::OnNewBrowserCreated( + bool show_customization_bubble) { DCHECK(interception_bubble_handle_); interception_bubble_handle_.reset(); // Close the bubble now. session_startup_helper_.reset(); - if (is_new_profile && !profile_->IsEphemeralGuestProfile()) { + if (show_customization_bubble) { Browser* browser = chrome::FindBrowserWithProfile(profile_); DCHECK(browser); delegate_->ShowProfileCustomizationBubble(browser);
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.h b/chrome/browser/signin/dice_web_signin_interceptor.h index 42967f5..033b549d 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.h +++ b/chrome/browser/signin/dice_web_signin_interceptor.h
@@ -205,12 +205,14 @@ // `intercepted_contents` may be null if the tab was already closed. // The intercepted web contents belong to the source profile (which is not the // profile attached to this service). + // `show_customization_bubble` indicates whether the customization bubble + // should be shown after the browser is opened. void CreateBrowserAfterSigninInterception( CoreAccountId account_id, content::WebContents* intercepted_contents, std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> bubble_handle, - bool is_new_profile); + bool show_customization_bubble); // Returns the outcome of the interception heuristic. // If the outcome is kInterceptProfileSwitch, the target profile is returned @@ -281,7 +283,7 @@ // Called when the new browser is created after interception. Passed as // callback to `session_startup_helper_`. - void OnNewBrowserCreated(bool is_new_profile); + void OnNewBrowserCreated(bool show_customization_bubble); // Returns a 8-bit hash of the email that can be persisted. static std::string GetPersistentEmailHash(const std::string& email);
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc index 41158ec..e4265c8cd 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/signin/dice_web_signin_interceptor.h" #include <map> -#include <string> #include "base/memory/weak_ptr.h" #include "base/run_loop.h" @@ -22,7 +21,6 @@ #include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/chrome_signin_client_test_util.h" -#include "chrome/browser/signin/dice_intercepted_session_startup_helper.h" #include "chrome/browser/signin/dice_web_signin_interceptor_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" @@ -39,19 +37,12 @@ #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/signin/public/identity_manager/primary_account_mutator.h" -#include "components/signin/public/identity_manager/test_identity_manager_observer.h" #include "content/public/test/browser_test.h" -#include "google_apis/gaia/fake_gaia.h" -#include "google_apis/gaia/gaia_switches.h" -#include "google_apis/gaia/gaia_urls.h" -#include "net/test/embedded_test_server/default_handlers.h" -#include "net/test/embedded_test_server/http_response.h" #include "services/network/test/test_url_loader_factory.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace { - class FakeDiceWebSigninInterceptorDelegate; class FakeBubbleHandle : public ScopedDiceWebSigninInterceptionBubbleHandle, @@ -80,7 +71,6 @@ SigninInterceptionResult::kAccepted)); return bubble_handle; } - void ShowProfileCustomizationBubble(Browser* browser) override { EXPECT_FALSE(customized_browser_) << "Customization must be shown only once."; @@ -88,7 +78,6 @@ } Browser* customized_browser() { return customized_browser_; } - void set_expected_interception_type( DiceWebSigninInterceptor::SigninInterceptionType type) { expected_interception_type_ = type; @@ -168,31 +157,16 @@ profile_creation_count); histogram_tester.ExpectTotalCount("Signin.Intercept.ProfileSwitchDuration", profile_switch_count); - histogram_tester.ExpectTotalCount( - "Signin.Intercept.SessionStartupDuration.Multilogin", - profile_creation_count); - histogram_tester.ExpectTotalCount( - "Signin.Intercept.SessionStartupDuration.Reconcilor", - profile_switch_count); - histogram_tester.ExpectUniqueSample( - "Signin.Intercept.SessionStartupResult", - profile_switch_count - ? DiceInterceptedSessionStartupHelper::Result::kReconcilorSuccess - : DiceInterceptedSessionStartupHelper::Result::kMultiloginSuccess, - 1); + histogram_tester.ExpectTotalCount("Signin.Intercept.SessionStartupDuration", + 1); } } // namespace class DiceWebSigninInterceptorBrowserTest : public InProcessBrowserTest { public: - DiceWebSigninInterceptorBrowserTest() - : embedded_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + DiceWebSigninInterceptorBrowserTest() { feature_list_.InitAndEnableFeature(kDiceWebSigninInterceptionFeature); - - net::test_server::RegisterDefaultHandlers(&embedded_test_server_); - embedded_test_server_.RegisterRequestHandler(base::BindRepeating( - &FakeGaia::HandleRequest, base::Unretained(&fake_gaia_))); } Profile* profile() { return browser()->profile(); } @@ -221,59 +195,13 @@ return interceptor_delegate; } - // Configures future profiles to use FakeGaia (otherwise they use - // IdentityTestEnvironment instead). Must be called before the profile is - // created. - void SetupFakeGaiaResponsesOnNewProfile(const std::string& email) { - set_test_url_loader_factory_on_new_profile_ = false; - FakeGaia::AccessTokenInfo access_token_info; - access_token_info.token = "test_access_token"; - access_token_info.any_scope = true; - access_token_info.audience = - GaiaUrls::GetInstance()->oauth2_chrome_client_id(); - access_token_info.email = email; - fake_gaia_.IssueOAuthToken( - base::StringPrintf("test_refresh_token_for_%s", email.c_str()), - access_token_info); - fake_gaia_.SetFakeMergeSessionParams(email, "sid_cookie", "lsid_cooke"); - } - - net::EmbeddedTestServer* test_server() { return &embedded_test_server_; } - - void WaitForTokensLoaded(signin::IdentityManager* identity_manager) { - if (identity_manager->AreRefreshTokensLoaded()) - return; - - base::RunLoop run_loop; - signin::TestIdentityManagerObserver load_credentials_observer( - identity_manager); - load_credentials_observer.SetOnRefreshTokensLoadedCallback( - run_loop.QuitClosure()); - run_loop.Run(); - } - private: - // InProcessBrowserTest: - void SetUp() override { - ASSERT_TRUE(embedded_test_server_.InitializeAndListen()); - InProcessBrowserTest::SetUp(); - } - void SetUpOnMainThread() override { - embedded_test_server_.StartAcceptingConnections(); + ASSERT_TRUE(embedded_test_server()->Start()); identity_test_env_profile_adaptor_ = std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile()); } - void SetUpCommandLine(base::CommandLine* command_line) override { - const GURL& base_url = embedded_test_server_.base_url(); - command_line->AppendSwitchASCII(::switches::kGaiaUrl, base_url.spec()); - command_line->AppendSwitchASCII(::switches::kLsoUrl, base_url.spec()); - command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, - base_url.spec()); - fake_gaia_.Initialize(); - } - void TearDownOnMainThread() override { // Must be destroyed before the Profile. identity_test_env_profile_adaptor_.reset(); @@ -290,13 +218,11 @@ } void OnWillCreateBrowserContextServices(content::BrowserContext* context) { - if (set_test_url_loader_factory_on_new_profile_) { - IdentityTestEnvironmentProfileAdaptor:: - SetIdentityTestEnvironmentFactoriesOnBrowserContext(context); - ChromeSigninClientFactory::GetInstance()->SetTestingFactory( - context, base::BindRepeating(&BuildChromeSigninClientWithURLLoader, - &test_url_loader_factory_)); - } + IdentityTestEnvironmentProfileAdaptor:: + SetIdentityTestEnvironmentFactoriesOnBrowserContext(context); + ChromeSigninClientFactory::GetInstance()->SetTestingFactory( + context, base::BindRepeating(&BuildChromeSigninClientWithURLLoader, + &test_url_loader_factory_)); DiceWebSigninInterceptorFactory::GetInstance()->SetTestingFactory( context, base::BindRepeating(&DiceWebSigninInterceptorBrowserTest:: @@ -322,9 +248,6 @@ base::CallbackListSubscription create_services_subscription_; std::map<content::BrowserContext*, FakeDiceWebSigninInterceptorDelegate*> interceptor_delegates_; - net::EmbeddedTestServer embedded_test_server_; - FakeGaia fake_gaia_; - bool set_test_url_loader_factory_on_new_profile_ = true; }; // Tests the complete interception flow including profile and browser creation. @@ -344,18 +267,12 @@ DCHECK(account_info.IsValid()); identity_test_env()->UpdateAccountInfoForAccount(account_info); - // The new profile does not use the IdentityTestEnvironment, and has a real - // IdentityManager. It relies on FakeGaia to handle the network requests - // instead. - SetupFakeGaiaResponsesOnNewProfile(account_info.email); - // Add a tab. - GURL intercepted_url = test_server()->GetURL("/defaultresponse"); + GURL intercepted_url = embedded_test_server()->GetURL("/defaultresponse"); content::WebContents* web_contents = AddTab(intercepted_url); int original_tab_count = browser()->tab_strip_model()->count(); // Do the signin interception. - EXPECT_EQ(BrowserList::GetInstance()->size(), 1u); Profile* new_profile = InterceptAndWaitProfileCreation(web_contents, account_info.account_id); ASSERT_TRUE(new_profile); @@ -364,7 +281,6 @@ EXPECT_TRUE(source_interceptor_delegate->intercept_bubble_shown()); signin::IdentityManager* new_identity_manager = IdentityManagerFactory::GetForProfile(new_profile); - WaitForTokensLoaded(new_identity_manager); EXPECT_TRUE(new_identity_manager->HasAccountWithRefreshToken( account_info.account_id)); @@ -380,10 +296,15 @@ EXPECT_TRUE(ThemeServiceFactory::GetForProfile(new_profile) ->UsingAutogeneratedTheme()); + // Add the account to the cookies (simulates the account reconcilor). + EXPECT_EQ(BrowserList::GetInstance()->size(), 1u); + signin::SetCookieAccounts(new_identity_manager, test_url_loader_factory(), + {{account_info.email, account_info.gaia}}); + // A browser has been created for the new profile and the tab was moved there. - Browser* added_browser = ui_test_utils::WaitForBrowserToOpen(); - ASSERT_TRUE(added_browser); ASSERT_EQ(BrowserList::GetInstance()->size(), 2u); + Browser* added_browser = BrowserList::GetInstance()->get(1); + ASSERT_TRUE(added_browser); EXPECT_EQ(added_browser->profile(), new_profile); EXPECT_EQ(browser()->tab_strip_model()->count(), original_tab_count - 1); EXPECT_EQ(added_browser->tab_strip_model()->GetActiveWebContents()->GetURL(), @@ -426,7 +347,7 @@ ASSERT_EQ(entry->GetGAIAId(), account_info.gaia); // Add a tab. - GURL intercepted_url = test_server()->GetURL("/defaultresponse"); + GURL intercepted_url = embedded_test_server()->GetURL("/defaultresponse"); content::WebContents* web_contents = AddTab(intercepted_url); int original_tab_count = browser()->tab_strip_model()->count(); @@ -506,7 +427,7 @@ account_info.account_id); // Add a tab. - GURL intercepted_url = test_server()->GetURL("/defaultresponse"); + GURL intercepted_url = embedded_test_server()->GetURL("/defaultresponse"); content::WebContents* web_contents = AddTab(intercepted_url); int original_tab_count = browser()->tab_strip_model()->count(); int other_original_tab_count = other_browser->tab_strip_model()->count(); @@ -558,7 +479,7 @@ identity_test_env()->UpdateAccountInfoForAccount(account_info); // Add a tab. - GURL intercepted_url = test_server()->GetURL("/defaultresponse"); + GURL intercepted_url = embedded_test_server()->GetURL("/defaultresponse"); content::WebContents* contents = AddTab(intercepted_url); int original_tab_count = browser()->tab_strip_model()->count();
diff --git a/chrome/browser/signin/signin_promo.cc b/chrome/browser/signin/signin_promo.cc index 22bb3c2fd..444319b23 100644 --- a/chrome/browser/signin/signin_promo.cc +++ b/chrome/browser/signin/signin_promo.cc
@@ -7,7 +7,6 @@ #include "base/strings/string_number_conversions.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/google/google_brand.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/account_consistency_mode_manager.h"
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc index 9b9af29b..a6f8c85 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
@@ -29,6 +29,7 @@ #include "components/subresource_filter/core/common/activation_decision.h" #include "components/subresource_filter/core/common/activation_scope.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "services/metrics/public/cpp/ukm_source_id.h" @@ -97,6 +98,18 @@ } } +subresource_filter::mojom::ActivationLevel +ChromeSubresourceFilterClient::OnPageActivationComputed( + content::NavigationHandle* navigation_handle, + subresource_filter::mojom::ActivationLevel initial_activation_level, + subresource_filter::ActivationDecision* decision) { + // TODO(crbug.com/1116095): Once SafeBrowsingActivationThrottle knows about + // ProfileInteractionManager, it can invoke ProfileInteractionManager directly + // and SubresourceFilterClient::OnPageActivationComputed() can be eliminated. + return profile_interaction_manager_->OnPageActivationComputed( + navigation_handle, initial_activation_level, decision); +} + void ChromeSubresourceFilterClient::OnAdsViolationTriggered( content::RenderFrameHost* rfh, subresource_filter::mojom::AdsViolation triggered_violation) { @@ -116,11 +129,6 @@ : nullptr; } -subresource_filter::ProfileInteractionManager* -ChromeSubresourceFilterClient::GetProfileInteractionManager() { - return profile_interaction_manager_.get(); -} - void ChromeSubresourceFilterClient::ShowUI(const GURL& url) { #if defined(OS_ANDROID) InfoBarService* infobar_service =
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.h b/chrome/browser/subresource_filter/chrome_subresource_filter_client.h index 72ee4a3..0ef6322 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.h +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.h
@@ -15,11 +15,13 @@ class GURL; namespace content { +class NavigationHandle; class WebContents; } // namespace content namespace subresource_filter { class ContentSubresourceFilterThrottleManager; +class ProfileInteractionManager; class SubresourceFilterProfileContext; } // namespace subresource_filter @@ -45,13 +47,15 @@ // SubresourceFilterClient: void ShowNotification() override; + subresource_filter::mojom::ActivationLevel OnPageActivationComputed( + content::NavigationHandle* navigation_handle, + subresource_filter::mojom::ActivationLevel initial_activation_level, + subresource_filter::ActivationDecision* decision) override; void OnAdsViolationTriggered( content::RenderFrameHost* rfh, subresource_filter::mojom::AdsViolation triggered_violation) override; const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> GetSafeBrowsingDatabaseManager() override; - subresource_filter::ProfileInteractionManager* GetProfileInteractionManager() - override; void OnReloadRequested() override; private:
diff --git a/chrome/browser/supervised_user/logged_in_user_mixin.cc b/chrome/browser/supervised_user/logged_in_user_mixin.cc index 8ab30aa8..4b6f5559 100644 --- a/chrome/browser/supervised_user/logged_in_user_mixin.cc +++ b/chrome/browser/supervised_user/logged_in_user_mixin.cc
@@ -6,6 +6,7 @@ #include <vector> +#include "chrome/browser/chromeos/login/wizard_controller.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/login/auth/stub_authenticator_builder.h" #include "chromeos/login/auth/user_context.h" @@ -49,7 +50,9 @@ AccountId::FromUserEmailGaiaId(FakeGaiaMixin::kFakeUserEmail, FakeGaiaMixin::kFakeUserGaiaId)), ConvertUserType(type)), - login_manager_(mixin_host, GetInitialUsers(user_, include_initial_user)), + login_manager_(mixin_host, + GetInitialUsers(user_, include_initial_user), + &fake_gaia_), local_policy_server_(mixin_host), user_policy_(mixin_host, user_.account_id, @@ -72,6 +75,8 @@ // account.google.com requests would never reach fake GAIA server without // this. test_base_->host_resolver()->AddRule("*", "127.0.0.1"); + // Ensures logging in doesn't hang on the post login Gaia screens. + WizardController::SkipPostLoginScreensForTesting(); } void LoggedInUserMixin::LogInUser(bool issue_any_scope_token, @@ -89,17 +94,14 @@ FakeGaiaMixin::kFakeRefreshToken); } if (request_policy_update) { - // Set up policy, which prevents the call to LoginAndWaitForActiveSession() - // below from hanging indefinitely in some test scenarios. + // Child users require user policy, set up an empty one so the user can get + // through login. GetUserPolicyMixin()->RequestPolicyUpdate(); } if (wait_for_active_session) { login_manager_.LoginAndWaitForActiveSession(user_context); - // Set the private |browser_| member in InProcessBrowserTest. - // Otherwise calls to InProcessBrowserTest::browser() returns null and leads - // to segmentation faults. - // Note: |browser_| is only non-null if should_launch_browser was set to - // true in the constructor. + // If should_launch_browser was set to true, then ensures + // InProcessBrowserTest::browser() doesn't return nullptr. test_base_->SelectFirstBrowser(); } else { login_manager_.AttemptLoginUsingAuthenticator(
diff --git a/chrome/browser/supervised_user/logged_in_user_mixin.h b/chrome/browser/supervised_user/logged_in_user_mixin.h index 9c6bb8e..31ddbde 100644 --- a/chrome/browser/supervised_user/logged_in_user_mixin.h +++ b/chrome/browser/supervised_user/logged_in_user_mixin.h
@@ -5,7 +5,6 @@ #ifndef CHROME_BROWSER_SUPERVISED_USER_LOGGED_IN_USER_MIXIN_H_ #define CHROME_BROWSER_SUPERVISED_USER_LOGGED_IN_USER_MIXIN_H_ -#include "base/macros.h" #include "base/optional.h" #include "chrome/browser/chromeos/login/test/embedded_test_server_mixin.h" #include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h" @@ -60,15 +59,13 @@ // that can be passed into this constructor. // |test_base|: just pass in a pointer to the browser test class. // |should_launch_browser| determines whether a browser instance is launched - // after successful login. Call SelectFirstBrowser() afterwards to ensure - // calls to browser() don't return nullptr. LogInUser() already calls - // SelectFirstBrowser() for convenience. + // after successful login. // |account_id| is the desired test account id for logging in. The default // test account already works for the majority of test cases, unless an // enterprise account is needed for setting up policy. - // |include_initial_user| determines whether the TestUserInfo should be passed - // to the initial users list of the LoginManagerMixin. Excluding the initial - // user causes the OOBE GAIA screen to show on start-up. + // |include_initial_user| if true, then the user already exists on the login + // screen. Otherwise, the user is newly added to the device and the OOBE Gaia + // screen will show on start-up. // |use_local_policy_server| determines if the LocalPolicyTestServerMixin // should be passed into the UserPolicyMixin. LoggedInUserMixin(InProcessBrowserTestMixinHost* mixin_host, @@ -78,7 +75,10 @@ bool should_launch_browser = true, base::Optional<AccountId> account_id = base::nullopt, bool include_initial_user = true, + // TODO(crbug/1112885): Remove this parameter. bool use_local_policy_server = true); + LoggedInUserMixin(const LoggedInUserMixin&) = delete; + LoggedInUserMixin& operator=(const LoggedInUserMixin&) = delete; ~LoggedInUserMixin() override; // InProcessBrowserTestMixin: @@ -93,7 +93,7 @@ // * If |request_policy_update|, UserPolicyMixin will set up user policy. void LogInUser(bool issue_any_scope_token = false, bool wait_for_active_session = true, - bool request_policy_update = false); + bool request_policy_update = true); LoginManagerMixin* GetLoginManagerMixin() { return &login_manager_; } @@ -123,8 +123,6 @@ FakeGaiaMixin fake_gaia_; InProcessBrowserTest* test_base_; - - DISALLOW_COPY_AND_ASSIGN(LoggedInUserMixin); }; } // namespace chromeos
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc index 31314b8..11f46de 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -37,7 +37,6 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" -#include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" using content::NavigationController; @@ -198,8 +197,6 @@ void SupervisedUserNavigationThrottleTest::SetUpOnMainThread() { MixinBasedInProcessBrowserTest::SetUpOnMainThread(); - // Resolve everything to localhost. - host_resolver()->AddIPLiteralRule("*", "127.0.0.1", "localhost"); ASSERT_TRUE(embedded_test_server()->Started());
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc index 917105fe..4147b38 100644 --- a/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_web_apps_bmo_sync_test.cc
@@ -193,7 +193,7 @@ // Test is flaky (crbug.com/1097050) IN_PROC_BROWSER_TEST_F(TwoClientWebAppsBMOSyncTest, DISABLED_SyncDoubleInstallation) { - ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(SetupClients()); ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(AllProfilesHaveSameWebAppIds()); @@ -203,6 +203,8 @@ EXPECT_EQ(app_id, app_id2); + ASSERT_TRUE(SetupSync()); + // Install a 'dummy' app & wait for installation to ensure sync has processed // the initial apps. InstallDummyAppAndWaitForSync(GURL("http://www.dummy.org/"), GetProfile(0), @@ -252,7 +254,7 @@ #endif IN_PROC_BROWSER_TEST_F(TwoClientWebAppsBMOSyncTest, MAYBE_SyncDoubleInstallationDifferentUserDisplayMode) { - ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(SetupClients()); ASSERT_TRUE(AllProfilesHaveSameWebAppIds()); WebApplicationInfo info; @@ -268,10 +270,14 @@ EXPECT_EQ(app_id, app_id2); - // Install a 'dummy' app & wait for installation to ensure sync has processed + ASSERT_TRUE(SetupSync()); + + // Install a 'dummy' apps & wait for installation to ensure sync has processed // the initial apps. - InstallDummyAppAndWaitForSync(GURL("http://www.dummy.org/"), GetProfile(0), + InstallDummyAppAndWaitForSync(GURL("http://www.dummy1.org/"), GetProfile(0), GetProfile(1)); + InstallDummyAppAndWaitForSync(GURL("http://www.dummy2.org/"), GetProfile(1), + GetProfile(0)); EXPECT_TRUE(AllProfilesHaveSameWebAppIds()); @@ -320,7 +326,7 @@ #endif IN_PROC_BROWSER_TEST_F(TwoClientWebAppsBMOSyncTest, MAYBE_DoubleInstallWithUninstall) { - ASSERT_TRUE(SetupSync()); + ASSERT_TRUE(SetupClients()); ASSERT_TRUE(AllProfilesHaveSameWebAppIds()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -329,6 +335,8 @@ AppId app_id2 = InstallAppAsUserInitiated(GetProfile(1)); EXPECT_EQ(app_id, app_id2); + ASSERT_TRUE(SetupSync()); + // Uninstall the app from one of the profiles. UninstallWebApp(GetProfile(0), app_id);
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn index f8929447..3ad0b09b 100644 --- a/chrome/browser/tab/BUILD.gn +++ b/chrome/browser/tab/BUILD.gn
@@ -53,6 +53,7 @@ "//chrome/browser/android/crypto:java", "//chrome/browser/contextmenu:java", "//chrome/browser/endpoint_fetcher:java", + "//chrome/browser/optimization_guide/android:java", "//chrome/browser/profiles/android:java", "//chrome/browser/ui/android/native_page:java", "//components/browser_ui/util/android:java", @@ -63,6 +64,7 @@ "//components/external_intents/android:java", "//components/find_in_page/android:java", "//components/navigation_interception/android:navigation_interception_java", + "//components/optimization_guide/proto:optimization_guide_proto_java", "//components/payments/content/android:java", "//components/security_state/content/android:java", "//components/security_state/core:security_state_enums_java",
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/DEPS index 93ed3c44..852502b 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/DEPS +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -7,6 +7,7 @@ "+chrome/browser/contextmenu/java", "+chrome/browser/endpoint_fetcher", "+chrome/browser/tab/java", + "+chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide", "+chrome/browser/profiles/android/java", "+chrome/browser/ui/android/native_page", "+components/browser_ui/util/android/java",
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java index a570c71..8c1f848 100644 --- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java +++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/ShoppingPersistedTabData.java
@@ -20,14 +20,19 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.chrome.browser.endpoint_fetcher.EndpointFetcher; +import org.chromium.chrome.browser.optimization_guide.OptimizationGuideBridgeFactory; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.proto.ShoppingPersistedTabData.ShoppingPersistedTabDataProto; +import org.chromium.components.optimization_guide.OptimizationGuideDecision; +import org.chromium.components.optimization_guide.proto.HintsProto; import org.chromium.components.payments.CurrencyFormatter; +import org.chromium.url.GURL; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; import java.util.Locale; import java.util.concurrent.TimeUnit; @@ -87,6 +92,15 @@ @VisibleForTesting protected EmptyTabObserver mUrlUpdatedObserver; + // Lazy initialization of OptimizationGuideBridgeFactory + private static class OptimizationGuideBridgeFactoryHolder { + private static final OptimizationGuideBridgeFactory sOptimizationGuideBridgeFactory; + static { + sOptimizationGuideBridgeFactory = new OptimizationGuideBridgeFactory( + Arrays.asList(HintsProto.OptimizationType.SHOPPING_PAGE_PREDICTOR)); + } + } + /** * A price drop for the offer {@link ShoppingPersistedTabData} * refers to @@ -171,18 +185,24 @@ -> { ShoppingPersistedTabData previousShoppingPersistedTabData = PersistedTabData.from(tab, USER_DATA_KEY); - EndpointFetcher.fetchUsingChromeAPIKey( - (endpointResponse) - -> { - supplierCallback.onResult( - build(tab, endpointResponse.getResponseString(), - previousShoppingPersistedTabData)); - }, - Profile.getLastUsedRegularProfile(), - String.format(ENDPOINT, tab.getUrlString()), HTTPS_METHOD, CONTENT_TYPE, - EMPTY_POST_DATA, TIMEOUT_MS, - new String[] { - ACCEPT_LANGUAGE_KEY, LocaleUtils.getDefaultLocaleListString()}); + ShoppingPersistedTabData.isShoppingPage(tab.getUrl(), (isShoppingPage) -> { + if (!isShoppingPage) { + supplierCallback.onResult(null); + return; + } + EndpointFetcher.fetchUsingChromeAPIKey( + (endpointResponse) + -> { + supplierCallback.onResult( + build(tab, endpointResponse.getResponseString(), + previousShoppingPersistedTabData)); + }, + Profile.getLastUsedRegularProfile(), + String.format(ENDPOINT, tab.getUrlString()), HTTPS_METHOD, + CONTENT_TYPE, EMPTY_POST_DATA, TIMEOUT_MS, + new String[] {ACCEPT_LANGUAGE_KEY, + LocaleUtils.getDefaultLocaleListString()}); + }); }, ShoppingPersistedTabData.class, callback); } @@ -448,4 +468,13 @@ mTab.removeObserver(mUrlUpdatedObserver); super.destroy(); } + + private static void isShoppingPage(GURL url, Callback<Boolean> callback) { + OptimizationGuideBridgeFactoryHolder.sOptimizationGuideBridgeFactory.create() + .canApplyOptimization(url, HintsProto.OptimizationType.SHOPPING_PAGE_PREDICTOR, + (decision, metadata) -> { + callback.onResult(decision == OptimizationGuideDecision.TRUE + || decision == OptimizationGuideDecision.UNKNOWN); + }); + } } \ No newline at end of file
diff --git a/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc b/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc index ffa44a8..637561f 100644 --- a/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc +++ b/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/test/metrics/histogram_tester.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/tab_contents/navigation_metrics_recorder.h" @@ -13,6 +12,7 @@ #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/navigation_metrics/navigation_metrics.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 9bd4987..3416ed9 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -502,6 +502,7 @@ "//components/signin/core/browser", "//components/signin/public/base:signin_buildflags", "//components/signin/public/identity_manager", + "//components/site_engagement/content", "//components/site_engagement/core/mojom:mojo_bindings", "//components/spellcheck/browser", "//components/ssl_errors", @@ -804,7 +805,7 @@ "//chrome/android:jni_headers", "//chrome/android/features/dev_ui:buildflags", "//chrome/browser/image_decoder", - "//chrome/browser/resources/webapks:webapks_ui_resources", + "//chrome/browser/resources/webapks:webapks_resources", "//components/autofill_assistant/browser", "//components/autofill_assistant/browser:proto", "//components/browser_ui/client_certificate/android", @@ -2708,6 +2709,7 @@ "//components/captive_portal/core", "//components/consent_auditor:consent_auditor", "//components/exo", + "//components/full_restore", "//components/login", "//components/metrics/structured:structured_events", "//components/services/app_service/public/cpp:app_file_handling", @@ -4204,7 +4206,6 @@ "//base", "//base/util/timer", "//chrome/browser/ui/views", - "//chrome/common/qr_code_generator", "//components/constrained_window", "//components/content_settings/browser/ui", "//components/media_message_center", @@ -4212,6 +4213,7 @@ "//components/payments/content", "//components/payments/content:utils", "//components/payments/core", + "//components/qr_code_generator", "//components/reading_list/features:flags", "//components/tab_count_metrics", "//components/ui_devtools/views",
diff --git a/chrome/browser/ui/DEPS b/chrome/browser/ui/DEPS index e376e69..1b13b71 100644 --- a/chrome/browser/ui/DEPS +++ b/chrome/browser/ui/DEPS
@@ -8,6 +8,7 @@ "+components/enterprise", "+components/infobars/android", "+components/page_load_metrics/browser", + "+components/qr_code_generator", "+components/safety_check", "+components/translate/content/android", "+services/content/public",
diff --git a/chrome/browser/ui/android/infobars/translate_compact_infobar.cc b/chrome/browser/ui/android/infobars/translate_compact_infobar.cc index 2d48217..e2fa933 100644 --- a/chrome/browser/ui/android/infobars/translate_compact_infobar.cc +++ b/chrome/browser/ui/android/infobars/translate_compact_infobar.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/infobars/infobar_service.h" #include "components/translate/content/android/translate_utils.h" #include "components/translate/core/browser/translate_infobar_delegate.h" +#include "components/translate/core/browser/translate_metrics_logger.h" #include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_context.h" @@ -96,10 +97,12 @@ Java_TranslateCompactInfoBar_setAutoAlwaysTranslate(env, GetJavaInfoBar()); } + delegate->ReportUIInteraction(translate::UIInteraction::kTranslate); } else if (action == infobars::InfoBarAndroid::ACTION_TRANSLATE_SHOW_ORIGINAL) { action_flags_ |= FLAG_REVERT; delegate->RevertWithoutClosingInfobar(); + delegate->ReportUIInteraction(translate::UIInteraction::kRevert); } else { DCHECK_EQ(infobars::InfoBarAndroid::ACTION_NONE, action); } @@ -124,11 +127,15 @@ base::android::ConvertJavaStringToUTF8(env, value); if (delegate->original_language_code().compare(source_code) != 0) delegate->UpdateOriginalLanguage(source_code); + delegate->ReportUIInteraction( + translate::UIInteraction::kChangeSourceLanguage); } else if (option == translate::TranslateUtils::OPTION_TARGET_CODE) { std::string target_code = base::android::ConvertJavaStringToUTF8(env, value); if (delegate->target_language_code().compare(target_code) != 0) delegate->UpdateTargetLanguage(target_code); + delegate->ReportUIInteraction( + translate::UIInteraction::kChangeTargetLanguage); } else { DCHECK(false); } @@ -145,6 +152,8 @@ action_flags_ |= FLAG_ALWAYS_TRANSLATE; delegate->ToggleAlwaysTranslate(); } + delegate->ReportUIInteraction( + translate::UIInteraction::kAlwaysTranslateLanguage); } else if (option == translate::TranslateUtils::OPTION_NEVER_TRANSLATE) { if (value && delegate->IsTranslatableLanguageByPrefs()) { action_flags_ |= FLAG_NEVER_LANGUAGE; @@ -152,6 +161,8 @@ RemoveSelf(); delegate->OnInfoBarClosedByUser(); } + delegate->ReportUIInteraction( + translate::UIInteraction::kNeverTranslateLanguage); } else if (option == translate::TranslateUtils::OPTION_NEVER_TRANSLATE_SITE) { if (value && !delegate->IsSiteOnNeverPromptList()) { action_flags_ |= FLAG_NEVER_SITE; @@ -159,6 +170,8 @@ RemoveSelf(); delegate->OnInfoBarClosedByUser(); } + delegate->ReportUIInteraction( + translate::UIInteraction::kNeverTranslateSite); } else { DCHECK(false); }
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index cadd9b6..68603016 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/nearby_sharing/nearby_share_delegate_impl.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/sessions/session_restore.h" #include "chrome/browser/ui/ash/back_gesture_contextual_nudge_delegate.h" #include "chrome/browser/ui/ash/chrome_accessibility_delegate.h" #include "chrome/browser/ui/ash/chrome_capture_mode_delegate.h" @@ -212,3 +213,8 @@ ash::NearbyShareController* controller) const { return std::make_unique<NearbyShareDelegateImpl>(controller); } + +bool ChromeShellDelegate::IsSessionRestoreInProgress() const { + Profile* profile = ProfileManager::GetActiveUserProfile(); + return SessionRestore::IsRestoring(profile); +}
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h index 4ea7cc3..cf94e2c 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.h +++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -46,6 +46,7 @@ media_session::MediaSessionService* GetMediaSessionService() override; std::unique_ptr<ash::NearbyShareDelegate> CreateNearbyShareDelegate( ash::NearbyShareController* controller) const override; + bool IsSessionRestoreInProgress() const override; private: DISALLOW_COPY_AND_ASSIGN(ChromeShellDelegate);
diff --git a/chrome/browser/ui/ash/clipboard_image_model_factory_impl.cc b/chrome/browser/ui/ash/clipboard_image_model_factory_impl.cc index 1ee035d..78ffea7 100644 --- a/chrome/browser/ui/ash/clipboard_image_model_factory_impl.cc +++ b/chrome/browser/ui/ash/clipboard_image_model_factory_impl.cc
@@ -29,7 +29,8 @@ void ClipboardImageModelFactoryImpl::CancelRequest( const base::UnguessableToken& id) { if (request_ && request_->IsRunningRequest(id)) { - request_->Stop(); + request_->Stop( + ClipboardImageModelRequest::RequestStopReason::kRequestCanceled); return; }
diff --git a/chrome/browser/ui/ash/clipboard_image_model_request.cc b/chrome/browser/ui/ash/clipboard_image_model_request.cc index 41d9a57..99193b5f 100644 --- a/chrome/browser/ui/ash/clipboard_image_model_request.cc +++ b/chrome/browser/ui/ash/clipboard_image_model_request.cc
@@ -9,6 +9,8 @@ #include "ash/public/cpp/clipboard_history_controller.h" #include "ash/public/cpp/scoped_clipboard_history_pause.h" #include "base/base64.h" +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_macros.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_view_host.h" @@ -75,7 +77,8 @@ base::RepeatingClosure on_request_finished_callback) : widget_(std::make_unique<views::Widget>()), web_view_(new views::WebView(profile)), - on_request_finished_callback_(std::move(on_request_finished_callback)) { + on_request_finished_callback_(std::move(on_request_finished_callback)), + request_creation_time_(base::TimeTicks::Now()) { views::Widget::InitParams widget_params; widget_params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; widget_params.ownership = @@ -88,7 +91,10 @@ web_contents()->SetDelegate(this); } -ClipboardImageModelRequest::~ClipboardImageModelRequest() = default; +ClipboardImageModelRequest::~ClipboardImageModelRequest() { + UMA_HISTOGRAM_TIMES("Ash.ClipboardHistory.ImageModelRequest.Lifetime", + base::TimeTicks::Now() - request_creation_time_); +} void ClipboardImageModelRequest::Start(Params&& params) { DCHECK(!deliver_image_model_callback_); @@ -101,6 +107,7 @@ timeout_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(10), this, &ClipboardImageModelRequest::OnTimeout); + request_start_time_ = base::TimeTicks::Now(); // Begin the document with the proper charset, this should prevent strange // looking characters from showing up in the render in some cases. @@ -130,7 +137,13 @@ web_contents()->GetNativeView()->SetBounds(gfx::Rect(0, 0, 1, 1)); } -void ClipboardImageModelRequest::Stop() { +void ClipboardImageModelRequest::Stop(RequestStopReason stop_reason) { + UMA_HISTOGRAM_ENUMERATION("Ash.ClipboardHistory.ImageModelRequest.StopReason", + stop_reason); + DCHECK(!request_start_time_.is_null()); + UMA_HISTOGRAM_TIMES("Ash.ClipboardHistory.ImageModelRequest.Runtime", + base::TimeTicks::Now() - request_start_time_); + request_start_time_ = base::TimeTicks(); scoped_clipboard_modifier_.reset(); weak_ptr_factory_.InvalidateWeakPtrs(); copy_surface_weak_ptr_factory_.InvalidateWeakPtrs(); @@ -148,7 +161,7 @@ DCHECK(IsRunningRequest()); Params params(request_id_, html_markup_, std::move(deliver_image_model_callback_)); - Stop(); + Stop(RequestStopReason::kRequestCanceled); return params; } @@ -231,7 +244,7 @@ content::RenderWidgetHostView* source_view = web_contents()->GetRenderViewHost()->GetWidget()->GetView(); if (source_view->GetViewBounds().size().IsEmpty()) { - Stop(); + Stop(RequestStopReason::kEmptyResult); return; } @@ -245,17 +258,17 @@ void ClipboardImageModelRequest::OnCopyComplete(const SkBitmap& bitmap) { if (!deliver_image_model_callback_) { - Stop(); + Stop(RequestStopReason::kMultipleCopyCompletion); return; } std::move(deliver_image_model_callback_) .Run(ui::ImageModel::FromImageSkia( gfx::ImageSkia::CreateFrom1xBitmap(bitmap))); - Stop(); + Stop(RequestStopReason::kFulfilled); } void ClipboardImageModelRequest::OnTimeout() { DCHECK(deliver_image_model_callback_); - Stop(); + Stop(RequestStopReason::kTimeout); }
diff --git a/chrome/browser/ui/ash/clipboard_image_model_request.h b/chrome/browser/ui/ash/clipboard_image_model_request.h index 19d1ac99..a2cf1ede 100644 --- a/chrome/browser/ui/ash/clipboard_image_model_request.h +++ b/chrome/browser/ui/ash/clipboard_image_model_request.h
@@ -9,6 +9,7 @@ #include <string> #include "base/optional.h" +#include "base/time/time.h" #include "base/timer/timer.h" #include "base/unguessable_token.h" #include "content/public/browser/web_contents_delegate.h" @@ -85,9 +86,22 @@ // fails to load after 5 seconds, OnTimeout is called. void Start(Params&& params); - // Stops the request and resets state. |web_view_| is still alive to - // enable fast restarting of the request. - void Stop(); + // The different reasons a request can `Stop()`. These values are logged to + // UMA. Entries should not be renumbered and numeric values should never be + // reused. Please keep in sync with "RequestStopReason" in + // src/tools/metrics/histograms/enums.xml. + enum class RequestStopReason { + kFulfilled = 0, + kTimeout = 1, + kEmptyResult = 2, + kMultipleCopyCompletion = 3, + kRequestCanceled = 4, + kMaxValue = kRequestCanceled, + }; + // Stops the request and resets state. `stop_reason` is the reason the request + // was `Stop()`-ed. |web_view_| is kept alive to enable fast restarting of the + // request. + void Stop(RequestStopReason stop_reason); // `Stop()`s the request and gets the params of the running request. Params StopAndGetParams(); @@ -154,6 +168,12 @@ // Timer used to abort requests which take longer than 5s to load. base::RepeatingTimer timeout_timer_; + // Time this object was created. Used to log object lifetime. + const base::TimeTicks request_creation_time_; + + // Time this object started its most recent request. + base::TimeTicks request_start_time_; + base::WeakPtrFactory<ClipboardImageModelRequest> weak_ptr_factory_{this}; // Used to debounce calls to `CopySurface()`.
diff --git a/chrome/browser/ui/ash/recording_service_browsertest.cc b/chrome/browser/ui/ash/recording_service_browsertest.cc index 6d8926b..633d56e 100644 --- a/chrome/browser/ui/ash/recording_service_browsertest.cc +++ b/chrome/browser/ui/ash/recording_service_browsertest.cc
@@ -180,17 +180,13 @@ FinishVideoRecordingTest(&test_api); } -// This test is currently disabled since it will always fail on the bots for -// now, since audio is not captured on the bots, and currently window recording -// captures no video frames, so the resulting video file will always be empty. -// TODO(crbug.com/1143930): Re-enable this once window capture is working. -IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, DISABLED_RecordWindow) { +IN_PROC_BROWSER_TEST_F(RecordingServiceBrowserTest, RecordWindow) { ash::CaptureModeTestApi test_api; test_api.StartForWindow(/*for_video=*/true); auto* generator = GetEventGenerator(); // Move the mouse cursor above the browser window to select it for window - // capture. - generator->MoveMouseTo(GetBrowserWindow()->GetBoundsInScreen().CenterPoint()); + // capture (make sure it doesn't hover over the capture bar). + generator->MoveMouseTo(GetBrowserWindow()->GetBoundsInScreen().top_center()); FinishVideoRecordingTest(&test_api); }
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc index 1964ef6..6c615286 100644 --- a/chrome/browser/ui/browser_ui_prefs.cc +++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -9,7 +9,6 @@ #include "base/numerics/safe_conversions.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/upgrade_detector/upgrade_detector.h" #include "chrome/common/buildflags.h"
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc index 76d50db..9159d014 100644 --- a/chrome/browser/ui/extensions/application_launch.cc +++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -21,8 +21,6 @@ #include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/apps/platform_apps/platform_app_launch.h" -#include "chrome/browser/banners/app_banner_settings_helper.h" -#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/launch_util.h" @@ -37,15 +35,8 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/extensions/extension_enable_flow.h" #include "chrome/browser/ui/extensions/extension_enable_flow_delegate.h" -#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" -#include "chrome/browser/ui/web_applications/web_app_launch_manager.h" #include "chrome/browser/ui/web_applications/web_app_launch_utils.h" -#include "chrome/browser/web_applications/components/os_integration_manager.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" -#include "chrome/browser/web_applications/components/web_app_provider_base.h" -#include "chrome/browser/web_applications/components/web_app_tab_helper_base.h" -#include "chrome/browser/web_applications/system_web_app_manager.h" -#include "chrome/browser/web_launch/web_launch_files_helper.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/url_constants.h" #include "content/public/browser/web_contents.h" @@ -139,12 +130,6 @@ if (override_url.GetOrigin() == extension->url()) return true; - if (extension->from_bookmark() && - extensions::AppLaunchInfo::GetFullLaunchURL(extension).GetOrigin() == - override_url.GetOrigin()) { - return true; - } - return false; } @@ -161,13 +146,6 @@ if (!params.override_url.is_empty()) { DCHECK(IsAllowedToOverrideURL(extension, params.override_url)); url = params.override_url; - } else if (extension->from_bookmark()) { - web_app::OsIntegrationManager& os_integration_manager = - web_app::WebAppProviderBase::GetProviderBase(profile) - ->os_integration_manager(); - url = os_integration_manager - .GetMatchingFileHandlerURL(params.app_id, params.launch_files) - .value_or(extensions::AppLaunchInfo::GetFullLaunchURL(extension)); } else { url = extensions::AppLaunchInfo::GetFullLaunchURL(extension); } @@ -275,13 +253,6 @@ contents = params.navigated_or_inserted_contents; } - if (extension->from_bookmark()) { - web_app::WebAppTabHelperBase* tab_helper = - web_app::WebAppTabHelperBase::FromWebContents(contents); - DCHECK(tab_helper); - tab_helper->SetAppId(extension->id()); - } - #if BUILDFLAG(IS_CHROMEOS_ASH) // In ash, LAUNCH_FULLSCREEN launches in the OpenApplicationWindow function // i.e. it should not reach here. @@ -333,15 +304,6 @@ GURL url = UrlForExtension(extension, profile, params); - // System Web Apps go through their own launch path. - base::Optional<web_app::SystemAppType> system_app_type = - web_app::GetSystemWebAppTypeForAppId(profile, extension->id()); - if (system_app_type) { - Browser* browser = web_app::LaunchSystemWebApp(profile, *system_app_type, - url, std::move(params)); - return browser->tab_strip_model()->GetActiveWebContents(); - } - // Record v1 app launch. Platform app launch is recorded when dispatching // the onLaunched event. prefs->SetLastLaunchTime(extension->id(), base::Time::Now()); @@ -365,34 +327,6 @@ break; } - if (extension->from_bookmark()) { - if (web_app::WebAppProviderBase::GetProviderBase(profile) - ->os_integration_manager() - .IsFileHandlingAPIAvailable(extension->id())) { - web_launch::WebLaunchFilesHelper::SetLaunchPaths(tab, url, - params.launch_files); - } - - UMA_HISTOGRAM_ENUMERATION("Extensions.BookmarkAppLaunchSource", - params.source); - UMA_HISTOGRAM_ENUMERATION("Extensions.BookmarkAppLaunchContainer", - params.container); - - // Record the launch time in the site engagement service. A recent bookmark - // app launch will provide an engagement boost to the origin. - site_engagement::SiteEngagementService* service = - site_engagement::SiteEngagementService::Get(profile); - service->SetLastShortcutLaunchTime(tab, url); - - // Refresh the app banner added to homescreen event. The user may have - // cleared their browsing data since installing the app, which removes the - // event and will potentially permit a banner to be shown for the site. - webapps::AppBannerSettingsHelper::RecordBannerEvent( - tab, url, url.spec(), - webapps::AppBannerSettingsHelper:: - APP_BANNER_EVENT_DID_ADD_TO_HOMESCREEN, - base::Time::Now()); - } return tab; } @@ -462,22 +396,13 @@ WebContents* const web_contents = nav_params.navigated_or_inserted_contents; - if (extension && !extension->from_bookmark()) { + if (extension) { DCHECK(extension->is_app()); extensions::TabHelper::FromWebContents(web_contents) ->SetExtensionApp(extension); } web_app::SetAppPrefsForWebContents(web_contents); - // TODO(https://crbug.com/1032443): - // Eventually move this to browser_navigator.cc: CreateTargetContents(). - if (extension && extension->from_bookmark()) { - web_app::WebAppTabHelperBase* tab_helper = - web_app::WebAppTabHelperBase::FromWebContents(web_contents); - DCHECK(tab_helper); - tab_helper->SetAppId(extension->id()); - } - return web_contents; } @@ -549,13 +474,6 @@ apps::mojom::LaunchContainer container; if (apps::OpenExtensionApplicationWindow(profile, app_id, command_line, current_directory)) { - const extensions::Extension* extension = - extensions::ExtensionRegistry::Get(profile)->GetInstalledExtension( - app_id); - // TODO(crbug.com/1061843): Remove this when BMO launches. - if (extension && extension->from_bookmark()) - web_app::RecordAppWindowLaunch(profile, app_id); - container = apps::mojom::LaunchContainer::kLaunchContainerWindow; } else if (apps::OpenExtensionApplicationTab(profile, app_id)) { container = apps::mojom::LaunchContainer::kLaunchContainerTab;
diff --git a/chrome/browser/ui/profile_picker.cc b/chrome/browser/ui/profile_picker.cc index 6460acd..22589b89 100644 --- a/chrome/browser/ui/profile_picker.cc +++ b/chrome/browser/ui/profile_picker.cc
@@ -4,14 +4,11 @@ #include "chrome/browser/ui/profile_picker.h" -#include <algorithm> #include <string> #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" -#include "base/time/time.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profiles_state.h" @@ -22,16 +19,6 @@ namespace { -constexpr base::TimeDelta kActiveTimeThreshold = base::TimeDelta::FromDays(28); - -// Returns a pref value indicating whether the profile picker has been shown to -// the user before. -bool ProfilePickerShown() { - PrefService* prefs = g_browser_process->local_state(); - DCHECK(prefs); - return prefs->GetBoolean(prefs::kBrowserProfilePickerShown); -} - ProfilePicker::AvailabilityOnStartup GetAvailabilityOnStartup() { int availability_on_startup = g_browser_process->local_state()->GetInteger( prefs::kBrowserProfilePickerAvailabilityOnStartup); @@ -63,28 +50,13 @@ if (availability_on_startup == AvailabilityOnStartup::kForced) return true; - ProfileManager* profile_manager = g_browser_process->profile_manager(); - - size_t number_of_profiles = profile_manager->GetNumberOfProfiles(); + size_t number_of_profiles = g_browser_process->profile_manager() + ->GetProfileAttributesStorage() + .GetNumberOfProfiles(); // Need to consider 0 profiles as this is what happens in some browser-tests. if (number_of_profiles <= 1) return false; - std::vector<ProfileAttributesEntry*> profile_attributes = - profile_manager->GetProfileAttributesStorage().GetAllProfilesAttributes(); - int number_of_active_profiles = - std::count_if(profile_attributes.begin(), profile_attributes.end(), - [](ProfileAttributesEntry* entry) { - return (base::Time::Now() - entry->GetActiveTime() < - kActiveTimeThreshold) && - !entry->IsGuest(); - }); - // Don't show the profile picker at launch if the user has less than two - // active profiles. However, if the user has already seen the profile picker - // before, respect user's preference. - if (number_of_active_profiles < 2 && !ProfilePickerShown()) - return false; - bool pref_enabled = g_browser_process->local_state()->GetBoolean( prefs::kBrowserShowProfilePickerOnStartup); base::UmaHistogramBoolean("ProfilePicker.AskOnStartup", pref_enabled);
diff --git a/chrome/browser/ui/profile_picker_unittest.cc b/chrome/browser/ui/profile_picker_unittest.cc deleted file mode 100644 index e531160..0000000 --- a/chrome/browser/ui/profile_picker_unittest.cc +++ /dev/null
@@ -1,169 +0,0 @@ -// Copyright 2020 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/profile_picker.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "base/time/time.h" -#include "chrome/browser/profiles/profile_attributes_entry.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/ui_features.h" -#include "chrome/common/chrome_features.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile_manager.h" -#include "components/prefs/pref_service.h" -#include "content/public/test/browser_task_environment.h" -#include "testing/gtest/include/gtest/gtest.h" - -class ProfilePickerTest : public testing::Test { - public: - ProfilePickerTest() - : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) { - feature_list_.InitAndEnableFeature(features::kNewProfilePicker); - } - - void SetUp() override { ASSERT_TRUE(testing_profile_manager_.SetUp()); } - - ProfileAttributesEntry* GetProfileAttributes(Profile* profile) { - ProfileAttributesEntry* entry = nullptr; - testing_profile_manager() - ->profile_attributes_storage() - ->GetProfileAttributesWithPath(profile->GetPath(), &entry); - return entry; - } - - base::test::TaskEnvironment* task_environment() { return &task_environment_; } - - TestingProfileManager* testing_profile_manager() { - return &testing_profile_manager_; - } - - PrefService* local_state() { - return testing_profile_manager()->local_state()->Get(); - } - - private: - content::BrowserTaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - TestingProfileManager testing_profile_manager_; - base::test::ScopedFeatureList feature_list_; -}; - -TEST_F(ProfilePickerTest, ShouldShowAtLaunch_MultipleProfiles_TwoActive) { - TestingProfile* profile1 = - testing_profile_manager()->CreateTestingProfile("profile1"); - GetProfileAttributes(profile1)->SetActiveTimeToNow(); - TestingProfile* profile2 = - testing_profile_manager()->CreateTestingProfile("profile2"); - GetProfileAttributes(profile2)->SetActiveTimeToNow(); - - EXPECT_TRUE(ProfilePicker::ShouldShowAtLaunch()); - - // Should be within the activity time threshold. - task_environment()->FastForwardBy(base::TimeDelta::FromDays(27)); - EXPECT_TRUE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTest, - ShouldShowAtLaunch_MultipleProfiles_Inactive_SeenPicker) { - testing_profile_manager()->CreateTestingProfile("profile1"); - testing_profile_manager()->CreateTestingProfile("profile2"); - local_state()->SetBoolean(prefs::kBrowserProfilePickerShown, true); - - EXPECT_TRUE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTest, ShouldShowAtLaunch_MultipleProfiles_OneGuest) { - TestingProfile* profile1 = - testing_profile_manager()->CreateTestingProfile("profile1"); - GetProfileAttributes(profile1)->SetActiveTimeToNow(); - testing_profile_manager()->CreateTestingProfile("profile2"); - testing_profile_manager()->CreateGuestProfile(); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTest, - ShouldShowAtLaunch_MultipleProfiles_TwoActive_Disabled) { - TestingProfile* profile1 = - testing_profile_manager()->CreateTestingProfile("profile1"); - GetProfileAttributes(profile1)->SetActiveTimeToNow(); - TestingProfile* profile2 = - testing_profile_manager()->CreateTestingProfile("profile2"); - GetProfileAttributes(profile2)->SetActiveTimeToNow(); - local_state()->SetBoolean(prefs::kBrowserShowProfilePickerOnStartup, false); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTest, ShouldShowAtLaunch_MultipleProfiles_Inactive) { - testing_profile_manager()->CreateTestingProfile("profile1"); - testing_profile_manager()->CreateTestingProfile("profile2"); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTest, ShouldShowAtLaunch_MultipleProfiles_Expired) { - TestingProfile* profile1 = - testing_profile_manager()->CreateTestingProfile("profile1"); - GetProfileAttributes(profile1)->SetActiveTimeToNow(); - TestingProfile* profile2 = - testing_profile_manager()->CreateTestingProfile("profile2"); - GetProfileAttributes(profile2)->SetActiveTimeToNow(); - // Should be outside of the activity time threshold. - task_environment()->FastForwardBy(base::TimeDelta::FromDays(29)); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTest, ShouldShowAtLaunch_MultipleProfiles_OneActive) { - TestingProfile* profile1 = - testing_profile_manager()->CreateTestingProfile("profile1"); - GetProfileAttributes(profile1)->SetActiveTimeToNow(); - testing_profile_manager()->CreateTestingProfile("profile2"); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTest, ShouldShowAtLaunch_SingleProfile) { - testing_profile_manager()->CreateTestingProfile("profile1"); - local_state()->SetBoolean(prefs::kBrowserProfilePickerShown, true); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -} - -class ProfilePickerTestEphemeralGuest : public ProfilePickerTest { - public: - ProfilePickerTestEphemeralGuest() { - feature_list_.InitAndEnableFeature( - features::kEnableEphemeralGuestProfilesOnDesktop); - } - - private: - base::test::ScopedFeatureList feature_list_; -}; - -TEST_F(ProfilePickerTestEphemeralGuest, - ShouldShowAtLaunch_MultipleProfiles_OneGuest) { - TestingProfile* profile1 = - testing_profile_manager()->CreateTestingProfile("profile1"); - GetProfileAttributes(profile1)->SetActiveTimeToNow(); - testing_profile_manager()->CreateTestingProfile("profile2"); - TestingProfile* guest_profile = - testing_profile_manager()->CreateGuestProfile(); - GetProfileAttributes(guest_profile)->SetActiveTimeToNow(); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -} - -TEST_F(ProfilePickerTestEphemeralGuest, - ShouldShowAtLaunch_MultipleProfiles_OneGuest_SeenPicker) { - testing_profile_manager()->CreateTestingProfile("profile1"); - testing_profile_manager()->CreateGuestProfile(); - local_state()->SetBoolean(prefs::kBrowserProfilePickerShown, true); - - EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch()); -}
diff --git a/chrome/browser/ui/startup/startup_tab_provider.h b/chrome/browser/ui/startup/startup_tab_provider.h index 03870d4..ceaea1c 100644 --- a/chrome/browser/ui/startup/startup_tab_provider.h +++ b/chrome/browser/ui/startup/startup_tab_provider.h
@@ -9,7 +9,6 @@ #include "base/gtest_prod_util.h" #include "build/build_config.h" -#include "chrome/browser/first_run/first_run.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" #include "chrome/browser/ui/startup/startup_tab.h"
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc index 06e28b9..5001859 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.cc +++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -34,19 +34,24 @@ TabMenuModel::~TabMenuModel() {} void TabMenuModel::Build(TabStripModel* tab_strip, int index) { - std::vector<int> affected_indices = - tab_strip->IsTabSelected(index) - ? tab_strip->selection_model().selected_indices() - : std::vector<int>{index}; - int num_affected_tabs = affected_indices.size(); + std::vector<int> indices; + if (tab_strip->IsTabSelected(index)) { + const ui::ListSelectionModel::SelectedIndices& sel = + tab_strip->selection_model().selected_indices(); + indices = std::vector<int>(sel.begin(), sel.end()); + } else { + indices = {index}; + } + + int num_tabs = indices.size(); AddItemWithStringId(TabStripModel::CommandNewTabToRight, IDS_TAB_CXMENU_NEWTABTORIGHT); if (base::FeatureList::IsEnabled(reading_list::switches::kReadLater)) { - AddItem(TabStripModel::CommandAddToReadLater, - l10n_util::GetPluralStringFUTF16(IDS_TAB_CXMENU_READ_LATER, - num_affected_tabs)); + AddItem( + TabStripModel::CommandAddToReadLater, + l10n_util::GetPluralStringFUTF16(IDS_TAB_CXMENU_READ_LATER, num_tabs)); SetEnabledAt(GetItemCount() - 1, - tab_strip->IsReadLaterSupportedForAny(affected_indices)); + tab_strip->IsReadLaterSupportedForAny(indices)); } if (ExistingTabGroupSubMenuModel::ShouldShowSubmenu(tab_strip, index)) { // Create submenu with existing groups @@ -55,18 +60,18 @@ index); AddSubMenu(TabStripModel::CommandAddToExistingGroup, l10n_util::GetPluralStringFUTF16(IDS_TAB_CXMENU_ADD_TAB_TO_GROUP, - num_affected_tabs), + num_tabs), add_to_existing_group_submenu_.get()); SetIsNewFeatureAt(GetItemCount() - 1, true); } else { AddItem(TabStripModel::CommandAddToNewGroup, l10n_util::GetPluralStringFUTF16( - IDS_TAB_CXMENU_ADD_TAB_TO_NEW_GROUP, num_affected_tabs)); + IDS_TAB_CXMENU_ADD_TAB_TO_NEW_GROUP, num_tabs)); SetIsNewFeatureAt(GetItemCount() - 1, true); } - for (size_t index = 0; index < affected_indices.size(); index++) { - if (tab_strip->GetTabGroupForTab(affected_indices[index]).has_value()) { + for (const auto& selection : indices) { + if (tab_strip->GetTabGroupForTab(selection).has_value()) { AddItemWithStringId(TabStripModel::CommandRemoveFromGroup, IDS_TAB_CXMENU_REMOVE_TAB_FROM_GROUP); break; @@ -80,12 +85,12 @@ index); AddSubMenu(TabStripModel::CommandMoveToExistingWindow, l10n_util::GetPluralStringFUTF16( - IDS_TAB_CXMENU_MOVETOANOTHERWINDOW, num_affected_tabs), + IDS_TAB_CXMENU_MOVETOANOTHERWINDOW, num_tabs), add_to_existing_window_submenu_.get()); } else { AddItem(TabStripModel::CommandMoveTabsToNewWindow, l10n_util::GetPluralStringFUTF16( - IDS_TAB_CXMENU_MOVE_TABS_TO_NEW_WINDOW, num_affected_tabs)); + IDS_TAB_CXMENU_MOVE_TABS_TO_NEW_WINDOW, num_tabs)); } AddSeparator(ui::NORMAL_SEPARATOR); @@ -103,13 +108,12 @@ IDS_TAB_CXMENU_FOCUS_THIS_TAB); } } - const bool will_mute = - !chrome::AreAllSitesMuted(*tab_strip, affected_indices); + const bool will_mute = !chrome::AreAllSitesMuted(*tab_strip, indices); AddItem(TabStripModel::CommandToggleSiteMuted, will_mute ? l10n_util::GetPluralStringFUTF16( - IDS_TAB_CXMENU_SOUND_MUTE_SITE, num_affected_tabs) + IDS_TAB_CXMENU_SOUND_MUTE_SITE, num_tabs) : l10n_util::GetPluralStringFUTF16( - IDS_TAB_CXMENU_SOUND_UNMUTE_SITE, num_affected_tabs)); + IDS_TAB_CXMENU_SOUND_UNMUTE_SITE, num_tabs)); if (send_tab_to_self::ShouldOfferFeature( tab_strip->GetWebContentsAt(index))) { AddSeparator(ui::NORMAL_SEPARATOR);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 9da5baa..04ef938 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -469,7 +469,8 @@ if (!selection_model_.empty()) { // The active tab was removed, but there is still something selected. // Move the active and anchor to the first selected index. - selection_model_.set_active(selection_model_.selected_indices()[0]); + selection_model_.set_active( + *selection_model_.selected_indices().begin()); selection_model_.set_anchor(selection_model_.active()); } else { DCHECK(next_selected_index.has_value()); @@ -626,12 +627,12 @@ int total_pinned_count = IndexOfFirstNonPinnedTab(); int selected_pinned_count = 0; - int selected_count = - static_cast<int>(selection_model_.selected_indices().size()); - for (int i = 0; i < selected_count && - IsTabPinned(selection_model_.selected_indices()[i]); - ++i) { - selected_pinned_count++; + const ui::ListSelectionModel::SelectedIndices& selected_indices = + selection_model_.selected_indices(); + int selected_count = static_cast<int>(selected_indices.size()); + for (auto selection : selected_indices) { + if (IsTabPinned(selection)) + selected_pinned_count++; } // To maintain that all pinned tabs occur before non-pinned tabs we move them @@ -886,7 +887,7 @@ new_model.set_anchor(index); if (new_model.active() == index || new_model.active() == ui::ListSelectionModel::kUnselectedIndex) - new_model.set_active(new_model.selected_indices()[0]); + new_model.set_active(*new_model.selected_indices().begin()); } else { new_model.AddIndexToSelection(index); new_model.set_anchor(index); @@ -1015,8 +1016,10 @@ void TabStripModel::CloseSelectedTabs() { ReentrancyCheck reentrancy_check(&reentrancy_guard_); + const ui::ListSelectionModel::SelectedIndices& sel = + selection_model_.selected_indices(); InternalCloseTabs( - GetWebContentsesByIndices(selection_model_.selected_indices()), + GetWebContentsesByIndices(std::vector<int>(sel.begin(), sel.end())), CLOSE_CREATE_HISTORICAL_TAB | CLOSE_USER_GESTURE); } @@ -1616,7 +1619,9 @@ std::vector<int> TabStripModel::GetIndicesForCommand(int index) const { if (!IsTabSelected(index)) return {index}; - return selection_model_.selected_indices(); + const ui::ListSelectionModel::SelectedIndices& sel = + selection_model_.selected_indices(); + return std::vector<int>(sel.begin(), sel.end()); } std::vector<int> TabStripModel::GetIndicesClosedByCommand( @@ -1628,7 +1633,7 @@ int last_unclosed_tab = -1; if (id == CommandCloseTabsToRight) { last_unclosed_tab = - is_selected ? selection_model_.selected_indices().back() : index; + is_selected ? *selection_model_.selected_indices().rbegin() : index; } // NOTE: callers expect the vector to be sorted in descending order. @@ -1969,29 +1974,33 @@ start + length <= selection_model_.selected_indices().size()); size_t end = start + length; int count_before_index = 0; - for (size_t i = start; i < end && selection_model_.selected_indices()[i] < - index + count_before_index; - ++i) { - count_before_index++; + const ui::ListSelectionModel::SelectedIndices& sel = + selection_model_.selected_indices(); + auto indices = std::vector<int>(sel.begin(), sel.end()); + + for (size_t i = start; i < end; ++i) { + if (indices[i] < index + count_before_index) + count_before_index++; } // First move those before index. Any tabs before index end up moving in the // selection model so we use start each time through. int target_index = index + count_before_index; size_t tab_index = start; - while (tab_index < end && - selection_model_.selected_indices()[start] < index) { - MoveWebContentsAtImpl(selection_model_.selected_indices()[start], - target_index - 1, false); + while (tab_index < end && indices[start] < index) { + MoveWebContentsAtImpl(indices[start], target_index - 1, false); + // It is necessary to re-populate selected indices because + // MoveWebContetsAtImpl mutates selection_model_. + const auto& new_sel = selection_model_.selected_indices(); + indices = std::vector<int>(new_sel.begin(), new_sel.end()); tab_index++; } // Then move those after the index. These don't result in reordering the - // selection. + // selection, therefore there is no need to repopulate indices. while (tab_index < end) { - if (selection_model_.selected_indices()[tab_index] != target_index) { - MoveWebContentsAtImpl(selection_model_.selected_indices()[tab_index], - target_index, false); + if (indices[tab_index] != target_index) { + MoveWebContentsAtImpl(indices[tab_index], target_index, false); } tab_index++; target_index++;
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc index b3eaf7e7..8de7b1b 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -447,7 +447,7 @@ ASSERT_TRUE(base::StringToInt(sel, &value)); selection_model.AddIndexToSelection(value); } - selection_model.set_active(selection_model.selected_indices()[0]); + selection_model.set_active(*selection_model.selected_indices().begin()); model->SetSelectionFromModel(selection_model); }
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.cc b/chrome/browser/ui/thumbnails/thumbnail_image.cc index 3a8e8433..32730e140 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_image.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_image.cc
@@ -82,12 +82,18 @@ } void ThumbnailImage::ClearData() { - // TODO(collinbaker): Update this to notify the observers that the data has - // changed. It may be necessary to re-engineer them to accept empty/invalid - // data. crbug.com/1152894 + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // TODO(crbug.com/1163121): Update this to notify the observers that the data + // has changed. It may be necessary to re-engineer them to accept + // empty/invalid data. crbug.com/1152894 if (!data_) return; - data_->data.clear(); + + // TODO(crbug.com/1163121): Cancel existing thumbnail request. If + // called after ConvertJPEGDataToImageSkiaAndNotifyObservers() but + // before observers get notified, the observers will receive the stale + // thumbnail. data_.reset(); } @@ -121,6 +127,8 @@ } bool ThumbnailImage::ConvertJPEGDataToImageSkiaAndNotifyObservers() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!data_) { if (async_operation_finished_callback_) async_operation_finished_callback_.Run();
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.h b/chrome/browser/ui/thumbnails/thumbnail_image.h index 9b67c4f..dbad55c 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_image.h +++ b/chrome/browser/ui/thumbnails/thumbnail_image.h
@@ -132,6 +132,10 @@ Delegate* delegate_; + // This is a scoped_refptr to immutable data. Once set, the wrapped + // data must not be modified; it is referenced by other threads. + // |data_| itself can be changed as this does not affect references to + // the old data. CompressedThumbnailData data_; base::ObserverList<Observer> observers_;
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc b/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc index 93b7ed7c..308715a 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc
@@ -280,3 +280,17 @@ image->RequestCompressedThumbnailData(); EXPECT_EQ(count_before_request + 1, observer.new_compressed_count()); } + +TEST_F(ThumbnailImageTest, ClearThumbnailWhileNotifyingObservers) { + auto image = base::MakeRefCounted<ThumbnailImage>(this); + TestThumbnailImageObserver observer; + observer.scoped_observer()->Add(image.get()); + + SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight); + image->AssignSkBitmap(bitmap); + observer.WaitForImage(); + + image->RequestThumbnailImage(); + image->ClearData(); + observer.WaitForImage(); +}
diff --git a/chrome/browser/ui/translate/translate_bubble_model.h b/chrome/browser/ui/translate/translate_bubble_model.h index 5a1f7c0..f84aa9b 100644 --- a/chrome/browser/ui/translate/translate_bubble_model.h +++ b/chrome/browser/ui/translate/translate_bubble_model.h
@@ -8,6 +8,7 @@ #include <string> #include "base/strings/string16.h" +#include "components/translate/core/browser/translate_metrics_logger_impl.h" #include "components/translate/core/common/translate_errors.h" // The model for the Translate bubble UX. This manages the user's manipulation @@ -123,6 +124,10 @@ // True if the site of the current page can be blocklisted. virtual bool CanBlocklistSite() = 0; + + // Reports a high level UI interaction to the centralzied + // TranslateMetricsLogger. + virtual void ReportUIInteraction(translate::UIInteraction ui_interaction) = 0; }; #endif // CHROME_BROWSER_UI_TRANSLATE_TRANSLATE_BUBBLE_MODEL_H_
diff --git a/chrome/browser/ui/translate/translate_bubble_model_impl.cc b/chrome/browser/ui/translate/translate_bubble_model_impl.cc index 78c71b3..0293493 100644 --- a/chrome/browser/ui/translate/translate_bubble_model_impl.cc +++ b/chrome/browser/ui/translate/translate_bubble_model_impl.cc
@@ -151,3 +151,8 @@ ui_delegate_->GetTargetLanguageCode() == language_state.current_language(); } + +void TranslateBubbleModelImpl::ReportUIInteraction( + translate::UIInteraction ui_interaction) { + ui_delegate_->ReportUIInteraction(ui_interaction); +}
diff --git a/chrome/browser/ui/translate/translate_bubble_model_impl.h b/chrome/browser/ui/translate/translate_bubble_model_impl.h index c8586d6..9cc6f62 100644 --- a/chrome/browser/ui/translate/translate_bubble_model_impl.h +++ b/chrome/browser/ui/translate/translate_bubble_model_impl.h
@@ -54,6 +54,7 @@ void OnBubbleClosing() override; bool IsPageTranslatedInCurrentLanguages() const override; bool CanBlocklistSite() override; + void ReportUIInteraction(translate::UIInteraction ui_interaction) override; private: std::unique_ptr<translate::TranslateUIDelegate> ui_delegate_;
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc index f6c4adb..bc1f565 100644 --- a/chrome/browser/ui/views/download/download_item_view.cc +++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -188,6 +188,14 @@ return base::FeatureList::IsEnabled(safe_browsing::kUseNewDownloadWarnings); } +int GetFilenameStyle(const views::Label& label) { +#if !defined(OS_LINUX) && !defined(OS_CHROMEOS) + if (UseNewWarnings()) + return STYLE_EMPHASIZED; +#endif + return label.GetTextStyle(); +} + int GetFilenameStyle(const views::StyledLabel& label) { #if !defined(OS_LINUX) && !defined(OS_CHROMEOS) if (UseNewWarnings()) @@ -196,6 +204,10 @@ return label.GetDefaultTextStyle(); } +void StyleFilename(views::Label& label, size_t pos, size_t len) { + label.SetTextStyleRange(GetFilenameStyle(label), gfx::Range(pos, pos + len)); +} + void StyleFilename(views::StyledLabel& label, size_t pos, size_t len) { // Ensure the label contains a nonempty filename. if ((pos == base::string16::npos) || (len == 0)) @@ -258,7 +270,7 @@ open_button_->SetCallback(base::BindRepeating( &DownloadItemView::OpenButtonPressed, base::Unretained(this))); - file_name_label_ = AddChildView(std::make_unique<views::StyledLabel>()); + file_name_label_ = AddChildView(std::make_unique<views::Label>()); file_name_label_->SetTextContext(CONTEXT_DOWNLOAD_SHELF); file_name_label_->GetViewAccessibility().OverrideIsIgnored(true); const base::string16 filename = ElidedFilename(*file_name_label_); @@ -449,7 +461,7 @@ void DownloadItemView::OnDownloadOpened() { SetEnabled(false); - file_name_label_->SetDefaultTextStyle(views::style::STYLE_DISABLED); + file_name_label_->SetTextStyle(views::style::STYLE_DISABLED); const base::string16 filename = ElidedFilename(*file_name_label_); size_t filename_offset; file_name_label_->SetText(l10n_util::GetStringFUTF16( @@ -461,7 +473,7 @@ return; view->SetEnabled(true); auto* label = view->file_name_label_; - label->SetDefaultTextStyle(views::style::STYLE_PRIMARY); + label->SetTextStyle(views::style::STYLE_PRIMARY); const base::string16 filename = view->ElidedFilename(*label); label->SetText(filename); StyleFilename(*label, 0, filename.length()); @@ -630,7 +642,7 @@ const SkColor background_color = GetThemeProvider()->GetColor(ThemeProperties::COLOR_DOWNLOAD_SHELF); SetBackground(views::CreateSolidBackground(background_color)); - file_name_label_->SetDisplayedOnBackgroundColor(background_color); + file_name_label_->SetBackgroundColor(background_color); status_label_->SetBackgroundColor(background_color); warning_label_->SetDisplayedOnBackgroundColor(background_color); deep_scanning_label_->SetDisplayedOnBackgroundColor(background_color); @@ -696,6 +708,11 @@ UpdateAccessibleAlert(model_->GetWarningText(unelided_filename, &ignore)); accessible_alert_timer_.Stop(); } + } else if (is_mixed_content(mode_)) { + announce_accessible_alert_soon_ = true; + UpdateAccessibleAlert(l10n_util::GetStringFUTF16( + IDS_PROMPT_DOWNLOAD_MIXED_CONTENT_BLOCKED_ACCESSIBLE_ALERT, + unelided_filename)); } else if (mode_ == Mode::kDeepScanning) { UpdateAccessibleAlert(l10n_util::GetStringFUTF16( IDS_DEEP_SCANNING_ACCESSIBLE_ALERT, unelided_filename)); @@ -1078,6 +1095,14 @@ } base::string16 DownloadItemView::ElidedFilename( + const views::Label& label) const { + const gfx::FontList& font_list = + views::style::GetFont(CONTEXT_DOWNLOAD_SHELF, GetFilenameStyle(label)); + return gfx::ElideFilename(model_->GetFileNameToReportUser(), font_list, + kTextWidth); +} + +base::string16 DownloadItemView::ElidedFilename( const views::StyledLabel& label) const { const gfx::FontList& font_list = views::style::GetFont(CONTEXT_DOWNLOAD_SHELF, GetFilenameStyle(label));
diff --git a/chrome/browser/ui/views/download/download_item_view.h b/chrome/browser/ui/views/download/download_item_view.h index 47114be..536f6f2b 100644 --- a/chrome/browser/ui/views/download/download_item_view.h +++ b/chrome/browser/ui/views/download/download_item_view.h
@@ -175,6 +175,7 @@ // Returns the file name to report to the user. It might be elided to fit into // the text width. |label| dictates the default text style. + base::string16 ElidedFilename(const views::Label& label) const; base::string16 ElidedFilename(const views::StyledLabel& label) const; // Returns the Y coordinate that centers |element_height| within the current @@ -252,7 +253,7 @@ // used, so that we can detect a change in the path and reload the icon. base::FilePath file_path_; - views::StyledLabel* file_name_label_; + views::Label* file_name_label_; views::Label* status_label_; views::StyledLabel* warning_label_; views::StyledLabel* deep_scanning_label_;
diff --git a/chrome/browser/ui/views/frame/DEPS b/chrome/browser/ui/views/frame/DEPS index 3d307d1..1ab82166 100644 --- a/chrome/browser/ui/views/frame/DEPS +++ b/chrome/browser/ui/views/frame/DEPS
@@ -3,6 +3,9 @@ "browser_non_client_frame_view_chromeos\.*": [ "+ash", ], + "browser_frame\.cc": [ + "+components/full_restore/full_restore_utils.h", + ], "browser_frame_ash\.*": [ "+ash", ],
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc index 8c705f9..e31d4e6 100644 --- a/chrome/browser/ui/views/frame/browser_frame.cc +++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -36,6 +36,7 @@ #include "ui/views/widget/native_widget.h" #if BUILDFLAG(IS_CHROMEOS_ASH) +#include "components/full_restore/full_restore_utils.h" #include "components/user_manager/user_manager.h" #endif @@ -81,6 +82,10 @@ views::Widget::InitParams params = native_browser_frame_->GetWidgetParams(); params.name = "BrowserFrame"; params.delegate = browser_view_; +#if BUILDFLAG(IS_CHROMEOS_ASH) + params.init_properties_container.SetProperty( + full_restore::kWindowIdKey, browser_view_->browser()->session_id().id()); +#endif if (browser_view_->browser()->is_type_normal() || browser_view_->browser()->is_type_devtools() || browser_view_->browser()->is_type_app()) {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc index d48ea067..fe8503b 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc
@@ -128,10 +128,10 @@ // Initializing the TabIconView is expensive, so only do it if we need to. if (browser_view()->ShouldShowWindowIcon()) { - window_icon_ = new TabIconView(this, views::Button::PressedCallback()); - window_icon_->set_is_light(true); - AddChildView(window_icon_); - window_icon_->Update(); + AddChildView(views::Builder<TabIconView>() + .CopyAddressTo(&window_icon_) + .SetModel(this) + .Build()); } UpdateProfileIcons();
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index fd6e215..25f86b55 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -95,14 +95,16 @@ if (browser_view->CanShowWindowIcon()) { InitThrobberIcons(); - window_icon_ = new TabIconView(this, views::Button::PressedCallback()); - window_icon_->set_is_light(true); - window_icon_->SetID(VIEW_ID_WINDOW_ICON); - // Stop the icon from intercepting clicks intended for the HTSYSMENU region - // of the window. Even though it does nothing on click, it will still - // prevent us from giving the event back to Windows to handle properly. - window_icon_->SetCanProcessEventsWithinSubtree(false); - AddChildView(window_icon_); + AddChildView(views::Builder<TabIconView>() + .CopyAddressTo(&window_icon_) + .SetModel(this) + .SetID(VIEW_ID_WINDOW_ICON) + // Stop the icon from intercepting clicks intended for the + // HTSYSMENU region of the window. Even though it does + // nothing on click, it will still prevent us from giving + // the event back to Windows to handle properly. + .SetCanProcessEventsWithinSubtree(false) + .Build()); } web_app::AppBrowserController* controller = @@ -368,7 +370,8 @@ } bool GlassBrowserFrameView::ShouldTabIconViewAnimate() const { - DCHECK(ShouldShowWindowIcon(TitlebarType::kCustom)); + if (!ShouldShowWindowIcon(TitlebarType::kCustom)) + return false; content::WebContents* current_tab = browser_view()->GetActiveWebContents(); return current_tab && current_tab->IsLoading(); }
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index c773c7d..f9b51dc 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -179,13 +179,14 @@ // Initializing the TabIconView is expensive, so only do it if we need to. if (browser_view()->ShouldShowWindowIcon()) { - window_icon_ = new TabIconView( - this, base::BindRepeating(&OpaqueBrowserFrameView::WindowIconPressed, - base::Unretained(this))); - window_icon_->set_is_light(true); - window_icon_->SetID(VIEW_ID_WINDOW_ICON); - AddChildView(window_icon_); - window_icon_->Update(); + AddChildView(views::Builder<TabIconView>() + .CopyAddressTo(&window_icon_) + .SetModel(this) + .SetCallback(base::BindRepeating( + &OpaqueBrowserFrameView::WindowIconPressed, + base::Unretained(this))) + .SetID(VIEW_ID_WINDOW_ICON) + .Build()); } web_app::AppBrowserController* controller =
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc index 69f85552..c04c731bd 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -151,10 +151,10 @@ } void AddWindowTitleIcons() { - tab_icon_view_ = new TabIconView(nullptr, views::Button::PressedCallback()); - tab_icon_view_->set_is_light(true); - tab_icon_view_->SetID(VIEW_ID_WINDOW_ICON); - root_view_->AddChildView(tab_icon_view_); + root_view_->AddChildView(views::Builder<TabIconView>() + .CopyAddressTo(&tab_icon_view_) + .SetID(VIEW_ID_WINDOW_ICON) + .Build()); window_title_ = new views::Label(delegate_->GetWindowTitle()); window_title_->SetVisible(delegate_->ShouldShowWindowTitle());
diff --git a/chrome/browser/ui/views/login_view.cc b/chrome/browser/ui/views/login_view.cc index 4e40a7d..b3433d80 100644 --- a/chrome/browser/ui/views/login_view.cc +++ b/chrome/browser/ui/views/login_view.cc
@@ -15,6 +15,7 @@ #include "ui/views/controls/label.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/layout/grid_layout.h" +#include "ui/views/metadata/metadata_impl_macros.h" namespace { @@ -112,6 +113,7 @@ http_auth_manager_ = nullptr; } -const char* LoginView::GetClassName() const { - return "LoginView"; -} +BEGIN_METADATA(LoginView, views::View) +ADD_READONLY_PROPERTY_METADATA(base::string16, Username) +ADD_READONLY_PROPERTY_METADATA(base::string16, Password) +END_METADATA
diff --git a/chrome/browser/ui/views/login_view.h b/chrome/browser/ui/views/login_view.h index 5ce4b61..a06e84f 100644 --- a/chrome/browser/ui/views/login_view.h +++ b/chrome/browser/ui/views/login_view.h
@@ -5,10 +5,10 @@ #ifndef CHROME_BROWSER_UI_VIEWS_LOGIN_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_LOGIN_VIEW_H_ -#include "base/macros.h" #include "base/strings/string16.h" #include "chrome/browser/ui/login/login_handler.h" #include "components/password_manager/core/browser/http_auth_observer.h" +#include "ui/views/metadata/metadata_header_macros.h" #include "ui/views/view.h" namespace views { @@ -24,12 +24,15 @@ class LoginView : public views::View, public password_manager::HttpAuthObserver { public: + METADATA_HEADER(LoginView); // |login_model_data->model| is observed for the entire lifetime of the // LoginView. Therefore |login_model_data->model| should not be destroyed // before the LoginView object. |login_model_data| may be null. LoginView(const base::string16& authority, const base::string16& explanation, LoginHandler::LoginModelData* login_model_data); + LoginView(const LoginView&) = delete; + LoginView& operator=(const LoginView&) = delete; ~LoginView() override; // Access the data in the username/password text fields. @@ -45,9 +48,6 @@ views::View* GetInitiallyFocusedView(); private: - // views::View: - const char* GetClassName() const override; - // Non-owning refs to the input text fields. views::Textfield* username_field_; views::Textfield* password_field_; @@ -55,8 +55,6 @@ // If not null, points to a model we need to notify of our own destruction // so it doesn't try and access this when its too late. password_manager::HttpAuthManager* http_auth_manager_; - - DISALLOW_COPY_AND_ASSIGN(LoginView); }; #endif // CHROME_BROWSER_UI_VIEWS_LOGIN_VIEW_H_
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.cc b/chrome/browser/ui/views/page_action/pwa_install_view.cc index 42b2a50..07f5f0f 100644 --- a/chrome/browser/ui/views/page_action/pwa_install_view.cc +++ b/chrome/browser/ui/views/page_action/pwa_install_view.cc
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/banners/app_banner_manager.h" +#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/user_education/feature_promo_controller.h" #include "chrome/browser/ui/user_education/feature_promo_text_replacements.h"
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc index 606ea03..c876d10 100644 --- a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc +++ b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
@@ -11,6 +11,7 @@ #include "base/test/scoped_feature_list.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/banners/test_app_banner_manager_desktop.h" +#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_dialogs.h"
diff --git a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc index 154ddfd..ecf5e225 100644 --- a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc
@@ -13,7 +13,6 @@ #include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" -#include "chrome/browser/engagement/site_engagement_score.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/history/history_test_utils.h" @@ -39,6 +38,7 @@ #include "components/security_interstitials/core/common_string_util.h" #include "components/security_state/core/features.h" #include "components/security_state/core/security_state.h" +#include "components/site_engagement/content/site_engagement_score.h" #include "components/strings/grit/components_chromium_strings.h" #include "components/strings/grit/components_strings.h" #include "components/ukm/test_ukm_recorder.h"
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.cc b/chrome/browser/ui/views/profiles/profile_picker_view.cc index 9a92c63..dfd0295d 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_view.cc
@@ -44,7 +44,6 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/google_chrome_strings.h" #include "components/keep_alive_registry/keep_alive_types.h" -#include "components/prefs/pref_service.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/startup_metric_utils/browser/startup_metric_utils.h" #include "content/public/browser/browser_context.h" @@ -324,9 +323,6 @@ GetWidget()->Show(); state_ = kReady; - PrefService* prefs = g_browser_process->local_state(); - prefs->SetBoolean(prefs::kBrowserProfilePickerShown, true); - if (entry_point == ProfilePicker::EntryPoint::kOnStartup) { DCHECK(!creation_time_on_startup_.is_null()); base::UmaHistogramTimes("ProfilePicker.StartupTime.WebViewCreated",
diff --git a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc index 2408e2c..45a7cd3 100644 --- a/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc +++ b/chrome/browser/ui/views/profiles/signin_view_controller_delegate_views.cc
@@ -262,7 +262,7 @@ if (should_show_close_button_) { GetBubbleFrameView()->SetBubbleBorder( std::make_unique<views::BubbleBorder>( - views::BubbleBorder::NONE, views::BubbleBorder::BIG_SHADOW, + views::BubbleBorder::NONE, views::BubbleBorder::SMALL_SHADOW, SK_ColorWHITE)); } constrained_window::ShowModalDialog(
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc index 821ee382..b295801 100644 --- a/chrome/browser/ui/views/status_bubble_views.cc +++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/i18n/rtl.h" #include "base/location.h" -#include "base/macros.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -41,6 +40,8 @@ #include "ui/views/controls/label.h" #include "ui/views/controls/scrollbar/scroll_bar_views.h" #include "ui/views/layout/fill_layout.h" +#include "ui/views/metadata/metadata_header_macros.h" +#include "ui/views/metadata/metadata_impl_macros.h" #include "ui/views/style/typography.h" #include "ui/views/widget/root_view.h" #include "ui/views/widget/widget.h" @@ -101,6 +102,8 @@ StatusViewAnimation(StatusView* status_view, float opacity_start, float opacity_end); + StatusViewAnimation(const StatusViewAnimation&) = delete; + StatusViewAnimation& operator=(const StatusViewAnimation&) = delete; ~StatusViewAnimation() override; float GetCurrentOpacity(); @@ -119,8 +122,6 @@ // a value between 0 and 1. float opacity_start_; float opacity_end_; - - DISALLOW_COPY_AND_ASSIGN(StatusViewAnimation); }; // StatusBubbleViews::StatusView ----------------------------------------------- @@ -129,37 +130,45 @@ // fading in or out the bubble as required. class StatusBubbleViews::StatusView : public views::View { public: + METADATA_HEADER(StatusView); + // The bubble can be in one of many states: - enum BubbleState { - BUBBLE_HIDDEN, // Entirely BUBBLE_HIDDEN. - BUBBLE_HIDING_FADE, // In a fade-out transition. - BUBBLE_HIDING_TIMER, // Waiting before a fade-out. - BUBBLE_SHOWING_TIMER, // Waiting before a fade-in. - BUBBLE_SHOWING_FADE, // In a fade-in transition. - BUBBLE_SHOWN // Fully visible. + enum class BubbleState { + kHidden, + kPreFadeIn, + kFadingIn, + kShown, + kPreFadeOut, + kFadingOut, }; - enum BubbleStyle { - STYLE_BOTTOM, - STYLE_FLOATING, - STYLE_STANDARD, - STYLE_STANDARD_RIGHT + enum class BubbleStyle { + kBottom, + kFloating, + kStandard, + kStandardRight, }; explicit StatusView(StatusBubbleViews* status_bubble); + StatusView(const StatusView&) = delete; + StatusView& operator=(const StatusView&) = delete; ~StatusView() override; // views::View: gfx::Insets GetInsets() const override; - // Set the bubble text, or hide the bubble if |text| is an empty string. - // Triggers an animation sequence to display if |should_animate_open| is true. - void SetText(const base::string16& text, bool should_animate_open); + const base::string16& GetText() const; + void SetText(const base::string16& text); - BubbleState state() const { return state_; } - BubbleStyle style() const { return style_; } + BubbleState GetState() const { return state_; } + + BubbleStyle GetStyle() const { return style_; } void SetStyle(BubbleStyle style); + // If |text| is empty, hides the bubble; otherwise, sets the bubble text to + // |text| and shows the bubble. + void AnimateForText(const base::string16& text); + // Show the bubble instantly. void ShowInstantly(); @@ -201,11 +210,10 @@ void SetTextLabelColors(views::Label* label); // views::View: - const char* GetClassName() const override; void OnPaint(gfx::Canvas* canvas) override; - BubbleState state_ = BUBBLE_HIDDEN; - BubbleStyle style_ = STYLE_STANDARD; + BubbleState state_ = BubbleState::kHidden; + BubbleStyle style_ = BubbleStyle::kStandard; std::unique_ptr<StatusViewAnimation> animation_; @@ -221,11 +229,10 @@ base::OneShotTimer destroy_popup_timer_; base::WeakPtrFactory<StatusBubbleViews::StatusView> timer_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(StatusView); }; +using StatusView = StatusBubbleViews::StatusView; -StatusBubbleViews::StatusView::StatusView(StatusBubbleViews* status_bubble) +StatusView::StatusView(StatusBubbleViews* status_bubble) : status_bubble_(status_bubble) { animation_ = std::make_unique<StatusViewAnimation>(this, 0, 0); @@ -239,48 +246,59 @@ text_ = AddChildView(std::move(text)); } -StatusBubbleViews::StatusView::~StatusView() { +StatusView::~StatusView() { animation_->Stop(); CancelTimer(); } -gfx::Insets StatusBubbleViews::StatusView::GetInsets() const { +gfx::Insets StatusView::GetInsets() const { return gfx::Insets(kShadowThickness, kShadowThickness + kTextHorizPadding); } -void StatusBubbleViews::StatusView::SetText(const base::string16& text, - bool should_animate_open) { +const base::string16& StatusView::GetText() const { + return text_->GetText(); +} + +void StatusView::SetText(const base::string16& text) { + if (text == GetText()) + return; + + text_->SetText(text); + OnPropertyChanged(&text_, views::kPropertyEffectsNone); +} + +void StatusView::AnimateForText(const base::string16& text) { if (text.empty()) { StartHiding(); } else { - text_->SetText(text); - if (should_animate_open) - StartShowing(); + SetText(text); + StartShowing(); } } -void StatusBubbleViews::StatusView::SetStyle(BubbleStyle style) { - if (style_ != style) { - style_ = style; - SchedulePaint(); - } +void StatusView::SetStyle(BubbleStyle style) { + if (style_ == style) + return; + + style_ = style; + OnPropertyChanged(&style_, views::kPropertyEffectsPaint); } -void StatusBubbleViews::StatusView::ShowInstantly() { +void StatusView::ShowInstantly() { animation_->Stop(); CancelTimer(); SetOpacity(1.0); - state_ = BUBBLE_SHOWN; + state_ = BubbleState::kShown; GetWidget()->ShowInactive(); destroy_popup_timer_.Stop(); } -void StatusBubbleViews::StatusView::HideInstantly() { +void StatusView::HideInstantly() { animation_->Stop(); CancelTimer(); SetOpacity(0.0); - text_->SetText(base::string16()); - state_ = BUBBLE_HIDDEN; + SetText(base::string16()); + state_ = BubbleState::kHidden; // Don't orderOut: the window on macOS. Doing so for a child window requires // it to be detached/reattached, which may trigger a space switch. Instead, // just leave the window fully transparent and unclickable. @@ -293,68 +311,64 @@ &StatusBubbleViews::DestroyPopup); } -void StatusBubbleViews::StatusView::ResetTimer() { - if (state_ == BUBBLE_SHOWING_TIMER) { +void StatusView::ResetTimer() { + if (state_ == BubbleState::kPreFadeIn) { // We hadn't yet begun showing anything when we received a new request // for something to show, so we start from scratch. RestartTimer(kShowDelay); } } -void StatusBubbleViews::StatusView::SetOpacity(float opacity) { +void StatusView::SetOpacity(float opacity) { GetWidget()->SetOpacity(opacity); } -void StatusBubbleViews::StatusView::OnAnimationEnded() { - if (state_ == BUBBLE_SHOWING_FADE) - state_ = BUBBLE_SHOWN; - else if (state_ == BUBBLE_HIDING_FADE) +void StatusView::OnAnimationEnded() { + if (state_ == BubbleState::kFadingIn) + state_ = BubbleState::kShown; + else if (state_ == BubbleState::kFadingOut) HideInstantly(); // This view may be destroyed after calling HideInstantly. } -bool StatusBubbleViews::StatusView::IsDestroyPopupTimerRunning() const { +bool StatusView::IsDestroyPopupTimerRunning() const { return destroy_popup_timer_.IsRunning(); } -void StatusBubbleViews::StatusView::OnThemeChanged() { +void StatusView::OnThemeChanged() { views::View::OnThemeChanged(); SetTextLabelColors(text_); } -void StatusBubbleViews::StatusView::StartTimer(base::TimeDelta time) { +void StatusView::StartTimer(base::TimeDelta time) { if (timer_factory_.HasWeakPtrs()) timer_factory_.InvalidateWeakPtrs(); status_bubble_->task_runner_->PostDelayedTask( FROM_HERE, - base::BindOnce(&StatusBubbleViews::StatusView::OnTimer, - timer_factory_.GetWeakPtr()), - time); + base::BindOnce(&StatusView::OnTimer, timer_factory_.GetWeakPtr()), time); } -void StatusBubbleViews::StatusView::OnTimer() { - if (state_ == BUBBLE_HIDING_TIMER) { - state_ = BUBBLE_HIDING_FADE; +void StatusView::OnTimer() { + if (state_ == BubbleState::kPreFadeOut) { + state_ = BubbleState::kFadingOut; StartFade(1.0f, 0.0f, kHideFadeDuration); - } else if (state_ == BUBBLE_SHOWING_TIMER) { - state_ = BUBBLE_SHOWING_FADE; + } else if (state_ == BubbleState::kPreFadeIn) { + state_ = BubbleState::kFadingIn; StartFade(0.0f, 1.0f, kShowFadeDuration); } } -void StatusBubbleViews::StatusView::CancelTimer() { +void StatusView::CancelTimer() { if (timer_factory_.HasWeakPtrs()) timer_factory_.InvalidateWeakPtrs(); } -void StatusBubbleViews::StatusView::RestartTimer(base::TimeDelta delay) { +void StatusView::RestartTimer(base::TimeDelta delay) { CancelTimer(); StartTimer(delay); } -void StatusBubbleViews::StatusView::StartFade(float start, - float end, - base::TimeDelta duration) { +void StatusView::StartFade(float start, float end, base::TimeDelta duration) { animation_ = std::make_unique<StatusViewAnimation>(this, start, end); // This will also reset the currently-occurring animation. @@ -362,49 +376,49 @@ animation_->Start(); } -void StatusBubbleViews::StatusView::StartHiding() { - if (state_ == BUBBLE_SHOWN) { - state_ = BUBBLE_HIDING_TIMER; +void StatusView::StartHiding() { + if (state_ == BubbleState::kShown) { + state_ = BubbleState::kPreFadeOut; StartTimer(kHideDelay); - } else if (state_ == BUBBLE_SHOWING_FADE) { - state_ = BUBBLE_HIDING_FADE; + } else if (state_ == BubbleState::kFadingIn) { + state_ = BubbleState::kFadingOut; // Figure out where we are in the current fade. float current_opacity = animation_->GetCurrentOpacity(); // Start a fade in the opposite direction. StartFade(current_opacity, 0.0f, kHideFadeDuration * current_opacity); - } else if (state_ == BUBBLE_SHOWING_TIMER) { + } else if (state_ == BubbleState::kPreFadeIn) { HideInstantly(); // This view may be destroyed after calling HideInstantly. } } -void StatusBubbleViews::StatusView::StartShowing() { +void StatusView::StartShowing() { destroy_popup_timer_.Stop(); - if (state_ == BUBBLE_HIDDEN) { + if (state_ == BubbleState::kHidden) { GetWidget()->ShowInactive(); - state_ = BUBBLE_SHOWING_TIMER; + state_ = BubbleState::kPreFadeIn; StartTimer(kShowDelay); - } else if (state_ == BUBBLE_HIDING_TIMER) { - state_ = BUBBLE_SHOWN; + } else if (state_ == BubbleState::kPreFadeOut) { + state_ = BubbleState::kShown; CancelTimer(); - } else if (state_ == BUBBLE_HIDING_FADE) { + } else if (state_ == BubbleState::kFadingOut) { // We're partway through a fade. - state_ = BUBBLE_SHOWING_FADE; + state_ = BubbleState::kFadingIn; // Figure out where we are in the current fade. float current_opacity = animation_->GetCurrentOpacity(); // Start a fade in the opposite direction. StartFade(current_opacity, 1.0f, kShowFadeDuration * current_opacity); - } else if (state_ == BUBBLE_SHOWING_TIMER) { + } else if (state_ == BubbleState::kPreFadeIn) { // We hadn't yet begun showing anything when we received a new request // for something to show, so we start from scratch. ResetTimer(); } } -void StatusBubbleViews::StatusView::SetTextLabelColors(views::Label* text) { +void StatusView::SetTextLabelColors(views::Label* text) { const auto* theme_provider = status_bubble_->base_view()->GetThemeProvider(); SkColor bubble_color = theme_provider->GetColor(ThemeProperties::COLOR_STATUS_BUBBLE); @@ -414,11 +428,7 @@ ThemeProperties::COLOR_TAB_FOREGROUND_INACTIVE_FRAME_ACTIVE)); } -const char* StatusBubbleViews::StatusView::GetClassName() const { - return "StatusBubbleViews::StatusView"; -} - -void StatusBubbleViews::StatusView::OnPaint(gfx::Canvas* canvas) { +void StatusView::OnPaint(gfx::Canvas* canvas) { gfx::ScopedCanvas scoped(canvas); float scale = canvas->UndoDeviceScaleFactor(); const float radius = kBubbleCornerRadius * scale; @@ -429,8 +439,8 @@ // then we square the top edges. Otherwise, we square the edges based on the // position of the bubble within the window (the bubble is positioned in the // southeast corner in RTL and in the southwest corner in LTR). - if (style_ != STYLE_BOTTOM) { - if (base::i18n::IsRTL() != (style_ == STYLE_STANDARD_RIGHT)) { + if (style_ != BubbleStyle::kBottom) { + if (base::i18n::IsRTL() != (style_ == BubbleStyle::kStandardRight)) { // The text is RtL or the bubble is on the right side (but not both). // Top Left corner. @@ -445,7 +455,8 @@ // Bottom edges - Keep these squared off if the bubble is in its standard // position (sticking upward). - if (style_ != STYLE_STANDARD && style_ != STYLE_STANDARD_RIGHT) { + if (style_ != BubbleStyle::kStandard && + style_ != BubbleStyle::kStandardRight) { // Bottom Right Corner. rad[4] = radius; rad[5] = radius; @@ -466,8 +477,10 @@ // The shadow will overlap the window frame. Clip it off when the bubble is // docked. Otherwise when the bubble is floating preserve the full shadow so // the bubble looks complete. - int clip_left = style_ == STYLE_STANDARD ? shadow_thickness_pixels : 0; - int clip_right = style_ == STYLE_STANDARD_RIGHT ? shadow_thickness_pixels : 0; + int clip_left = + style_ == BubbleStyle::kStandard ? shadow_thickness_pixels : 0; + int clip_right = + style_ == BubbleStyle::kStandardRight ? shadow_thickness_pixels : 0; if (base::i18n::IsRTL()) std::swap(clip_left, clip_right); @@ -483,8 +496,8 @@ // bubble bounds by 1 DIP minus 1 pixel. Failing to do this results in drawing // further and further outside the window as the scale increases. const int inset = shadow_thickness_pixels - 1; - bubble_rect.Inset(style_ == STYLE_STANDARD_RIGHT ? 0 : inset, 0, - style_ == STYLE_STANDARD_RIGHT ? inset : 0, inset); + bubble_rect.Inset(style_ == BubbleStyle::kStandardRight ? 0 : inset, 0, + style_ == BubbleStyle::kStandardRight ? inset : 0, inset); // Align to pixel centers now that the layout is correct. bubble_rect.Inset(0.5, 0.5); @@ -514,6 +527,28 @@ canvas->sk_canvas()->drawPath(stroke_path, flags); } +DEFINE_ENUM_CONVERTERS( + StatusView::BubbleState, + {StatusView::BubbleState::kHidden, base::ASCIIToUTF16("kHidden")}, + {StatusView::BubbleState::kPreFadeIn, base::ASCIIToUTF16("kPreFadeIn")}, + {StatusView::BubbleState::kFadingIn, base::ASCIIToUTF16("kFadingIn")}, + {StatusView::BubbleState::kShown, base::ASCIIToUTF16("kShown")}, + {StatusView::BubbleState::kPreFadeOut, base::ASCIIToUTF16("kPreFadeOut")}, + {StatusView::BubbleState::kFadingOut, base::ASCIIToUTF16("kFadingOut")}) + +DEFINE_ENUM_CONVERTERS( + StatusView::BubbleStyle, + {StatusView::BubbleStyle::kBottom, base::ASCIIToUTF16("kBottom")}, + {StatusView::BubbleStyle::kFloating, base::ASCIIToUTF16("kFloating")}, + {StatusView::BubbleStyle::kStandard, base::ASCIIToUTF16("kStandard")}, + {StatusView::BubbleStyle::kStandardRight, + base::ASCIIToUTF16("kStandardRight")}) + +BEGIN_METADATA(StatusView, views::View) +ADD_PROPERTY_METADATA(base::string16, Text) +ADD_READONLY_PROPERTY_METADATA(StatusView::BubbleState, State) +ADD_PROPERTY_METADATA(StatusView::BubbleStyle, Style) +END_METADATA // StatusBubbleViews::StatusViewAnimation -------------------------------------- @@ -563,6 +598,8 @@ views::AnimationDelegateViews(status_view), status_bubble_(status_bubble), status_view_(status_view) {} + StatusViewExpander(const StatusViewExpander&) = delete; + StatusViewExpander& operator=(const StatusViewExpander&) = delete; // Manage the expansion of the bubble. void StartExpansion(const base::string16& expanded_text, @@ -588,8 +625,6 @@ // Widths at expansion start and end. int expansion_start_ = 0; int expansion_end_ = 0; - - DISALLOW_COPY_AND_ASSIGN(StatusViewExpander); }; void StatusBubbleViews::StatusViewExpander::AnimateToState(double state) { @@ -598,7 +633,7 @@ void StatusBubbleViews::StatusViewExpander::AnimationEnded( const gfx::Animation* animation) { - status_view_->SetText(expanded_text_, false); + status_view_->SetText(expanded_text_); SetBubbleWidth(expansion_end_); // WARNING: crash data seems to indicate |this| may be deleted by the time // SetBubbleWidth() returns. @@ -755,8 +790,10 @@ return; InitPopup(); - view_->SetText(!status_text_.empty() ? status_text_ : url_text_, true); - if (!status_text_.empty()) { + if (status_text_.empty()) { + view_->AnimateForText(url_text_); + } else { + view_->SetText(status_text_); SetBubbleWidth(GetStandardStatusBubbleWidth()); view_->ShowInstantly(); } @@ -777,7 +814,7 @@ if (url.is_empty() && !status_text_.empty()) { url_text_ = base::string16(); if (IsFrameVisible()) - view_->SetText(status_text_, true); + view_->AnimateForText(status_text_); return; } @@ -795,7 +832,7 @@ int unexpanded_width = std::min(url_width, GetStandardStatusBubbleWidth()); // Reset expansion state only when bubble is completely hidden. - if (view_->state() == StatusView::BUBBLE_HIDDEN) { + if (view_->GetState() == StatusView::BubbleState::kHidden) { is_expanded_ = false; url_text_ = url_formatter::ElideUrl(url, GetFont(), unexpanded_width); SetBubbleWidth(unexpanded_width); @@ -826,8 +863,8 @@ // An URL is always treated as a left-to-right string. On right-to-left UIs // we need to explicitly mark the URL as LTR to make sure it is displayed // correctly. - view_->SetText(base::i18n::GetDisplayStringInLTRDirectionality(url_text_), - true); + view_->AnimateForText( + base::i18n::GetDisplayStringInLTRDirectionality(url_text_)); } } @@ -855,9 +892,9 @@ if (view_) { view_->ResetTimer(); - if (view_->state() != StatusView::BUBBLE_HIDDEN && - view_->state() != StatusView::BUBBLE_HIDING_FADE && - view_->state() != StatusView::BUBBLE_HIDING_TIMER) { + if (view_->GetState() != StatusView::BubbleState::kHidden && + view_->GetState() != StatusView::BubbleState::kFadingOut && + view_->GetState() != StatusView::BubbleState::kPreFadeOut) { AvoidMouse(location); } } @@ -910,11 +947,11 @@ // and mate to the edges of the tab content). if (offset >= size_.height() - kShadowThickness * 2) { offset = size_.height() - kShadowThickness * 2; - view_->SetStyle(StatusView::STYLE_BOTTOM); + view_->SetStyle(StatusView::BubbleStyle::kBottom); } else if (offset > kBubbleCornerRadius / 2 - kShadowThickness) { - view_->SetStyle(StatusView::STYLE_FLOATING); + view_->SetStyle(StatusView::BubbleStyle::kFloating); } else { - view_->SetStyle(StatusView::STYLE_STANDARD); + view_->SetStyle(StatusView::BubbleStyle::kStandard); } // Check if the bubble sticks out from the monitor or will obscure @@ -926,11 +963,11 @@ if (bubble_bottom_y + offset > monitor_rect.height() || (download_shelf_is_visible_ && - (view_->style() == StatusView::STYLE_FLOATING || - view_->style() == StatusView::STYLE_BOTTOM))) { + (view_->GetStyle() == StatusView::BubbleStyle::kFloating || + view_->GetStyle() == StatusView::BubbleStyle::kBottom))) { // The offset is still too large. Move the bubble to the right and reset // Y offset_ to zero. - view_->SetStyle(StatusView::STYLE_STANDARD_RIGHT); + view_->SetStyle(StatusView::BubbleStyle::kStandardRight); offset_ = 0; // Subtract border width + bubble width. @@ -945,9 +982,9 @@ size_.width(), size_.height())); } } else if (offset_ != 0 || - view_->style() == StatusView::STYLE_STANDARD_RIGHT) { + view_->GetStyle() == StatusView::BubbleStyle::kStandardRight) { offset_ = 0; - view_->SetStyle(StatusView::STYLE_STANDARD); + view_->SetStyle(StatusView::BubbleStyle::kStandard); popup_->SetBounds(gfx::Rect(top_left.x() + position_.x(), top_left.y() + position_.y(), size_.width(), size_.height()));
diff --git a/chrome/browser/ui/views/status_bubble_views.h b/chrome/browser/ui/views/status_bubble_views.h index cc4d6e3..0e63d56 100644 --- a/chrome/browser/ui/views/status_bubble_views.h +++ b/chrome/browser/ui/views/status_bubble_views.h
@@ -32,6 +32,8 @@ // to allow users to see where hovered links point to. class StatusBubbleViews : public StatusBubble { public: + class StatusView; + // How wide the bubble's shadow is. static const int kShadowThickness; @@ -79,7 +81,6 @@ void MouseMovedAt(const gfx::Point& location, bool left_content); private: - class StatusView; class StatusViewAnimation; class StatusViewExpander;
diff --git a/chrome/browser/ui/views/tab_icon_view.cc b/chrome/browser/ui/views/tab_icon_view.cc index 6d71e986..5081b65c 100644 --- a/chrome/browser/ui/views/tab_icon_view.cc +++ b/chrome/browser/ui/views/tab_icon_view.cc
@@ -23,6 +23,7 @@ #include "ui/gfx/favicon_size.h" #include "ui/gfx/paint_throbber.h" #include "ui/native_theme/native_theme.h" +#include "ui/views/metadata/metadata_impl_macros.h" #if defined(OS_WIN) #include "chrome/browser/win/app_icon.h" @@ -67,10 +68,8 @@ } // namespace -TabIconView::TabIconView(TabIconViewModel* model, - views::Button::PressedCallback callback) - : views::MenuButton(std::move(callback)), model_(model), is_light_(false) { - // Inheriting from Button causes this View to be focusable, but it us +TabIconView::TabIconView() { + // Inheriting from Button causes this View to be focusable, but it is // purely decorative and should not be exposed as focusable in accessibility. SetFocusBehavior(FocusBehavior::NEVER); } @@ -78,8 +77,13 @@ TabIconView::~TabIconView() { } +void TabIconView::SetModel(TabIconViewModel* model) { + model_ = model; + Update(); +} + void TabIconView::Update() { - if (!model_->ShouldTabIconViewAnimate()) + if (!model_ || !model_->ShouldTabIconViewAnimate()) throbber_start_time_ = base::TimeTicks(); SchedulePaint(); @@ -89,12 +93,10 @@ if (throbber_start_time_ == base::TimeTicks()) throbber_start_time_ = base::TimeTicks::Now(); - gfx::PaintThrobberSpinning( - canvas, GetLocalBounds(), - GetNativeTheme()->GetSystemColor( - is_light_ ? ui::NativeTheme::kColorId_ThrobberLightColor - : ui::NativeTheme::kColorId_ThrobberSpinningColor), - base::TimeTicks::Now() - throbber_start_time_); + gfx::PaintThrobberSpinning(canvas, GetLocalBounds(), + GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_ThrobberLightColor), + base::TimeTicks::Now() - throbber_start_time_); } void TabIconView::PaintFavicon(gfx::Canvas* canvas, @@ -129,24 +131,22 @@ return gfx::Size(gfx::kFaviconSize, gfx::kFaviconSize); } -const char* TabIconView::GetClassName() const { - return "TabIconView"; -} - void TabIconView::PaintButtonContents(gfx::Canvas* canvas) { - bool rendered = false; + if (model_) { + if (model_->ShouldTabIconViewAnimate()) { + PaintThrobber(canvas); + return; + } - if (model_->ShouldTabIconViewAnimate()) { - rendered = true; - PaintThrobber(canvas); - } else { gfx::ImageSkia favicon = model_->GetFaviconForTabIconView(); if (!favicon.isNull()) { - rendered = true; PaintFavicon(canvas, favicon); + return; } } - if (!rendered) - PaintFavicon(canvas, DefaultFavicon::GetInstance().icon()); + PaintFavicon(canvas, DefaultFavicon::GetInstance().icon()); } + +BEGIN_METADATA(TabIconView, views::MenuButton) +END_METADATA
diff --git a/chrome/browser/ui/views/tab_icon_view.h b/chrome/browser/ui/views/tab_icon_view.h index 302c6ed..3e990c4 100644 --- a/chrome/browser/ui/views/tab_icon_view.h +++ b/chrome/browser/ui/views/tab_icon_view.h
@@ -5,9 +5,9 @@ #ifndef CHROME_BROWSER_UI_VIEWS_TAB_ICON_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_TAB_ICON_VIEW_H_ -#include "base/macros.h" #include "base/time/time.h" #include "ui/views/controls/button/menu_button.h" +#include "ui/views/metadata/metadata_header_macros.h" class TabIconViewModel; @@ -18,19 +18,20 @@ // A view to display a tab favicon or a throbber. class TabIconView : public views::MenuButton { public: - TabIconView(TabIconViewModel* model, views::Button::PressedCallback callback); + METADATA_HEADER(TabIconView); + TabIconView(); + TabIconView(const TabIconView&) = delete; + TabIconView& operator=(const TabIconView&) = delete; ~TabIconView() override; + void SetModel(TabIconViewModel* model); + // Invoke whenever the tab state changes or the throbber should update. void Update(); - // Set the throbber to the light style (for use on dark backgrounds). - void set_is_light(bool is_light) { is_light_ = is_light; } - private: // views::MenuButton: gfx::Size CalculatePreferredSize() const override; - const char* GetClassName() const override; void PaintButtonContents(gfx::Canvas* canvas) override; void PaintThrobber(gfx::Canvas* canvas); @@ -39,14 +40,15 @@ // Our model. TabIconViewModel* model_; - // Whether we should display our light or dark style. - bool is_light_; - // Time we painted the first frame of the current throbber animation, or // 0 if not painting the throbber. base::TimeTicks throbber_start_time_; - - DISALLOW_COPY_AND_ASSIGN(TabIconView); }; +BEGIN_VIEW_BUILDER(/* no export */, TabIconView, views::MenuButton) +VIEW_BUILDER_PROPERTY(TabIconViewModel*, Model) +END_VIEW_BUILDER + +DEFINE_VIEW_BUILDER(/* no export */, TabIconView) + #endif // CHROME_BROWSER_UI_VIEWS_TAB_ICON_VIEW_H_
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index d82b987..7aa242f 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -1667,9 +1667,9 @@ // The anchor/active may have been among the tabs that were dragged out. Force // the anchor/active to be valid. if (selection_model.anchor() == ui::ListSelectionModel::kUnselectedIndex) - selection_model.set_anchor(selection_model.selected_indices()[0]); + selection_model.set_anchor(*selection_model.selected_indices().begin()); if (selection_model.active() == ui::ListSelectionModel::kUnselectedIndex) - selection_model.set_active(selection_model.selected_indices()[0]); + selection_model.set_active(*selection_model.selected_indices().begin()); source_context_->GetTabStripModel()->SetSelectionFromModel(selection_model); } @@ -2169,7 +2169,7 @@ // Removing a tab from a group could change the index of the selected tabs. // Store this to move the tab back to the proper position. - const int to_index = selected[0]; + const int to_index = *selected.begin(); // All selected tabs should all be in the same group unless it is the initial // move.
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index 821116ac..c1d6ebf 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -412,6 +412,8 @@ void TranslateBubbleView::ExecuteCommand(int command_id, int event_flags) { switch (command_id) { case OptionsMenuItem::ALWAYS_TRANSLATE_LANGUAGE: + model_->ReportUIInteraction( + translate::UIInteraction::kAlwaysTranslateLanguage); should_always_translate_ = !should_always_translate_; model_->SetAlwaysTranslate(should_always_translate_); if (should_always_translate_) { @@ -427,6 +429,8 @@ break; case OptionsMenuItem::NEVER_TRANSLATE_LANGUAGE: + model_->ReportUIInteraction( + translate::UIInteraction::kNeverTranslateLanguage); should_never_translate_language_ = !should_never_translate_language_; if (should_never_translate_language_) { should_always_translate_ = false; @@ -441,6 +445,8 @@ break; case OptionsMenuItem::NEVER_TRANSLATE_SITE: + model_->ReportUIInteraction( + translate::UIInteraction::kNeverTranslateSite); should_never_translate_site_ = !should_never_translate_site_; if (should_never_translate_site_) { translate::ReportUiAction(translate::NEVER_TRANSLATE_SITE_MENU_CLICKED); @@ -471,6 +477,9 @@ views::Widget::ClosedReason::kCloseButtonClicked) { model_->DeclineTranslation(); translate::ReportUiAction(translate::CLOSE_BUTTON_CLICKED); + model_->ReportUIInteraction(translate::UIInteraction::kCloseUIExplicitly); + } else { + model_->ReportUIInteraction(translate::UIInteraction::kCloseUILostFocus); } } @@ -520,12 +529,14 @@ } void TranslateBubbleView::Translate() { + model_->ReportUIInteraction(translate::UIInteraction::kTranslate); model_->Translate(); SwitchView(TranslateBubbleModel::VIEW_STATE_TRANSLATING); translate::ReportUiAction(translate::TRANSLATE_BUTTON_CLICKED); } void TranslateBubbleView::ShowOriginal() { + model_->ReportUIInteraction(translate::UIInteraction::kRevert); model_->RevertTranslation(); SwitchView(TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE); translate::ReportUiAction(translate::SHOW_ORIGINAL_BUTTON_CLICKED); @@ -552,6 +563,7 @@ } void TranslateBubbleView::SourceLanguageChanged() { + model_->ReportUIInteraction(translate::UIInteraction::kChangeSourceLanguage); model_->UpdateOriginalLanguageIndex( source_language_combobox_->GetSelectedIndex() - 1); UpdateAdvancedView(); @@ -559,6 +571,7 @@ } void TranslateBubbleView::TargetLanguageChanged() { + model_->ReportUIInteraction(translate::UIInteraction::kChangeTargetLanguage); model_->UpdateTargetLanguageIndex( target_language_combobox_->GetSelectedIndex()); UpdateAdvancedView(); @@ -566,6 +579,8 @@ } void TranslateBubbleView::AlwaysTranslatePressed() { + model_->ReportUIInteraction( + translate::UIInteraction::kAlwaysTranslateLanguage); should_always_translate_ = GetAlwaysTranslateCheckbox()->GetChecked(); translate::ReportUiAction(should_always_translate_ ? translate::ALWAYS_TRANSLATE_CHECKED @@ -1040,7 +1055,8 @@ views::BubbleFrameView::CreateCloseButton(base::BindRepeating( [](View* view) { translate::ReportUiAction(translate::CLOSE_BUTTON_CLICKED); - view->GetWidget()->Close(); + view->GetWidget()->CloseWithReason( + views::Widget::ClosedReason::kCloseButtonClicked); }, base::Unretained(this))); close_button->SetVisible(true);
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc index 74940d0..8856cfa 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view_unittest.cc
@@ -145,6 +145,8 @@ void SetCanBlocklistSite(bool value) { can_blocklist_site_ = value; } + void ReportUIInteraction(translate::UIInteraction ui_interaction) override {} + TranslateBubbleViewStateTransition view_state_transition_; translate::TranslateErrors::Type error_type_; int original_language_index_;
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc index eb4e0c1..2bac29f2 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
@@ -271,6 +271,11 @@ app_menu_model->ExecuteCommand(WebAppMenuModel::kUninstallAppCommandId, /*event_flags=*/0); + // The |app_menu_model| must be destroyed here, as the |run_loop| waits + // until the app is fully uninstalled, which includes closing and deleting + // the app_browser_. + app_menu_model.reset(); + app_browser_ = nullptr; run_loop.Run(); }
diff --git a/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc b/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc index d84186df..8c86cf4b 100644 --- a/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc +++ b/chrome/browser/ui/views/webauthn/authenticator_qr_sheet_view.cc
@@ -7,8 +7,8 @@ #include "base/base64url.h" #include "base/rand_util.h" #include "base/strings/string_piece.h" -#include "chrome/common/qr_code_generator/dino_image.h" -#include "chrome/common/qr_code_generator/qr_code_generator.h" +#include "components/qr_code_generator/dino_image.h" +#include "components/qr_code_generator/qr_code_generator.h" #include "ui/gfx/canvas.h" #include "ui/views/layout/box_layout.h" #include "ui/views/view.h"
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc index 34e4f2b1..d424a49d 100644 --- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc +++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -97,9 +97,9 @@ std::make_unique<AuthenticatorBlePowerOnManualSheetModel>( dialog_model)); break; - case Step::kTouchIdIncognitoSpeedBump: + case Step::kPlatformAuthenticatorOffTheRecordInterstitial: sheet_view = std::make_unique<AuthenticatorRequestSheetView>( - std::make_unique<AuthenticatorTouchIdIncognitoBumpSheetModel>( + std::make_unique<AuthenticatorOffTheRecordInterstitialSheetModel>( dialog_model)); break; case Step::kCableActivate:
diff --git a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc index cc9cbc0..f59c8ea1 100644 --- a/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc +++ b/chrome/browser/ui/web_applications/app_browser_controller_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/run_loop.h" #include "base/test/bind.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/devtools/protocol/browser_handler.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/themes/custom_theme_supplier.h" #include "chrome/browser/themes/theme_properties.h" @@ -29,6 +30,7 @@ #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h" @@ -99,34 +101,53 @@ const AppBrowserControllerBrowserTest&) = delete; protected: - void InstallAndLaunchMockApp() { + Profile* profile() { + if (!profile_) + profile_ = browser()->profile(); + return profile_; + } + + void InstallMockSystemWebApp() { test_system_web_app_installation_->WaitForAppInstall(); + } + + void LaunchMockApp() { app_browser_ = web_app::LaunchWebAppBrowser( - browser()->profile(), test_system_web_app_installation_->GetAppId()); + profile(), test_system_web_app_installation_->GetAppId()); tabbed_app_url_ = test_system_web_app_installation_->GetAppUrl(); ASSERT_TRUE(content::NavigateToURL( app_browser_->tab_strip_model()->GetActiveWebContents(), tabbed_app_url_)); } - void InstallAndLaunchMockPopup() { - test_system_web_app_installation_->WaitForAppInstall(); + void LaunchMockPopup() { auto params = web_app::CreateSystemWebAppLaunchParams( - browser()->profile(), test_system_web_app_installation_->GetType(), + profile(), test_system_web_app_installation_->GetType(), display::kInvalidDisplayId); EXPECT_TRUE(params.has_value()); params->disposition = WindowOpenDisposition::NEW_POPUP; app_browser_ = web_app::LaunchSystemWebApp( - browser()->profile(), test_system_web_app_installation_->GetType(), + profile(), test_system_web_app_installation_->GetType(), test_system_web_app_installation_->GetAppUrl(), std::move(*params)); } + void InstallAndLaunchMockApp() { + InstallMockSystemWebApp(); + LaunchMockApp(); + } + + void InstallAndLaunchMockPopup() { + InstallMockSystemWebApp(); + LaunchMockPopup(); + } + GURL GetActiveTabURL() { return app_browser_->tab_strip_model() ->GetActiveWebContents() ->GetVisibleURL(); } + Profile* profile_ = nullptr; Browser* app_browser_ = nullptr; GURL tabbed_app_url_; @@ -252,6 +273,19 @@ EXPECT_FALSE(app_browser_->app_controller()->GetThemeColor().has_value()); } +IN_PROC_BROWSER_TEST_F(AppBrowserControllerBrowserTest, Shutdown) { + // Cache profile before browser() closes. + profile(); + InstallMockSystemWebApp(); + + BrowserHandler handler(nullptr, std::string()); + handler.Close(); + ui_test_utils::WaitForBrowserToClose(); + + LaunchMockPopup(); + EXPECT_EQ(app_browser_, nullptr); +} + IN_PROC_BROWSER_TEST_F(AppBrowserControllerBrowserTest, ReuseBrowserForSystemAppPopup) { InstallAndLaunchMockPopup();
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc index 9aff4d0..b3d8d79b 100644 --- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc +++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
@@ -179,6 +179,11 @@ return nullptr; } + if (Browser::GetBrowserCreationStatusForProfile(profile_for_launch) != + Browser::BrowserCreationStatus::kOk) { + return nullptr; + } + auto* provider = WebAppProvider::Get(profile_for_launch); if (!provider)
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc b/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc index a63c595..c431e88 100644 --- a/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc +++ b/chrome/browser/ui/web_applications/test/system_web_app_ui_browsertest.cc
@@ -33,9 +33,11 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/login_manager_test.h" #include "chrome/browser/chromeos/login/test/login_manager_mixin.h" #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" #endif @@ -476,16 +478,21 @@ run_loop.Run(); } - Browser* LaunchAppOnProfile(Profile* profile) { + AppId GetAppId(Profile* profile) { SystemWebAppManager& manager = web_app::WebAppProvider::Get(profile)->system_web_app_manager(); base::Optional<AppId> app_id = manager.GetAppIdForSystemApp(installation_->GetType()); CHECK(app_id.has_value()); + return *app_id; + } + + Browser* LaunchAppOnProfile(Profile* profile) { + AppId app_id = GetAppId(profile); auto launch_params = apps::AppLaunchParams( - *app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, + app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow, WindowOpenDisposition::CURRENT_TAB, apps::mojom::AppLaunchSource::kSourceAppLauncher); @@ -568,6 +575,55 @@ MultiUserWindowManagerHelper::GetInstance()->IsWindowOnDesktopOfUser( browser2->window()->GetNativeWindow(), account_id2_)); } + +IN_PROC_BROWSER_TEST_F(SystemWebAppManagerMultiDesktopLaunchBrowserTest, + ProfileScheduledForDeletion) { + // Login two users. + LoginUser(account_id1_); + base::RunLoop().RunUntilIdle(); + chromeos::UserAddingScreen::Get()->Start(); + AddUser(account_id2_); + base::RunLoop().RunUntilIdle(); + + // Wait for System Apps to be installed on both user profiles. + auto* user_manager = user_manager::UserManager::Get(); + Profile* profile1 = chromeos::ProfileHelper::Get()->GetProfileByUser( + user_manager->FindUser(account_id1_)); + Profile* profile2 = chromeos::ProfileHelper::Get()->GetProfileByUser( + user_manager->FindUser(account_id2_)); + WaitForSystemWebAppInstall(profile1); + WaitForSystemWebAppInstall(profile2); + + g_browser_process->profile_manager()->ScheduleProfileForDeletion( + profile2->GetPath(), base::DoNothing()); + + { + auto launch_params = apps::AppLaunchParams( + GetAppId(profile2), + apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::CURRENT_TAB, + apps::mojom::AppLaunchSource::kSourceAppLauncher); + content::WebContents* web_contents = + apps::AppServiceProxyFactory::GetForProfile(profile2) + ->BrowserAppLauncher() + ->LaunchAppWithParams(std::move(launch_params)); + EXPECT_EQ(web_contents, nullptr); + } + + { + auto launch_params = apps::AppLaunchParams( + GetAppId(profile1), + apps::mojom::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::CURRENT_TAB, + apps::mojom::AppLaunchSource::kSourceAppLauncher); + content::WebContents* web_contents = + apps::AppServiceProxyFactory::GetForProfile(profile1) + ->BrowserAppLauncher() + ->LaunchAppWithParams(std::move(launch_params)); + EXPECT_NE(web_contents, nullptr); + } +} + #endif // BUILDFLAG(IS_CHROMEOS_ASH) // The following tests are disabled in DCHECK builds. LaunchSystemWebApp DCHECKs
diff --git a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc index ec5f43d..8e97e12 100644 --- a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/web_applications/components/web_application_info.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/site_engagement/content/engagement_type.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/web_contents.h" @@ -77,11 +78,10 @@ using Histograms = std::bitset<kHistogramMaxValue>; -void ExpectUniqueSamples( - const base::HistogramTester& tester, - const Histograms& histograms_mask, - site_engagement::SiteEngagementService::EngagementType type, - base::HistogramBase::Count count) { +void ExpectUniqueSamples(const base::HistogramTester& tester, + const Histograms& histograms_mask, + site_engagement::EngagementType type, + base::HistogramBase::Count count) { for (int h = 0; h < kHistogramMaxValue; ++h) { if (histograms_mask[h]) { const char* histogram_name = HistogramEnumIndexToStr(h); @@ -90,11 +90,10 @@ } } -void ExpectBucketCounts( - const base::HistogramTester& tester, - const Histograms& histograms_mask, - site_engagement::SiteEngagementService::EngagementType type, - base::HistogramBase::Count count) { +void ExpectBucketCounts(const base::HistogramTester& tester, + const Histograms& histograms_mask, + site_engagement::EngagementType type, + base::HistogramBase::Count count) { for (int h = 0; h < kHistogramMaxValue; ++h) { if (histograms_mask[h]) { const char* histogram_name = HistogramEnumIndexToStr(h); @@ -117,13 +116,13 @@ void ExpectLaunchCounts(const base::HistogramTester& tester, base::HistogramBase::Count windowLaunches, base::HistogramBase::Count tabLaunches) { - tester.ExpectBucketCount("Extensions.HostedAppLaunchContainer", + tester.ExpectBucketCount("Extensions.BookmarkAppLaunchContainer", apps::mojom::LaunchContainer::kLaunchContainerWindow, windowLaunches); - tester.ExpectBucketCount("Extensions.HostedAppLaunchContainer", + tester.ExpectBucketCount("Extensions.BookmarkAppLaunchContainer", apps::mojom::LaunchContainer::kLaunchContainerTab, tabLaunches); - tester.ExpectTotalCount("Extensions.HostedAppLaunchContainer", + tester.ExpectTotalCount("Extensions.BookmarkAppLaunchContainer", windowLaunches + tabLaunches); if (tabLaunches > 0) { @@ -169,8 +168,7 @@ void TestEngagementEventWebAppLaunch(const base::HistogramTester& tester, const Histograms& histograms) { ExpectUniqueSamples(tester, histograms, - site_engagement::SiteEngagementService:: - ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, + site_engagement::EngagementType::kWebappShortcutLaunch, 1); ExpectTotalCounts(tester, ~histograms, 0); } @@ -192,23 +190,19 @@ site_engagement_service->HandleNavigation(web_contents, ui::PAGE_TRANSITION_TYPED); site_engagement_service->HandleUserInput( - web_contents, site_engagement::SiteEngagementService::ENGAGEMENT_MOUSE); + web_contents, site_engagement::EngagementType::kMouse); ExpectTotalCounts(tester, histograms, 4); ExpectTotalCounts(tester, ~histograms, 0); - ExpectBucketCounts( - tester, histograms, - site_engagement::SiteEngagementService::ENGAGEMENT_MEDIA_VISIBLE, 1); - ExpectBucketCounts( - tester, histograms, - site_engagement::SiteEngagementService::ENGAGEMENT_MEDIA_HIDDEN, 1); - ExpectBucketCounts( - tester, histograms, - site_engagement::SiteEngagementService::ENGAGEMENT_NAVIGATION, 1); ExpectBucketCounts(tester, histograms, - site_engagement::SiteEngagementService::ENGAGEMENT_MOUSE, - 1); + site_engagement::EngagementType::kMediaVisible, 1); + ExpectBucketCounts(tester, histograms, + site_engagement::EngagementType::kMediaHidden, 1); + ExpectBucketCounts(tester, histograms, + site_engagement::EngagementType::kNavigation, 1); + ExpectBucketCounts(tester, histograms, + site_engagement::EngagementType::kMouse, 1); } protected: @@ -354,10 +348,9 @@ histograms[kHistogramUserInstalled_InWindow] = true; histograms[kHistogramUpToThreeUserInstalledApps] = true; - ExpectUniqueSamples( - tester, histograms, - site_engagement::SiteEngagementService::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, - 3); + ExpectUniqueSamples(tester, histograms, + site_engagement::EngagementType::kWebappShortcutLaunch, + 3); ExpectTotalCounts(tester, ~histograms, 0); ExpectLaunchCounts(tester, /*windowLaunches=*/3, /*tabLaunches=*/0); } @@ -399,10 +392,9 @@ histograms[kHistogramUserInstalled_InWindow] = true; histograms[kHistogramMoreThanThreeUserInstalledApps] = true; - ExpectUniqueSamples( - tester, histograms, - site_engagement::SiteEngagementService::ENGAGEMENT_WEBAPP_SHORTCUT_LAUNCH, - num_launches); + ExpectUniqueSamples(tester, histograms, + site_engagement::EngagementType::kWebappShortcutLaunch, + num_launches); ExpectTotalCounts(tester, ~histograms, 0); ExpectLaunchCounts(tester, /*windowLaunches=*/num_launches, /*tabLaunches=*/0);
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.cc b/chrome/browser/ui/web_applications/web_app_launch_manager.cc index cba5da36..b51cdfe 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_manager.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
@@ -236,9 +236,6 @@ browser->window()->Show(); // TODO(crbug.com/1014328): Populate WebApp metrics instead of Extensions. - - UMA_HISTOGRAM_ENUMERATION("Extensions.HostedAppLaunchContainer", - params.container); if (params.container == apps::mojom::LaunchContainer::kLaunchContainerTab) { UMA_HISTOGRAM_ENUMERATION("Extensions.AppTabLaunchType", extensions::LAUNCH_TYPE_REGULAR, 100);
diff --git a/chrome/browser/ui/web_applications/web_app_metrics.cc b/chrome/browser/ui/web_applications/web_app_metrics.cc index 0e288d17..ed29cfda 100644 --- a/chrome/browser/ui/web_applications/web_app_metrics.cc +++ b/chrome/browser/ui/web_applications/web_app_metrics.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/web_applications/components/web_app_ui_manager.h" #include "chrome/browser/web_applications/daily_metrics_helper.h" #include "chrome/browser/web_applications/web_app_provider.h" +#include "components/site_engagement/content/engagement_type.h" #include "components/webapps/installable/installable_metrics.h" #include "third_party/blink/public/mojom/manifest/display_mode.mojom.h" @@ -39,23 +40,22 @@ void RecordEngagementHistogram( const std::string& histogram_name, - site_engagement::SiteEngagementService::EngagementType engagement_type) { - base::UmaHistogramEnumeration( - histogram_name, engagement_type, - site_engagement::SiteEngagementService::ENGAGEMENT_LAST); + site_engagement::EngagementType engagement_type) { + base::UmaHistogramEnumeration(histogram_name, engagement_type, + site_engagement::EngagementType::kLast); } void RecordTabOrWindowHistogram( const std::string& histogram_prefix, bool in_window, - site_engagement::SiteEngagementService::EngagementType engagement_type) { + site_engagement::EngagementType engagement_type) { RecordEngagementHistogram( histogram_prefix + (in_window ? ".InWindow" : ".InTab"), engagement_type); } void RecordUserInstalledHistogram( bool in_window, - site_engagement::SiteEngagementService::EngagementType engagement_type) { + site_engagement::EngagementType engagement_type) { const std::string histogram_prefix = "WebApp.Engagement.UserInstalled"; RecordTabOrWindowHistogram(histogram_prefix, in_window, engagement_type); } @@ -103,7 +103,7 @@ WebContents* web_contents, const GURL& url, double score, - site_engagement::SiteEngagementService::EngagementType engagement_type) { + site_engagement::EngagementType engagement_type) { if (!web_contents) return;
diff --git a/chrome/browser/ui/web_applications/web_app_metrics.h b/chrome/browser/ui/web_applications/web_app_metrics.h index 54b7d9ec..b2d8b25 100644 --- a/chrome/browser/ui/web_applications/web_app_metrics.h +++ b/chrome/browser/ui/web_applications/web_app_metrics.h
@@ -42,11 +42,11 @@ ~WebAppMetrics() override; // SiteEngagementObserver: - void OnEngagementEvent(content::WebContents* web_contents, - const GURL& url, - double score, - site_engagement::SiteEngagementService::EngagementType - engagement_type) override; + void OnEngagementEvent( + content::WebContents* web_contents, + const GURL& url, + double score, + site_engagement::EngagementType engagement_type) override; // BrowserListObserver: void OnBrowserNoLongerActive(Browser* browser) override;
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc index a0790b3..258b6e47 100644 --- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc +++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -72,8 +72,8 @@ model->SetCurrentStep( AuthenticatorRequestDialogModel::Step::kBlePowerOnManual); } else if (name == "touchid_incognito") { - model->SetCurrentStep( - AuthenticatorRequestDialogModel::Step::kTouchIdIncognitoSpeedBump); + model->SetCurrentStep(AuthenticatorRequestDialogModel::Step:: + kPlatformAuthenticatorOffTheRecordInterstitial); } else if (name == "cable_activate") { model->SetCurrentStep( AuthenticatorRequestDialogModel::Step::kCableActivate);
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc index e5d96fc8..82d8d4cc 100644 --- a/chrome/browser/ui/webauthn/sheet_models.cc +++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -470,28 +470,28 @@ dialog_model()->PowerOnBleAdapter(); } -// AuthenticatorTouchIdIncognitoBumpSheetModel +// AuthenticatorOffTheRecordInterstitialSheetModel // ----------------------------------------- -AuthenticatorTouchIdIncognitoBumpSheetModel:: - AuthenticatorTouchIdIncognitoBumpSheetModel( +AuthenticatorOffTheRecordInterstitialSheetModel:: + AuthenticatorOffTheRecordInterstitialSheetModel( AuthenticatorRequestDialogModel* dialog_model) : AuthenticatorSheetModelBase(dialog_model), other_transports_menu_model_(std::make_unique<OtherTransportsMenuModel>( dialog_model, AuthenticatorTransport::kInternal)) {} -AuthenticatorTouchIdIncognitoBumpSheetModel:: - ~AuthenticatorTouchIdIncognitoBumpSheetModel() = default; +AuthenticatorOffTheRecordInterstitialSheetModel:: + ~AuthenticatorOffTheRecordInterstitialSheetModel() = default; const gfx::VectorIcon& -AuthenticatorTouchIdIncognitoBumpSheetModel::GetStepIllustration( +AuthenticatorOffTheRecordInterstitialSheetModel::GetStepIllustration( ImageColorScheme color_scheme) const { return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon : kWebauthnPermissionIcon; } -base::string16 AuthenticatorTouchIdIncognitoBumpSheetModel::GetStepTitle() +base::string16 AuthenticatorOffTheRecordInterstitialSheetModel::GetStepTitle() const { #if defined(OS_MAC) return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TOUCH_ID_INCOGNITO_BUMP_TITLE, @@ -501,8 +501,8 @@ #endif // defined(OS_MAC) } -base::string16 AuthenticatorTouchIdIncognitoBumpSheetModel::GetStepDescription() - const { +base::string16 +AuthenticatorOffTheRecordInterstitialSheetModel::GetStepDescription() const { #if defined(OS_MAC) return l10n_util::GetStringUTF16( IDS_WEBAUTHN_TOUCH_ID_INCOGNITO_BUMP_DESCRIPTION); @@ -512,22 +512,22 @@ } ui::MenuModel* -AuthenticatorTouchIdIncognitoBumpSheetModel::GetOtherTransportsMenuModel() { +AuthenticatorOffTheRecordInterstitialSheetModel::GetOtherTransportsMenuModel() { return other_transports_menu_model_.get(); } -bool AuthenticatorTouchIdIncognitoBumpSheetModel::IsAcceptButtonVisible() +bool AuthenticatorOffTheRecordInterstitialSheetModel::IsAcceptButtonVisible() const { return true; } -bool AuthenticatorTouchIdIncognitoBumpSheetModel::IsAcceptButtonEnabled() +bool AuthenticatorOffTheRecordInterstitialSheetModel::IsAcceptButtonEnabled() const { return true; } base::string16 -AuthenticatorTouchIdIncognitoBumpSheetModel::GetAcceptButtonLabel() const { +AuthenticatorOffTheRecordInterstitialSheetModel::GetAcceptButtonLabel() const { #if defined(OS_MAC) return l10n_util::GetStringUTF16( IDS_WEBAUTHN_TOUCH_ID_INCOGNITO_BUMP_CONTINUE); @@ -536,8 +536,8 @@ #endif // defined(OS_MAC) } -void AuthenticatorTouchIdIncognitoBumpSheetModel::OnAccept() { - dialog_model()->HideDialogAndTryTouchId(); +void AuthenticatorOffTheRecordInterstitialSheetModel::OnAccept() { + dialog_model()->HideDialogAndDispatchToPlatformAuthenticator(); } // AuthenticatorPaaskSheetModel -----------------------------------------
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h index 9973cf2..8801ec5 100644 --- a/chrome/browser/ui/webauthn/sheet_models.h +++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -226,12 +226,12 @@ bool busy_powering_on_ble_ = false; }; -class AuthenticatorTouchIdIncognitoBumpSheetModel +class AuthenticatorOffTheRecordInterstitialSheetModel : public AuthenticatorSheetModelBase { public: - explicit AuthenticatorTouchIdIncognitoBumpSheetModel( + explicit AuthenticatorOffTheRecordInterstitialSheetModel( AuthenticatorRequestDialogModel* dialog_model); - ~AuthenticatorTouchIdIncognitoBumpSheetModel() override; + ~AuthenticatorOffTheRecordInterstitialSheetModel() override; private: // AuthenticatorSheetModelBase:
diff --git a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 1e444962..6cb4b41 100644 --- a/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/logging.h" #include "base/macros.h" #include "base/strings/string_piece.h" #include "build/build_config.h" @@ -157,15 +156,9 @@ ASSERT_TRUE(embedded_test_server()->Start()); ui_test_utils::NavigateToURL(browser(), GURL(url)); - - if (url == "chrome://network-error" || url == "chrome://dino") { - // We don't ASSERT_TRUE here because some WebUI pages are - // PAGE_TYPE_ERROR by design. - content::WaitForLoadStop(content); - } else { - ASSERT_TRUE(content::WaitForLoadStop(content)); - } - + // We don't ASSERT_TRUE here because some WebUI pages are by design not + // PAGE_TYPE_NORMAL (e.g. chrome://interstitials/ssl). + content::WaitForLoadStop(content); EXPECT_TRUE(console_observer.messages().empty()); } }; @@ -173,7 +166,6 @@ // Verify that there's no Trusted Types violation in chrome://chrome-urls IN_PROC_BROWSER_TEST_P(ChromeURLDataManagerWebUITrustedTypesTest, NoTrustedTypesViolation) { - LOG(INFO) << "Navigating to " << GetParam(); CheckTrustedTypesViolation(GetParam()); } @@ -184,18 +176,23 @@ // TODO(crbug.com/1114074): DCHECK failure when opening // chrome://appcache-internals. // "chrome://appcache-internals", + "chrome://apps", "chrome://autofill-internals", "chrome://blob-internals", "chrome://bluetooth-internals", "chrome://bookmarks", + "chrome://browser-switch", "chrome://chrome-urls", "chrome://components", + "chrome://conflicts", "chrome://connection-help", "chrome://connection-monitoring-detected", "chrome://conversion-internals", "chrome://crashes", "chrome://credits", "chrome://device-log", + // TODO(crbug.com/1114062): Crash when closing chrome://devices. + // "chrome://devices", "chrome://dino", // TODO(crbug.com/1113446): Test failure due to excessive output. // "chrome://discards", @@ -218,6 +215,7 @@ "chrome://invalidations", "chrome://local-state", "chrome://management", + "chrome://md-user-manager", "chrome://media-engagement", "chrome://media-feeds", "chrome://media-history", @@ -231,6 +229,7 @@ "chrome://network-errors", "chrome://new-tab-page", "chrome://newtab", + "chrome://notifications-internals", "chrome://ntp-tiles-internals", "chrome://omnibox", "chrome://password-manager-internals", @@ -248,8 +247,10 @@ // TODO(crbug.com/1115600): DCHECK failure when opening // chrome://signin-dice-web-intercept. // "chrome://signin-dice-web-intercept", + "chrome://signin-email-confirmation", "chrome://signin-internals", "chrome://site-engagement", + "chrome://snippets-internals", "chrome://suggestions", // TODO(crbug.com/1099564): Navigating to chrome://sync-confirmation and // quickly navigating away cause DCHECK failure. @@ -269,12 +270,12 @@ "chrome://version", "chrome://webrtc-internals", "chrome://webrtc-logs", + "chrome://welcome", #if defined(OS_ANDROID) "chrome://explore-sites-internals", "chrome://internals/notifications", "chrome://internals/query-tiles", "chrome://offline-internals", - "chrome://snippets-internals", "chrome://webapks", #endif #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -294,6 +295,7 @@ "chrome://crostini-installer", "chrome://cryptohome", "chrome://drive-internals", + "chrome://first-run", "chrome://help-app", "chrome://internet-config-dialog", "chrome://internet-detail-dialog", @@ -312,17 +314,11 @@ "chrome://smb-share-dialog", "chrome://supervised-user-internals", "chrome://sys-internals", + // TODO(crbug.com/1115643): DCHECK failure when opening + // chrome-untrusted://crosh. + // "chrome-untrusted://crosh", "chrome-untrusted://terminal", #endif -#if !BUILDFLAG(IS_CHROMEOS_ASH) - "chrome://apps", - "chrome://browser-switch", - "chrome://md-user-manager", - "chrome://signin-email-confirmation", -#endif -#if defined(OS_WIN) - "chrome://conflicts", -#endif }; INSTANTIATE_TEST_SUITE_P(,
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc index 0275b3f..a80915d 100644 --- a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc
@@ -8,6 +8,8 @@ #include "base/bind.h" #include "base/json/json_writer.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chromeos/in_session_password_change/confirm_password_change_handler.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" @@ -68,7 +70,8 @@ return; } g_dialog = new LockScreenStartReauthDialog(); - g_dialog->ShowSystemDialog(); + g_dialog->ShowSystemDialogForBrowserContext( + ProfileHelper::GetLockScreenIncognitoProfile()); } void LockScreenStartReauthDialog::Dismiss() {
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc index a73443d..594dd2b7 100644 --- a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc
@@ -21,7 +21,7 @@ : ui::WebDialogUI(web_ui) { Profile* profile = Profile::FromWebUI(web_ui); const user_manager::User* user = - ProfileHelper::Get()->GetUserByProfile(profile); + user_manager::UserManager::Get()->GetActiveUser(); std::string email; if (user) { email = user->GetDisplayEmail();
diff --git a/chrome/browser/ui/webui/invalidations/invalidations_ui.cc b/chrome/browser/ui/webui/invalidations/invalidations_ui.cc index 55cbab4..4b97b20 100644 --- a/chrome/browser/ui/webui/invalidations/invalidations_ui.cc +++ b/chrome/browser/ui/webui/invalidations/invalidations_ui.cc
@@ -8,8 +8,10 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/invalidations/invalidations_message_handler.h" +#include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" #include "chrome/grit/invalidations_resources.h" +#include "chrome/grit/invalidations_resources_map.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" @@ -26,10 +28,9 @@ source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::TrustedTypes, "trusted-types jstemplate;"); - source->AddResourcePath("about_invalidations.js", - IDR_INVALIDATIONS_ABOUT_INVALIDATIONS_JS); - source->AddResourcePath("about_invalidations.css", - IDR_INVALIDATIONS_ABOUT_INVALIDATIONS_CSS); + webui::AddResourcePathsBulk( + source, + base::make_span(kInvalidationsResources, kInvalidationsResourcesSize)); source->SetDefaultResource(IDR_INVALIDATIONS_ABOUT_INVALIDATIONS_HTML); return source; }
diff --git a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc index 277bf50c..5b7a6ba1 100644 --- a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc
@@ -188,8 +188,11 @@ DCHECK(settings_); CHECK_EQ(1U, args->GetSize()); - settings_->temperature_unit = ExtractTemperatureUnit(args); - UpdateSettings(); + auto temperature_unit = ExtractTemperatureUnit(args); + if (settings_->temperature_unit != temperature_unit) { + settings_->temperature_unit = temperature_unit; + UpdateSettings(); + } } void AmbientModeHandler::HandleSetSelectedAlbums(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc index d84e435..7e05d653 100644 --- a/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler_unittest.cc
@@ -64,6 +64,13 @@ handler_->settings_->topic_source = topic_source; } + void SetTemperatureUnit(ash::AmbientModeTemperatureUnit temperature_unit) { + if (!handler_->settings_) + handler_->settings_ = ash::AmbientSettings(); + + handler_->settings_->temperature_unit = temperature_unit; + } + void RequestSettings() { base::ListValue args; handler_->HandleRequestSettings(&args); @@ -75,6 +82,10 @@ handler_->HandleRequestAlbums(&args); } + void HandleSetSelectedTemperatureUnit(const base::ListValue* args) { + handler_->HandleSetSelectedTemperatureUnit(args); + } + void HandleSetSelectedAlbums(const base::ListValue* args) { handler_->HandleSetSelectedAlbums(args); } @@ -735,5 +746,40 @@ /*count=*/1); } +TEST_F(AmbientModeHandlerTest, TestTemperatureUnitChangeUpdatesSettings) { + SetTemperatureUnit(ash::AmbientModeTemperatureUnit::kCelsius); + + EXPECT_FALSE(IsUpdateSettingsPendingAtHandler()); + EXPECT_FALSE(IsUpdateSettingsPendingAtBackend()); + + base::ListValue args; + args.Append("fahrenheit"); + + HandleSetSelectedTemperatureUnit(&args); + + EXPECT_TRUE(IsUpdateSettingsPendingAtHandler()); + EXPECT_TRUE(IsUpdateSettingsPendingAtBackend()); + + ReplyUpdateSettings(/*success=*/true); + + EXPECT_FALSE(IsUpdateSettingsPendingAtHandler()); + EXPECT_FALSE(IsUpdateSettingsPendingAtBackend()); +} + +TEST_F(AmbientModeHandlerTest, TestSameTemperatureUnitSkipsUpdate) { + SetTemperatureUnit(ash::AmbientModeTemperatureUnit::kCelsius); + + EXPECT_FALSE(IsUpdateSettingsPendingAtHandler()); + EXPECT_FALSE(IsUpdateSettingsPendingAtBackend()); + + base::ListValue args; + args.Append("celsius"); + + HandleSetSelectedTemperatureUnit(&args); + + EXPECT_FALSE(IsUpdateSettingsPendingAtHandler()); + EXPECT_FALSE(IsUpdateSettingsPendingAtBackend()); +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc index e39efbe..f0b6d80c 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
@@ -283,7 +283,9 @@ ->GetTabGroup(tab_group_id.value()) ->ListTabs(); - const auto& selected_tabs = selection.new_model.selected_indices(); + const ui::ListSelectionModel::SelectedIndices& sel = + selection.new_model.selected_indices(); + const auto& selected_tabs = std::vector<int>(sel.begin(), sel.end()); const bool all_tabs_in_group = IsSortedAndContiguous(base::make_span(selected_tabs)) && selected_tabs.front() == static_cast<int>(tabs_in_group.start()) &&
diff --git a/chrome/browser/ui/webui/webapks/webapks_ui.cc b/chrome/browser/ui/webui/webapks/webapks_ui.cc index f5dcb36d..14b20c54 100644 --- a/chrome/browser/ui/webui/webapks/webapks_ui.cc +++ b/chrome/browser/ui/webui/webapks/webapks_ui.cc
@@ -9,8 +9,10 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/webapks/webapks_handler.h" +#include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" -#include "chrome/grit/webapks_ui_resources.h" +#include "chrome/grit/webapks_resources.h" +#include "chrome/grit/webapks_resources_map.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" @@ -22,9 +24,10 @@ WebUIDataSource* html_source = WebUIDataSource::Create(chrome::kChromeUIWebApksHost); html_source->UseStringsJs(); - html_source->AddResourcePath("webapks.js", IDR_WEBAPKS_UI_JS); - html_source->AddResourcePath("about_webapks.css", IDR_WEBAPKS_UI_CSS); - html_source->SetDefaultResource(IDR_WEBAPKS_UI_HTML); + + webui::AddResourcePathsBulk( + html_source, base::make_span(kWebapksResources, kWebapksResourcesSize)); + html_source->SetDefaultResource(IDR_WEBAPKS_ABOUT_WEBAPKS_HTML); return html_source; }
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index b25b2d0..469d08a 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -39,6 +39,7 @@ "policy/web_app_policy_manager.h", "protocol_handler_manager.cc", "protocol_handler_manager.h", + "system_web_app_types.h", "web_app_audio_focus_id_map.cc", "web_app_audio_focus_id_map.h", "web_app_chromeos_data.cc", @@ -69,6 +70,8 @@ "web_app_shortcut.h", "web_app_shortcuts_menu.cc", "web_app_shortcuts_menu.h", + "web_app_system_web_app_data.cc", + "web_app_system_web_app_data.h", "web_app_tab_helper_base.cc", "web_app_tab_helper_base.h", "web_app_ui_manager.h",
diff --git a/chrome/browser/web_applications/components/app_registrar.cc b/chrome/browser/web_applications/components/app_registrar.cc index a407492..5da8eb9 100644 --- a/chrome/browser/web_applications/components/app_registrar.cc +++ b/chrome/browser/web_applications/components/app_registrar.cc
@@ -64,6 +64,11 @@ observer.OnWebAppsWillBeUpdatedFromSync(new_apps_state); } +void AppRegistrar::NotifyWebAppUninstalled(const AppId& app_id) { + for (AppRegistrarObserver& observer : observers_) + observer.OnWebAppUninstalled(app_id); +} + void AppRegistrar::NotifyWebAppWillBeUninstalled(const AppId& app_id) { for (AppRegistrarObserver& observer : observers_) observer.OnWebAppWillBeUninstalled(app_id);
diff --git a/chrome/browser/web_applications/components/app_registrar.h b/chrome/browser/web_applications/components/app_registrar.h index ad0f44fe..14c3d13a 100644 --- a/chrome/browser/web_applications/components/app_registrar.h +++ b/chrome/browser/web_applications/components/app_registrar.h
@@ -200,6 +200,7 @@ base::StringPiece old_name); void NotifyWebAppsWillBeUpdatedFromSync( const std::vector<const WebApp*>& new_apps_state); + void NotifyWebAppUninstalled(const AppId& app_id); void NotifyWebAppWillBeUninstalled(const AppId& app_id); void NotifyWebAppLocallyInstalledStateChanged(const AppId& app_id, bool is_locally_installed);
diff --git a/chrome/browser/web_applications/components/app_registrar_observer.h b/chrome/browser/web_applications/components/app_registrar_observer.h index d1a7937..189c610 100644 --- a/chrome/browser/web_applications/components/app_registrar_observer.h +++ b/chrome/browser/web_applications/components/app_registrar_observer.h
@@ -35,11 +35,18 @@ virtual void OnWebAppsWillBeUpdatedFromSync( const std::vector<const WebApp*>& new_apps_state) {} - // Called before a web app is uninstalled. |app_id| is still registered in the - // AppRegistrar. For bookmark apps, use BookmarkAppRegistrar::FindExtension to - // convert this |app_id| to Extension pointer. + // Called before a web app is uninstalled, before the uninstallation process + // begins. |app_id| is still registered in the AppRegistrar, and OS hooks have + // not yet been uninstalled. For bookmark apps, use + // BookmarkAppRegistrar::FindExtension to convert this |app_id| to Extension + // pointer. virtual void OnWebAppWillBeUninstalled(const AppId& app_id) {} + // Called after a web app is uninstalled. |app_id| is no longer registered in + // the AppRegistrar, all OS hooks are uninstalled, and icons have been + // deleted. + virtual void OnWebAppUninstalled(const AppId& app_id) {} + // For bookmark apps, use BookmarkAppRegistrar::FindExtension to convert this // |app_id| to Extension pointer. virtual void OnWebAppProfileWillBeDeleted(const AppId& app_id) {}
diff --git a/chrome/browser/web_applications/components/external_install_options.cc b/chrome/browser/web_applications/components/external_install_options.cc index 674ab3f..434ecaa 100644 --- a/chrome/browser/web_applications/components/external_install_options.cc +++ b/chrome/browser/web_applications/components/external_install_options.cc
@@ -11,6 +11,7 @@ #include "base/strings/string_util.h" #include "build/chromeos_buildflags.h" +#include "chrome/browser/web_applications/components/system_web_app_types.h" namespace web_app { @@ -148,7 +149,11 @@ << base::JoinString(install_options.additional_search_terms, "\n ") << "\n only_use_app_info_factory: " << install_options.only_use_app_info_factory << "\n app_info_factory: " - << !install_options.app_info_factory.is_null(); + << !install_options.app_info_factory.is_null() + << "\n system_app_type: " + << (install_options.system_app_type.has_value() + ? static_cast<int32_t>(install_options.system_app_type.value()) + : -1); } InstallManager::InstallParams ConvertExternalInstallOptionsToParams( @@ -175,6 +180,8 @@ params.launch_query_params = install_options.launch_query_params; + params.system_app_type = install_options.system_app_type; + return params; }
diff --git a/chrome/browser/web_applications/components/external_install_options.h b/chrome/browser/web_applications/components/external_install_options.h index 1d89d43b..7031fc9a 100644 --- a/chrome/browser/web_applications/components/external_install_options.h +++ b/chrome/browser/web_applications/components/external_install_options.h
@@ -9,7 +9,9 @@ #include <string> #include <vector> +#include "base/optional.h" #include "chrome/browser/web_applications/components/install_manager.h" +#include "chrome/browser/web_applications/components/system_web_app_types.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_id.h" #include "chrome/browser/web_applications/components/web_application_info.h" @@ -152,6 +154,9 @@ // A factory callback that returns a unique_ptr<WebApplicationInfo> to be used // as the app's installation metadata. WebApplicationInfoFactory app_info_factory; + + // The type of SystemWebApp, if this app is a System Web App. + base::Optional<SystemAppType> system_app_type = base::nullopt; }; std::ostream& operator<<(std::ostream& out,
diff --git a/chrome/browser/web_applications/components/install_finalizer.h b/chrome/browser/web_applications/components/install_finalizer.h index 6b03ec8..f8bdbd3 100644 --- a/chrome/browser/web_applications/components/install_finalizer.h +++ b/chrome/browser/web_applications/components/install_finalizer.h
@@ -11,6 +11,7 @@ #include "base/optional.h" #include "chrome/browser/web_applications/components/web_app_chromeos_data.h" #include "chrome/browser/web_applications/components/web_app_id.h" +#include "chrome/browser/web_applications/components/web_app_system_web_app_data.h" #include "components/webapps/installable/installable_metrics.h" struct WebApplicationInfo; @@ -48,6 +49,7 @@ bool locally_installed = true; base::Optional<WebAppChromeOsData> chromeos_data; + base::Optional<WebAppSystemWebAppData> system_web_app_data; }; // Write the WebApp data to disk and register the app.
diff --git a/chrome/browser/web_applications/components/install_manager.h b/chrome/browser/web_applications/components/install_manager.h index c131aa77..d7bf468 100644 --- a/chrome/browser/web_applications/components/install_manager.h +++ b/chrome/browser/web_applications/components/install_manager.h
@@ -11,6 +11,7 @@ #include "base/callback_forward.h" #include "base/optional.h" +#include "chrome/browser/web_applications/components/system_web_app_types.h" #include "chrome/browser/web_applications/components/web_app_chromeos_data.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_id.h" @@ -126,6 +127,7 @@ std::vector<std::string> additional_search_terms; base::Optional<std::string> launch_query_params; + base::Optional<SystemAppType> system_app_type; }; // Starts a background web app installation process for a given // |web_contents|.
diff --git a/chrome/browser/web_applications/components/system_web_app_types.h b/chrome/browser/web_applications/components/system_web_app_types.h new file mode 100644 index 0000000..7f2e6db --- /dev/null +++ b/chrome/browser/web_applications/components/system_web_app_types.h
@@ -0,0 +1,42 @@ +// Copyright 2018 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_WEB_APPLICATIONS_COMPONENTS_SYSTEM_WEB_APP_TYPES_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_SYSTEM_WEB_APP_TYPES_H_ + +namespace web_app { + +// An enum that lists the different System Apps that exist. Can be used to +// retrieve the App ID from the underlying Web App system. +// +// These values are persisted to the web_app database. Entries should not be +// renumbered and numeric values should never be reused. +// +// When adding a new type, please add to the end, use an explicit number, and +// add a corresponding value to the proto enum in web_app.proto. +// +// When deprecating, comment out the entry so that it's not accidently re-used. +enum class SystemAppType { + FILE_MANAGER = 1, + TELEMETRY = 2, + SAMPLE = 3, + SETTINGS = 4, + CAMERA = 5, + TERMINAL = 6, + MEDIA = 7, + HELP = 8, + PRINT_MANAGEMENT = 9, + SCANNING = 10, + DIAGNOSTICS = 11, + CONNECTIVITY_DIAGNOSTICS = 12, + + // When adding a new System App, add a corresponding histogram suffix in + // WebAppSystemAppInternalName (histograms.xml). The suffix name should match + // the App's |internal_name|. This is for reporting per-app install results. + +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_SYSTEM_WEB_APP_TYPES_H_
diff --git a/chrome/browser/web_applications/components/web_app_system_web_app_data.cc b/chrome/browser/web_applications/components/web_app_system_web_app_data.cc new file mode 100644 index 0000000..dd25a4d --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_system_web_app_data.cc
@@ -0,0 +1,25 @@ +// Copyright 2020 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/web_applications/components/web_app_system_web_app_data.h" +#include <ios> +#include <ostream> +#include <tuple> + +namespace web_app { + +bool operator==(const WebAppSystemWebAppData& chromeos_data1, + const WebAppSystemWebAppData& chromeos_data2) { + return chromeos_data1.system_app_type == chromeos_data2.system_app_type; +} + +std::ostream& operator<<(std::ostream& out, + const WebAppSystemWebAppData& chromeos_data) { + out << " swa type: " << static_cast<int>(chromeos_data.system_app_type) + << std::endl; + + return out; +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_system_web_app_data.h b/chrome/browser/web_applications/components/web_app_system_web_app_data.h new file mode 100644 index 0000000..c3dbae2 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_system_web_app_data.h
@@ -0,0 +1,28 @@ +// Copyright 2020 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_WEB_APPLICATIONS_COMPONENTS_WEB_APP_SYSTEM_WEB_APP_DATA_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_SYSTEM_WEB_APP_DATA_H_ + +#include <iosfwd> +#include "base/optional.h" +#include "chrome/browser/web_applications/components/system_web_app_types.h" + +namespace web_app { + +struct WebAppSystemWebAppData { + SystemAppType system_app_type; +}; + +// For logging and debugging purposes. +std::ostream& operator<<(std::ostream& out, const WebAppSystemWebAppData& data); + +bool operator==(const WebAppSystemWebAppData& data1, + const WebAppSystemWebAppData& data2); +bool operator!=(const WebAppSystemWebAppData& data1, + const WebAppSystemWebAppData& data2); + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_SYSTEM_WEB_APP_DATA_H_
diff --git a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc index ce8a555..d741435 100644 --- a/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc +++ b/chrome/browser/web_applications/extensions/pending_app_install_task_unittest.cc
@@ -1005,6 +1005,96 @@ base::RunLoop().RunUntilIdle(); } +TEST_F(PendingAppInstallTaskTest, InstallWithWebAppInfo_Succeeds) { + ExternalInstallOptions options(WebAppUrl(), DisplayMode::kStandalone, + ExternalInstallSource::kSystemInstalled); + options.only_use_app_info_factory = true; + options.app_info_factory = base::BindLambdaForTesting([]() { + auto info = std::make_unique<WebApplicationInfo>(); + info->start_url = WebAppUrl(); + info->scope = WebAppUrl().GetWithoutFilename(); + info->title = base::UTF8ToUTF16("Foo Web App"); + return info; + }); + + PendingAppInstallTask task( + profile(), /*url_loader=*/nullptr, registrar(), os_integration_manager(), + ui_manager(), finalizer(), install_manager(), std::move(options)); + + finalizer()->SetNextFinalizeInstallResult( + WebAppUrl(), InstallResultCode::kSuccessNewInstall); + + base::RunLoop run_loop; + task.Install( + /*web_contents=*/nullptr, + base::BindLambdaForTesting([&](base::Optional<AppId> app_id, + PendingAppManager::InstallResult result) { + base::Optional<AppId> id = + ExternallyInstalledWebAppPrefs(profile()->GetPrefs()) + .LookupAppId(WebAppUrl()); + EXPECT_EQ(InstallResultCode::kSuccessOfflineOnlyInstall, result.code); + EXPECT_TRUE(app_id.has_value()); + + EXPECT_FALSE(IsPlaceholderApp(profile(), WebAppUrl())); + + EXPECT_EQ(app_id.value(), id.value()); + + // Installing with an App Info doesn't call into OS Integration Manager. + // This might be an issue for default apps. + EXPECT_FALSE( + os_integration_manager()->get_last_install_options().has_value()); + + EXPECT_EQ(0u, finalizer()->num_reparent_tab_calls()); + + EXPECT_TRUE(web_app_info().open_as_window); + EXPECT_EQ(webapps::WebappInstallSource::SYSTEM_DEFAULT, + finalize_options().install_source); + + run_loop.Quit(); + })); + run_loop.Run(); +} + +TEST_F(PendingAppInstallTaskTest, InstallWithWebAppInfo_Fails) { + ExternalInstallOptions options(WebAppUrl(), DisplayMode::kStandalone, + ExternalInstallSource::kSystemInstalled); + options.only_use_app_info_factory = true; + options.app_info_factory = base::BindLambdaForTesting([]() { + auto info = std::make_unique<WebApplicationInfo>(); + info->start_url = WebAppUrl(); + info->scope = WebAppUrl().GetWithoutFilename(); + info->title = base::UTF8ToUTF16("Foo Web App"); + return info; + }); + + PendingAppInstallTask task( + profile(), /*url_loader=*/nullptr, registrar(), os_integration_manager(), + ui_manager(), finalizer(), install_manager(), std::move(options)); + + finalizer()->SetNextFinalizeInstallResult( + WebAppUrl(), InstallResultCode::kWriteDataFailed); + + base::RunLoop run_loop; + + task.Install( + web_contents(), + base::BindLambdaForTesting([&](base::Optional<AppId> app_id, + PendingAppManager::InstallResult result) { + base::Optional<AppId> id = + ExternallyInstalledWebAppPrefs(profile()->GetPrefs()) + .LookupAppId(WebAppUrl()); + + EXPECT_EQ(InstallResultCode::kWriteDataFailed, result.code); + EXPECT_FALSE(app_id.has_value()); + + EXPECT_FALSE(id.has_value()); + + run_loop.Quit(); + })); + + run_loop.Run(); +} + TEST_F(PendingAppInstallTaskWithRunOnOsLoginTest, WebAppOrShortcutFromContents_RunOnOsLogin) { ExternalInstallOptions install_options(
diff --git a/chrome/browser/web_applications/pending_app_install_task.cc b/chrome/browser/web_applications/pending_app_install_task.cc index d78b972..e1bee1cc 100644 --- a/chrome/browser/web_applications/pending_app_install_task.cc +++ b/chrome/browser/web_applications/pending_app_install_task.cc
@@ -58,6 +58,12 @@ void PendingAppInstallTask::Install(content::WebContents* web_contents, ResultCallback result_callback) { + if (install_options_.only_use_app_info_factory) { + DCHECK(install_options_.app_info_factory); + InstallFromInfo(std::move(result_callback)); + return; + } + url_loader_->PrepareForLoad( web_contents, base::BindOnce(&PendingAppInstallTask::OnWebContentsReady, weak_ptr_factory_.GetWeakPtr(), web_contents,
diff --git a/chrome/browser/web_applications/pending_app_install_task.h b/chrome/browser/web_applications/pending_app_install_task.h index b253fa2..af8c8e3 100644 --- a/chrome/browser/web_applications/pending_app_install_task.h +++ b/chrome/browser/web_applications/pending_app_install_task.h
@@ -70,13 +70,13 @@ virtual void Install(content::WebContents* web_contents, ResultCallback result_callback); - // Install directly from a fully specified WebApplicationInfo struct. Used - // by system apps. - virtual void InstallFromInfo(ResultCallback result_callback); - const ExternalInstallOptions& install_options() { return install_options_; } private: + // Install directly from a fully specified WebApplicationInfo struct. Used + // by system apps. + void InstallFromInfo(ResultCallback result_callback); + void OnWebContentsReady(content::WebContents* web_contents, ResultCallback result_callback, WebAppUrlLoader::Result prepare_for_load_result);
diff --git a/chrome/browser/web_applications/pending_app_manager_impl.cc b/chrome/browser/web_applications/pending_app_manager_impl.cc index 56fd11f..b744fc3 100644 --- a/chrome/browser/web_applications/pending_app_manager_impl.cc +++ b/chrome/browser/web_applications/pending_app_manager_impl.cc
@@ -220,15 +220,8 @@ pending_registrations_.push_front(current_registration_->install_url()); current_registration_.reset(); } + current_install_ = std::move(task); - - if (current_install_->task->install_options().only_use_app_info_factory) { - DCHECK(current_install_->task->install_options().app_info_factory); - current_install_->task->InstallFromInfo(base::BindOnce( - &PendingAppManagerImpl::OnInstalled, weak_ptr_factory_.GetWeakPtr())); - return; - } - CreateWebContentsIfNecessary(); current_install_->task->Install( web_contents_.get(), base::BindOnce(&PendingAppManagerImpl::OnInstalled,
diff --git a/chrome/browser/web_applications/pending_app_manager_impl_unittest.cc b/chrome/browser/web_applications/pending_app_manager_impl_unittest.cc index 66689dd..71133b33 100644 --- a/chrome/browser/web_applications/pending_app_manager_impl_unittest.cc +++ b/chrome/browser/web_applications/pending_app_manager_impl_unittest.cc
@@ -339,17 +339,10 @@ ResultCallback callback) override { pending_app_manager_impl_->OnInstallCalled(install_options()); - const GURL install_url = install_options().install_url; - test_install_task_manager_.RunOrSaveRequest(base::BindLambdaForTesting( - [&, install_url, callback = std::move(callback)]() mutable { - DoInstall(install_url, std::move(callback)); - })); - } - - void InstallFromInfo(ResultCallback callback) override { - pending_app_manager_impl_->OnInstallCalled(install_options()); - - GURL install_url = install_options().app_info_factory.Run()->start_url; + const GURL install_url = + install_options().only_use_app_info_factory + ? install_options().app_info_factory.Run()->start_url + : install_options().install_url; test_install_task_manager_.RunOrSaveRequest(base::BindLambdaForTesting( [&, install_url, callback = std::move(callback)]() mutable { DoInstall(install_url, std::move(callback));
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto index 7498117e..4c4120b 100644 --- a/chrome/browser/web_applications/proto/web_app.proto +++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -54,6 +54,31 @@ required bool is_disabled = 4; } +// Properties for System Web Apps. +message SystemWebAppDataProto { + enum SystemAppType { + FILE_MANAGER = 1; + TELEMETRY = 2; + SAMPLE = 3; + SETTINGS = 4; + CAMERA = 5; + TERMINAL = 6; + MEDIA = 7; + HELP = 8; + PRINT_MANAGEMENT = 9; + SCANNING = 10; + DIAGNOSTICS = 11; + CONNECTIVITY_DIAGNOSTICS = 12; + }; + + optional SystemAppType system_app_type = 1; +} + +// Properties for System Web Apps. +message ClientDataProto { + optional SystemWebAppDataProto system_web_app_data = 1; +} + // Properties for a WebApp's shortcuts menu item. message WebAppShortcutsMenuItemInfoProto { required string name = 1; @@ -166,4 +191,6 @@ optional string launch_query_params = 26; repeated WebAppUrlHandlerProto url_handlers = 27; + + optional ClientDataProto client_data = 28; }
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc index ddf8cd48..a9778f2 100644 --- a/chrome/browser/web_applications/system_web_app_manager.cc +++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -14,6 +14,7 @@ #include "base/command_line.h" #include "base/containers/contains.h" #include "base/metrics/histogram_functions.h" +#include "base/optional.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/version.h" @@ -27,10 +28,13 @@ #include "chrome/browser/web_applications/components/external_install_options.h" #include "chrome/browser/web_applications/components/os_integration_manager.h" #include "chrome/browser/web_applications/components/web_app_constants.h" +#include "chrome/browser/web_applications/components/web_app_id.h" #include "chrome/browser/web_applications/components/web_app_install_utils.h" #include "chrome/browser/web_applications/components/web_app_ui_manager.h" #include "chrome/browser/web_applications/components/web_app_utils.h" #include "chrome/browser/web_applications/components/web_application_info.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" @@ -209,6 +213,7 @@ &CreateWebAppInfoForScanningSystemWebApp))); infos.at(SystemAppType::SCANNING).minimum_window_size = {600, 420}; infos.at(SystemAppType::SCANNING).capture_navigations = true; + infos.at(SystemAppType::SCANNING).show_in_launcher = false; } if (SystemWebAppManager::IsAppEnabled( @@ -265,6 +270,7 @@ } ExternalInstallOptions CreateInstallOptionsForSystemApp( + const SystemAppType app_type, const SystemAppInfo& info, bool force_update, bool is_disabled) { @@ -285,6 +291,7 @@ install_options.bypass_service_worker_check = true; install_options.force_reinstall = force_update; install_options.uninstall_and_replace = info.uninstall_and_replace; + install_options.system_app_type = app_type; const auto& search_terms = info.additional_search_terms; std::transform(search_terms.begin(), search_terms.end(), @@ -351,6 +358,13 @@ return true; #if BUILDFLAG(IS_CHROMEOS_ASH) + +#if !defined(OFFICIAL_BUILD) + bool install_experimental_apps = true; +#else + bool install_experimental_apps = false; +#endif + switch (type) { case SystemAppType::SETTINGS: return true; @@ -373,16 +387,17 @@ case SystemAppType::CONNECTIVITY_DIAGNOSTICS: return base::FeatureList::IsEnabled( chromeos::features::kConnectivityDiagnosticsWebUi); -#if !defined(OFFICIAL_BUILD) case SystemAppType::TELEMETRY: - return base::FeatureList::IsEnabled( - chromeos::features::kTelemetryExtension); + return install_experimental_apps && + base::FeatureList::IsEnabled( + chromeos::features::kTelemetryExtension); case SystemAppType::FILE_MANAGER: - return base::FeatureList::IsEnabled(chromeos::features::kFilesSWA); + return install_experimental_apps && + base::FeatureList::IsEnabled(chromeos::features::kFilesSWA); case SystemAppType::SAMPLE: - NOTREACHED(); + if (install_experimental_apps) + NOTREACHED(); return false; -#endif // !defined(OFFICIAL_BUILD) } #else return false; @@ -467,7 +482,7 @@ for (const auto& app : system_app_infos_) { install_options_list.push_back(CreateInstallOptionsForSystemApp( - app.second, should_force_install_apps, + app.first, app.second, should_force_install_apps, base::Contains(disabled_system_apps, app.first))); } @@ -525,23 +540,43 @@ base::Optional<SystemAppType> SystemWebAppManager::GetSystemAppTypeForAppId( AppId app_id) const { - auto it = app_id_to_app_type_.find(app_id); - if (it == app_id_to_app_type_.end()) - return base::nullopt; + WebAppRegistrar* web_registrar = registrar_->AsWebAppRegistrar(); - return it->second; + if (!web_registrar) { + return base::nullopt; + } + + const WebApp* web_app = web_registrar->GetAppById(app_id); + if (web_app && web_app->client_data().system_web_app_data.has_value()) { + return web_app->client_data().system_web_app_data->system_app_type; + } + + return base::nullopt; } std::vector<AppId> SystemWebAppManager::GetAppIds() const { std::vector<AppId> app_ids; - for (const auto& app_id_to_app_type : app_id_to_app_type_) { - app_ids.push_back(app_id_to_app_type.first); + for (const auto& app_type_to_app_info : system_app_infos_) { + base::Optional<AppId> app_id = + GetAppIdForSystemApp(app_type_to_app_info.first); + if (app_id.has_value()) { + app_ids.push_back(app_id.value()); + } } return app_ids; } bool SystemWebAppManager::IsSystemWebApp(const AppId& app_id) const { - return app_id_to_app_type_.contains(app_id); + WebAppRegistrar* web_registrar = registrar_->AsWebAppRegistrar(); + // some non-swa web app browser tests call this, and don't have a + // web registrar (they have a BookmarkAppRegistrar) so we need to be a little + // careful. + if (!web_registrar) { + return false; + } + + const WebApp* web_app = web_registrar->GetAppById(app_id); + return web_app && web_app->client_data().system_web_app_data.has_value(); } bool SystemWebAppManager::IsSingleWindow(SystemAppType type) const { @@ -657,14 +692,17 @@ } gfx::Size SystemWebAppManager::GetMinimumWindowSize(const AppId& app_id) const { - auto app_type_it = app_id_to_app_type_.find(app_id); - if (app_type_it == app_id_to_app_type_.end()) + base::Optional<SystemAppType> app_type = GetSystemAppTypeForAppId(app_id); + + if (!app_type.has_value()) return gfx::Size(); - const SystemAppType& app_type = app_type_it->second; - auto app_info_it = system_app_infos_.find(app_type); - if (app_info_it == system_app_infos_.end()) + auto app_type_to_app_info = system_app_infos_.find(app_type.value()); + + if (app_type_to_app_info == system_app_infos_.end()) { return gfx::Size(); - return app_info_it->second.minimum_window_size; + } + + return app_type_to_app_info->second.minimum_window_size; } void SystemWebAppManager::SetSystemAppsForTesting( @@ -799,15 +837,6 @@ RecordSystemWebAppInstallResults(install_results); - // Build the map from installed app id to app type. - for (const auto& it : system_app_infos_) { - const SystemAppType& app_type = it.first; - base::Optional<AppId> app_id = - registrar_->LookupExternalAppId(it.second.install_url); - if (app_id.has_value()) - app_id_to_app_type_[app_id.value()] = app_type; - } - // May be called more than once in tests. if (!on_apps_synchronized_->is_signaled()) { on_apps_synchronized_->Signal(); @@ -889,10 +918,14 @@ auto disabled_system_apps = GetDisabledSystemWebApps(); - for (const auto& id_and_type : app_id_to_app_type_) { + for (const auto& app_type_to_app_info : system_app_infos_) { const bool is_disabled = - base::Contains(disabled_system_apps, id_and_type.second); - registry_controller_->SetAppIsDisabled(id_and_type.first, is_disabled); + base::Contains(disabled_system_apps, app_type_to_app_info.first); + base::Optional<AppId> app_id = + GetAppIdForSystemApp(app_type_to_app_info.first); + if (app_id.has_value()) { + registry_controller_->SetAppIsDisabled(app_id.value(), is_disabled); + } } #endif // BUILDFLAG(IS_CHROMEOS_ASH) }
diff --git a/chrome/browser/web_applications/system_web_app_manager.h b/chrome/browser/web_applications/system_web_app_manager.h index c40ea69..50cacdae 100644 --- a/chrome/browser/web_applications/system_web_app_manager.h +++ b/chrome/browser/web_applications/system_web_app_manager.h
@@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/one_shot_event.h" #include "chrome/browser/web_applications/components/pending_app_manager.h" +#include "chrome/browser/web_applications/components/system_web_app_types.h" #include "chrome/browser/web_applications/components/web_application_info.h" #include "components/prefs/pref_change_registrar.h" #include "ui/gfx/geometry/size.h" @@ -43,29 +44,6 @@ class OsIntegrationManager; class AppRegistryController; -// An enum that lists the different System Apps that exist. Can be used to -// retrieve the App ID from the underlying Web App system. -enum class SystemAppType { - SETTINGS, - CAMERA, - TERMINAL, - MEDIA, - HELP, - PRINT_MANAGEMENT, - SCANNING, - DIAGNOSTICS, - CONNECTIVITY_DIAGNOSTICS, -#if !defined(OFFICIAL_BUILD) - FILE_MANAGER, - TELEMETRY, - SAMPLE, -#endif // !defined(OFFICIAL_BUILD) - - // When adding a new System App, add a corresponding histogram suffix in - // WebAppSystemAppInternalName (histograms.xml). The suffix name should match - // the App's |internal_name|. This is for reporting per-app install results. -}; - using OriginTrialsMap = std::map<url::Origin, std::vector<std::string>>; using WebApplicationInfoFactory = base::RepeatingCallback<std::unique_ptr<WebApplicationInfo>()>; @@ -285,8 +263,6 @@ base::flat_map<SystemAppType, SystemAppInfo> system_app_infos_; - base::flat_map<AppId, SystemAppType> app_id_to_app_type_; - PrefService* const pref_service_; // Used to install, uninstall, and update apps. Should outlive this class. @@ -303,7 +279,6 @@ PrefChangeRegistrar local_state_pref_change_registrar_; base::WeakPtrFactory<SystemWebAppManager> weak_ptr_factory_{this}; - }; } // namespace web_app
diff --git a/chrome/browser/web_applications/system_web_app_manager_unittest.cc b/chrome/browser/web_applications/system_web_app_manager_unittest.cc index f5d0450..dc0bfd84 100644 --- a/chrome/browser/web_applications/system_web_app_manager_unittest.cc +++ b/chrome/browser/web_applications/system_web_app_manager_unittest.cc
@@ -221,7 +221,6 @@ install_manager().Start(); install_finalizer().Start(); - } void TearDown() override { @@ -363,7 +362,6 @@ std::unique_ptr<TestWebAppUiManager> test_ui_manager_; TestWebAppUrlLoader* url_loader_ = nullptr; std::unique_ptr<TestDataRetrieverFactory> test_data_retriever_factory_; - }; // Test that System Apps do install with the feature enabled. @@ -1051,4 +1049,35 @@ } } +TEST_F(SystemWebAppManagerTest, IsSWABeforeSync) { + system_web_app_manager().SetUpdatePolicy( + SystemWebAppManager::UpdatePolicy::kOnVersionChange); + + InitEmptyRegistrar(); + + // Set up and install a baseline + base::flat_map<SystemAppType, SystemAppInfo> system_apps; + system_apps.emplace( + SystemAppType::SETTINGS, + SystemAppInfo(kSettingsAppInternalName, AppUrl1(), + base::BindRepeating(&GetApp1WebApplicationInfo))); + system_web_app_manager().SetSystemAppsForTesting(system_apps); + + system_web_app_manager().set_current_version(base::Version("1.0.0.0")); + StartAndWaitForAppsToSynchronize(); + EXPECT_TRUE( + system_web_app_manager().IsSystemWebApp(GenerateAppIdFromURL(AppUrl1()))); + + auto unsynced_system_web_app_manager = + std::make_unique<TestSystemWebAppManager>(profile()); + + unsynced_system_web_app_manager->SetSubsystems( + &pending_app_manager(), &controller().registrar(), + &controller().sync_bridge(), &ui_manager(), + &controller().os_integration_manager()); + + EXPECT_TRUE(unsynced_system_web_app_manager->IsSystemWebApp( + GenerateAppIdFromURL(AppUrl1()))); +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/test/web_app_install_observer.cc b/chrome/browser/web_applications/test/web_app_install_observer.cc index a60dcc90..cb444dd 100644 --- a/chrome/browser/web_applications/test/web_app_install_observer.cc +++ b/chrome/browser/web_applications/test/web_app_install_observer.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/web_applications/test/web_app_install_observer.h" + #include <memory> #include "base/run_loop.h" @@ -122,6 +123,11 @@ app_installed_with_os_hooks_delegate_ = delegate; } +void WebAppInstallObserver::SetWebAppWillBeUninstalledDelegate( + WebAppWillBeUninstalledDelegate delegate) { + app_will_be_uninstalled_delegate_ = delegate; +} + void WebAppInstallObserver::SetWebAppUninstalledDelegate( WebAppUninstalledDelegate delegate) { app_uninstalled_delegate_ = delegate; @@ -162,6 +168,11 @@ } void WebAppInstallObserver::OnWebAppWillBeUninstalled(const AppId& app_id) { + if (app_will_be_uninstalled_delegate_) + app_will_be_uninstalled_delegate_.Run(app_id); +} + +void WebAppInstallObserver::OnWebAppUninstalled(const AppId& app_id) { listening_for_uninstall_app_ids_.erase(app_id); if (!listening_for_uninstall_app_ids_.empty()) return;
diff --git a/chrome/browser/web_applications/test/web_app_install_observer.h b/chrome/browser/web_applications/test/web_app_install_observer.h index b01ad494..0e781c6 100644 --- a/chrome/browser/web_applications/test/web_app_install_observer.h +++ b/chrome/browser/web_applications/test/web_app_install_observer.h
@@ -79,6 +79,11 @@ void SetWebAppInstalledWithOsHooksDelegate( WebAppInstalledWithOsHooksDelegate delegate); + using WebAppWillBeUninstalledDelegate = + base::RepeatingCallback<void(const AppId& app_id)>; + void SetWebAppWillBeUninstalledDelegate( + WebAppWillBeUninstalledDelegate delegate); + using WebAppUninstalledDelegate = base::RepeatingCallback<void(const AppId& app_id)>; void SetWebAppUninstalledDelegate(WebAppUninstalledDelegate delegate); @@ -99,6 +104,7 @@ void OnWebAppsWillBeUpdatedFromSync( const std::vector<const WebApp*>& new_apps_state) override; void OnWebAppWillBeUninstalled(const AppId& app_id) override; + void OnWebAppUninstalled(const AppId& app_id) override; void OnWebAppProfileWillBeDeleted(const AppId& app_id) override; private: @@ -127,6 +133,7 @@ WebAppInstalledDelegate app_installed_delegate_; WebAppInstalledWithOsHooksDelegate app_installed_with_os_hooks_delegate_; WebAppWillBeUpdatedFromSyncDelegate app_will_be_updated_from_sync_delegate_; + WebAppWillBeUninstalledDelegate app_will_be_uninstalled_delegate_; WebAppUninstalledDelegate app_uninstalled_delegate_; WebAppProfileWillBeDeletedDelegate app_profile_will_be_deleted_delegate_;
diff --git a/chrome/browser/web_applications/test/web_app_uninstall_waiter.cc b/chrome/browser/web_applications/test/web_app_uninstall_waiter.cc index 62d79b97..ae3c13f 100644 --- a/chrome/browser/web_applications/test/web_app_uninstall_waiter.cc +++ b/chrome/browser/web_applications/test/web_app_uninstall_waiter.cc
@@ -18,7 +18,7 @@ run_loop_.Run(); } -void WebAppUninstallWaiter::OnWebAppWillBeUninstalled(const AppId& app_id) { +void WebAppUninstallWaiter::OnWebAppUninstalled(const AppId& app_id) { if (app_id == app_id_) run_loop_.Quit(); }
diff --git a/chrome/browser/web_applications/test/web_app_uninstall_waiter.h b/chrome/browser/web_applications/test/web_app_uninstall_waiter.h index 428e938..3fe2a342 100644 --- a/chrome/browser/web_applications/test/web_app_uninstall_waiter.h +++ b/chrome/browser/web_applications/test/web_app_uninstall_waiter.h
@@ -20,7 +20,7 @@ void Wait(); // AppRegistrarObserver: - void OnWebAppWillBeUninstalled(const AppId& app_id) final; + void OnWebAppUninstalled(const AppId& app_id) final; private: AppId app_id_;
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index 7f7d1e9..4561a2e95 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc
@@ -271,6 +271,12 @@ launch_query_params_ = std::move(launch_query_params); } +WebApp::ClientData::ClientData() = default; + +WebApp::ClientData::~ClientData() = default; + +WebApp::ClientData::ClientData(const ClientData& client_data) = default; + WebApp::SyncFallbackData::SyncFallbackData() = default; WebApp::SyncFallbackData::~SyncFallbackData() = default; @@ -362,6 +368,12 @@ if (app.chromeos_data_.has_value()) out << app.chromeos_data_.value(); + out << " system_web_app: " << app.client_data_.system_web_app_data.has_value() + << std::endl; + + if (app.client_data_.system_web_app_data.has_value()) + out << app.client_data_.system_web_app_data.value(); + return out; } @@ -416,7 +428,8 @@ app.install_time_, app.run_on_os_login_mode_, app.sync_fallback_data_, - app.url_handlers_ + app.url_handlers_, + app.client_data_.system_web_app_data // clang-format on ); };
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index 664aa58..ce617f6 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -14,6 +14,7 @@ #include "chrome/browser/web_applications/components/web_app_chromeos_data.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_id.h" +#include "chrome/browser/web_applications/components/web_app_system_web_app_data.h" #include "chrome/browser/web_applications/components/web_application_info.h" #include "components/services/app_service/public/cpp/file_handler.h" #include "components/services/app_service/public/cpp/protocol_handler_info.h" @@ -75,6 +76,17 @@ return chromeos_data_; } + struct ClientData { + ClientData(); + ~ClientData(); + ClientData(const ClientData& client_data); + base::Optional<WebAppSystemWebAppData> system_web_app_data; + }; + + const ClientData& client_data() const { return client_data_; } + + ClientData* client_data() { return &client_data_; } + // Locally installed apps have shortcuts installed on various UI surfaces. // If app isn't locally installed, it is excluded from UIs and only listed as // a part of user's app library. @@ -262,6 +274,7 @@ RunOnOsLoginMode run_on_os_login_mode_ = RunOnOsLoginMode::kUndefined; SyncFallbackData sync_fallback_data_; apps::UrlHandlers url_handlers_; + ClientData client_data_; // New fields must be added to |operator==| and |operator<<|. };
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc index ca2a663e..ddec201 100644 --- a/chrome/browser/web_applications/web_app_database.cc +++ b/chrome/browser/web_applications/web_app_database.cc
@@ -12,9 +12,12 @@ #include "base/callback.h" #include "base/containers/contains.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/web_applications/components/system_web_app_types.h" +#include "chrome/browser/web_applications/components/web_app_chromeos_data.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_utils.h" #include "chrome/browser/web_applications/components/web_application_info.h" +#include "chrome/browser/web_applications/system_web_app_manager.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_database_factory.h" #include "chrome/browser/web_applications/web_app_proto_utils.h" @@ -198,6 +201,16 @@ mutable_chromeos_data->set_is_disabled(chromeos_data.is_disabled); } + if (web_app.client_data().system_web_app_data.has_value()) { + auto& swa_data = web_app.client_data().system_web_app_data.value(); + + auto* mutable_swa_data = + local_data->mutable_client_data()->mutable_system_web_app_data(); + mutable_swa_data->set_system_app_type( + static_cast<::web_app::SystemWebAppDataProto_SystemAppType>( + swa_data.system_app_type)); + } + if (web_app.run_on_os_login_mode() != RunOnOsLoginMode::kUndefined) { local_data->set_user_run_on_os_login_mode( ToWebAppProtoRunOnOsLoginMode(web_app.run_on_os_login_mode())); @@ -403,6 +416,14 @@ web_app->SetWebAppChromeOsData(std::move(chromeos_data)); } + if (local_data.client_data().has_system_web_app_data()) { + WebAppSystemWebAppData& swa_data = + web_app->client_data()->system_web_app_data.emplace(); + + swa_data.system_app_type = static_cast<SystemAppType>( + local_data.client_data().system_web_app_data().system_app_type()); + } + // Optional fields: if (local_data.has_launch_query_params()) web_app->SetLaunchQueryParams(local_data.launch_query_params());
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc index 8b2e0444..37dbf42 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.cc +++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -4,8 +4,8 @@ #include "chrome/browser/web_applications/web_app_install_finalizer.h" -#include <utility> #include <map> +#include <utility> #include <vector> #include "base/bind.h" @@ -25,6 +25,7 @@ #include "chrome/browser/web_applications/components/web_app_prefs_utils.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/components/web_app_shortcuts_menu.h" +#include "chrome/browser/web_applications/components/web_app_system_web_app_data.h" #include "chrome/browser/web_applications/components/web_application_info.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_icon_manager.h" @@ -164,6 +165,13 @@ if (options.chromeos_data.has_value()) web_app->SetWebAppChromeOsData(options.chromeos_data.value()); + // `WebApp::system_web_app_data` has a default value already. Only override if + // the caller provided a new value. + if (options.system_web_app_data.has_value()) { + web_app->client_data()->system_web_app_data = + options.system_web_app_data.value(); + } + web_app->SetAdditionalSearchTerms(web_app_info.additional_search_terms); web_app->AddSource(source); web_app->SetIsInSyncInstall(false); @@ -209,9 +217,10 @@ DCHECK(!GetWebAppRegistrar().GetAppById(app_id)); icon_manager_->DeleteData( - app_id, base::BindOnce(&WebAppInstallFinalizer::OnIconsDataDeleted, - weak_ptr_factory_.GetWeakPtr(), app_id, - std::move(callback))); + app_id, + base::BindOnce( + &WebAppInstallFinalizer::OnIconsDataDeletedAndWebAppUninstalled, + weak_ptr_factory_.GetWeakPtr(), app_id, std::move(callback))); } void WebAppInstallFinalizer::UninstallExternalWebApp( @@ -330,9 +339,10 @@ update->DeleteApp(app_id); icon_manager_->DeleteData( - app_id, base::BindOnce(&WebAppInstallFinalizer::OnIconsDataDeleted, - weak_ptr_factory_.GetWeakPtr(), app_id, - std::move(callback))); + app_id, + base::BindOnce( + &WebAppInstallFinalizer::OnIconsDataDeletedAndWebAppUninstalled, + weak_ptr_factory_.GetWeakPtr(), app_id, std::move(callback))); } void WebAppInstallFinalizer::UninstallWebAppOrRemoveSource( @@ -427,10 +437,11 @@ std::move(update), std::move(commit_callback)); } -void WebAppInstallFinalizer::OnIconsDataDeleted( +void WebAppInstallFinalizer::OnIconsDataDeletedAndWebAppUninstalled( const AppId& app_id, UninstallWebAppCallback callback, bool success) { + registrar().NotifyWebAppUninstalled(app_id); std::move(callback).Run(success); }
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h index ac8add9..c2833c5 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.h +++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -76,9 +76,9 @@ std::unique_ptr<WebApp> web_app, bool success); - void OnIconsDataDeleted(const AppId& app_id, - UninstallWebAppCallback callback, - bool success); + void OnIconsDataDeletedAndWebAppUninstalled(const AppId& app_id, + UninstallWebAppCallback callback, + bool success); void OnDatabaseCommitCompletedForInstall(InstallFinalizedCallback callback, AppId app_id, bool success);
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc index db84f09..9437afc 100644 --- a/chrome/browser/web_applications/web_app_install_task.cc +++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -4,6 +4,8 @@ #include <utility> +#include "chrome/browser/web_applications/components/install_finalizer.h" +#include "chrome/browser/web_applications/components/web_app_system_web_app_data.h" #include "chrome/browser/web_applications/web_app_install_task.h" #include "base/bind.h" @@ -196,6 +198,26 @@ GetWeakPtr())); } +void UpdateFinalizerClientData( + const base::Optional<InstallManager::InstallParams>& params, + InstallFinalizer::FinalizeOptions* options) { + if (params) { + if (IsChromeOs()) { + options->chromeos_data.emplace(); + options->chromeos_data->show_in_launcher = + params->add_to_applications_menu; + options->chromeos_data->show_in_search = params->add_to_search; + options->chromeos_data->show_in_management = params->add_to_management; + options->chromeos_data->is_disabled = params->is_disabled; + } + if (params->system_app_type.has_value()) { + options->system_web_app_data.emplace(); + options->system_web_app_data->system_app_type = + params->system_app_type.value(); + } + } +} + void WebAppInstallTask::InstallWebAppFromInfo( std::unique_ptr<WebApplicationInfo> web_application_info, ForInstallableSite for_installable_site, @@ -217,15 +239,9 @@ InstallFinalizer::FinalizeOptions options; options.install_source = install_source; options.locally_installed = true; - if (IsChromeOs() && install_params_) { - options.chromeos_data.emplace(); - options.chromeos_data->show_in_launcher = - install_params_->add_to_applications_menu; - options.chromeos_data->show_in_search = install_params_->add_to_search; - options.chromeos_data->show_in_management = - install_params_->add_to_management; - options.chromeos_data->is_disabled = install_params_->is_disabled; - } + + UpdateFinalizerClientData(install_params_, &options); + install_finalizer_->FinalizeInstall(*web_application_info, options, std::move(callback)); } @@ -355,8 +371,8 @@ bool WebAppInstallTask::ShouldStopInstall() const { // Install should stop early if WebContents is being destroyed. - // WebAppInstallTask::WebContentsDestroyed will get called eventually and the - // callback will be invoked at that point. + // WebAppInstallTask::WebContentsDestroyed will get called eventually and + // the callback will be invoked at that point. return !web_contents() || web_contents()->IsBeingDestroyed(); } @@ -545,8 +561,8 @@ ForInstallableSite for_installable_site, bool skip_page_favicons) { #if BUILDFLAG(IS_CHROMEOS_ASH) - // Background installations are not a user-triggered installs, and thus cannot - // be sent to the store. + // Background installations are not a user-triggered installs, and thus + // cannot be sent to the store. if (base::FeatureList::IsEnabled(features::kApkWebAppInstalls) && for_installable_site == ForInstallableSite::kYes && !background_installation_ && manifest) { @@ -685,9 +701,10 @@ DCHECK(web_app_info); - // The old BookmarkApp Sync System uses |WebAppInstallTask::OnIconsRetrieved|. - // The new WebApp USS System has no sync wars and it doesn't need to preserve - // icons. |is_for_sync| is always false for USS. + // The old BookmarkApp Sync System uses + // |WebAppInstallTask::OnIconsRetrieved|. The new WebApp USS System has no + // sync wars and it doesn't need to preserve icons. |is_for_sync| is always + // false for USS. FilterAndResizeIconsGenerateMissing(web_app_info.get(), &icons_map); if (background_installation_) { @@ -748,16 +765,11 @@ if (install_params_) { finalize_options.locally_installed = install_params_->locally_installed; - if (IsChromeOs()) { - finalize_options.chromeos_data.emplace(); - finalize_options.chromeos_data->show_in_launcher = - install_params_->add_to_applications_menu; - finalize_options.chromeos_data->show_in_search = - install_params_->add_to_search; - finalize_options.chromeos_data->show_in_management = - install_params_->add_to_management; - finalize_options.chromeos_data->is_disabled = - install_params_->is_disabled; + UpdateFinalizerClientData(install_params_, &finalize_options); + + if (install_params_->user_display_mode != DisplayMode::kUndefined) { + web_app_info_copy.open_as_window = + install_params_->user_display_mode != DisplayMode::kBrowser; } }
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc index 602d62f..7b2a463b 100644 --- a/chrome/browser/web_applications/web_app_sync_bridge.cc +++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -535,6 +535,9 @@ // still registered at this stage. for (const AppId& app_id : update_local_data->apps_to_delete) { registrar_->NotifyWebAppWillBeUninstalled(app_id); + // TODO(https://crbug.com/1162349): Have the + // InstallDelegate::UninstallWebAppsAfterSync occur after OS hooks are + // uninstalled. os_integration_manager().UninstallAllOsHooks(app_id, base::DoNothing()); } @@ -556,6 +559,8 @@ // locally and not needed by other sources. We need to clean up disk data // (icons). if (!apps_unregistered.empty()) { + // TODO(https://crbug.com/1162349): Instead of calling this now, have this + // call occur after OS hooks are uninstalled. install_delegate_->UninstallWebAppsAfterSync(std::move(apps_unregistered), base::DoNothing()); }
diff --git a/chrome/browser/web_launch/web_launch_files_helper.cc b/chrome/browser/web_launch/web_launch_files_helper.cc index c3787f6..d753f06 100644 --- a/chrome/browser/web_launch/web_launch_files_helper.cc +++ b/chrome/browser/web_launch/web_launch_files_helper.cc
@@ -21,7 +21,7 @@ #include "mojo/public/cpp/bindings/associated_remote.h" #include "storage/browser/file_system/external_mount_points.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom.h" #include "url/origin.h" namespace web_launch { @@ -93,7 +93,7 @@ class EntriesBuilder { public: EntriesBuilder( - std::vector<blink::mojom::NativeFileSystemEntryPtr>* entries_ref, + std::vector<blink::mojom::FileSystemAccessEntryPtr>* entries_ref, content::WebContents* web_contents, const GURL& launch_url) : entries_ref_(entries_ref), @@ -125,7 +125,7 @@ } private: - std::vector<blink::mojom::NativeFileSystemEntryPtr>* entries_ref_; + std::vector<blink::mojom::FileSystemAccessEntryPtr>* entries_ref_; scoped_refptr<content::NativeFileSystemEntryFactory> entry_factory_; content::NativeFileSystemEntryFactory::BindingContext context_; };
diff --git a/chrome/browser/web_launch/web_launch_files_helper.h b/chrome/browser/web_launch/web_launch_files_helper.h index 5d84b7e..645b4fb 100644 --- a/chrome/browser/web_launch/web_launch_files_helper.h +++ b/chrome/browser/web_launch/web_launch_files_helper.h
@@ -14,7 +14,7 @@ #include "content/public/browser/native_file_system_entry_factory.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-forward.h" #include "third_party/blink/public/mojom/web_launch/web_launch.mojom.h" #include "url/gurl.h" @@ -34,7 +34,7 @@ // // Note: The lifetime of this class is tied to the WebContents it is attached // to. However, in general it will be destroyed before the WebContents, when the -// helper sends the NativeFileSystemEntries to the renderer. +// helper sends the FileSystemAccessEntries to the renderer. class WebLaunchFilesHelper : public content::WebContentsObserver, public content::WebContentsUserData<WebLaunchFilesHelper> { @@ -73,7 +73,7 @@ void MaybeSendLaunchEntries(); // The entries causing the launch (may be empty). - std::vector<blink::mojom::NativeFileSystemEntryPtr> launch_entries_; + std::vector<blink::mojom::FileSystemAccessEntryPtr> launch_entries_; // The url the launch entries are for. GURL launch_url_;
diff --git a/chrome/browser/webapps/chrome_webapps_client.cc b/chrome/browser/webapps/chrome_webapps_client.cc index ab941f77..9c0b640b 100644 --- a/chrome/browser/webapps/chrome_webapps_client.cc +++ b/chrome/browser/webapps/chrome_webapps_client.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/webapps/chrome_webapps_client.h" #include "base/logging.h" -#include "build/build_config.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/ssl/security_state_tab_helper.h" #include "components/webapps/installable/installable_metrics.h" @@ -70,16 +69,21 @@ return WebappInstallSource::COUNT; } +#if defined(OS_ANDROID) bool ChromeWebappsClient::IsInstallationInProgress( content::WebContents* web_contents, const GURL& manifest_url) { -#if defined(OS_ANDROID) return WebApkInstallService::Get(web_contents->GetBrowserContext()) ->IsInstallInProgress(manifest_url); -#else - NOTREACHED(); - return false; -#endif } +bool ChromeWebappsClient::CanShowAppBanners( + content::WebContents* web_contents) { + TabAndroid* tab = TabAndroid::FromWebContents(web_contents); + return tab && static_cast<android::TabWebContentsDelegateAndroid*>( + tab->web_contents()->GetDelegate()) + ->CanShowAppBanners(); +} +#endif + } // namespace webapps
diff --git a/chrome/browser/webapps/chrome_webapps_client.h b/chrome/browser/webapps/chrome_webapps_client.h index 55d0d60..0227c9b 100644 --- a/chrome/browser/webapps/chrome_webapps_client.h +++ b/chrome/browser/webapps/chrome_webapps_client.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_WEBAPPS_CHROME_WEBAPPS_CLIENT_H_ #include "base/no_destructor.h" +#include "build/build_config.h" #include "components/webapps/webapps_client.h" namespace webapps { @@ -24,8 +25,11 @@ content::WebContents* web_contents) override; WebappInstallSource GetInstallSource(content::WebContents* web_contents, InstallTrigger trigger) override; +#if defined(OS_ANDROID) bool IsInstallationInProgress(content::WebContents* web_contents, const GURL& manifest_url) override; + bool CanShowAppBanners(content::WebContents* web_contents) override; +#endif private: friend base::NoDestructor<ChromeWebappsClient>;
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index f0f079d..f432b374 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -43,11 +43,12 @@ return base::nullopt; } - // Auto advance to Touch ID if the authenticator has a matching credential + // Auto advance to the platform authenticator if it has a matching credential // for the (possibly empty) allow list. if (base::Contains(candidate_transports, device::FidoTransportProtocol::kInternal) && - transport_availability.has_recognized_mac_touch_id_credential) { + *transport_availability + .has_recognized_platform_authenticator_credential) { return device::FidoTransportProtocol::kInternal; } @@ -67,9 +68,10 @@ return base::nullopt; } - // Auto-advancing to Touch ID based on credential availability has been - // handled above. Hence, at this point it does not have a matching credential - // and should not be advanced to, because it would fail immediately. + // Auto-advancing to platform authenticator based on credential availability + // has been handled above. Hence, at this point it does not have a matching + // credential and should not be advanced to, because it would fail + // immediately. if (*last_used_transport == device::FidoTransportProtocol::kInternal) { return base::nullopt; } @@ -183,7 +185,7 @@ SetCurrentStep(Step::kTransportSelection); break; case AuthenticatorTransport::kInternal: - StartTouchIdFlow(); + StartPlatformAuthenticatorFlow(); break; case AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy: EnsureBleAdapterIsPoweredAndContinueWithCable(); @@ -279,43 +281,48 @@ DCHECK_EQ(current_step(), Step::kUsbInsertAndActivate); } -void AuthenticatorRequestDialogModel::StartTouchIdFlow() { - // Never try Touch ID if the request is known in advance to fail. Proceed to - // a special error screen instead. +void AuthenticatorRequestDialogModel::StartPlatformAuthenticatorFlow() { + // Never try the platform authenticator if the request is known in advance to + // fail. Proceed to a special error screen instead. if (transport_availability_.request_type == - device::FidoRequestHandlerBase::RequestType::kGetAssertion && - !transport_availability_.has_recognized_mac_touch_id_credential) { - SetCurrentStep(Step::kErrorInternalUnrecognized); - return; + device::FidoRequestHandlerBase::RequestType::kGetAssertion) { + DCHECK(transport_availability_ + .has_recognized_platform_authenticator_credential); + if (!*transport_availability_ + .has_recognized_platform_authenticator_credential) { + SetCurrentStep(Step::kErrorInternalUnrecognized); + return; + } } if (transport_availability_.request_type == device::FidoRequestHandlerBase::RequestType::kMakeCredential && transport_availability_.is_off_the_record_context) { - SetCurrentStep(Step::kTouchIdIncognitoSpeedBump); + SetCurrentStep(Step::kPlatformAuthenticatorOffTheRecordInterstitial); return; } - HideDialogAndTryTouchId(); + HideDialogAndDispatchToPlatformAuthenticator(); } -void AuthenticatorRequestDialogModel::HideDialogAndTryTouchId() { +void AuthenticatorRequestDialogModel:: + HideDialogAndDispatchToPlatformAuthenticator() { HideDialog(); auto& authenticators = ephemeral_state_.saved_authenticators_.authenticator_list(); - auto touch_id_authenticator_it = + auto platform_authenticator_it = std::find_if(authenticators.begin(), authenticators.end(), [](const auto& authenticator) { return authenticator.transport == device::FidoTransportProtocol::kInternal; }); - if (touch_id_authenticator_it == authenticators.end()) { + if (platform_authenticator_it == authenticators.end()) { return; } - DispatchRequestAsync(&*touch_id_authenticator_it); + DispatchRequestAsync(&*platform_authenticator_it); } void AuthenticatorRequestDialogModel::Cancel() {
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index e072970ff..b1fb6da 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -72,8 +72,9 @@ kBlePowerOnAutomatic, kBlePowerOnManual, - // Touch ID. - kTouchIdIncognitoSpeedBump, + // Let the user confirm that they want to create a platform credential in an + // off-the-record browsing context. + kPlatformAuthenticatorOffTheRecordInterstitial, // Phone as a security key. kCableActivate, @@ -236,17 +237,18 @@ // Valid action when at step: kUsbInsert. void TryUsbDevice(); - // Tries to use Touch ID -- either because the request requires it or because - // the user told us to. May show an error for unrecognized credential, or an - // Incognito mode interstitial, or proceed straight to the Touch ID prompt. + // Tries to dispatch to the platform authenticator -- either because the + // request requires it or because the user told us to. May show an error for + // unrecognized credential, or an Incognito mode interstitial, or proceed + // straight to the platform authenticator prompt. // // Valid action when at all steps. - void StartTouchIdFlow(); + void StartPlatformAuthenticatorFlow(); - // Proceeds straight to the Touch ID prompt. + // Proceeds straight to the platform authenticator prompt. // // Valid action when at all steps. - void HideDialogAndTryTouchId(); + void HideDialogAndDispatchToPlatformAuthenticator(); // Cancels the flow as a result of the user clicking `Cancel` on the UI. // @@ -308,8 +310,8 @@ // credential because of insufficient storage. void OnAuthenticatorStorageFull(); - // To be called when the user denies consent, e.g. by clicking "Cancel" on the - // system Touch ID prompt. + // To be called when the user denies consent, e.g. by canceling out of the + // system's platform authenticator prompt. void OnUserConsentDenied(); // To be called when the user clicks "Cancel" in the native Windows UI. @@ -426,9 +428,10 @@ // to connect to or conduct WebAuthN request to via the WebAuthN UI. base::Optional<std::string> selected_authenticator_id_; - // Transport type and id of Mac TouchId and BLE authenticators are cached so - // that the WebAuthN request for the corresponding authenticators can be - // dispatched lazily after the user interacts with the UI element. + // Stores a list of |AuthenticatorReference| values such that a request can + // be dispatched dispatched after some UI interaction. This is useful for + // platform authenticators (and Windows) where dispatch to the authenticator + // immediately results in modal UI to appear. ObservableAuthenticatorList saved_authenticators_; // responses_ contains possible accounts to select between.
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc index 27104be..50147383 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
@@ -97,7 +97,7 @@ TEST_F(AuthenticatorRequestDialogModelTest, TransportAutoSelection) { enum class TransportAvailabilityParam { - kHasTouchIdCredential, + kHasPlatformCredential, kHasWinNativeAuthenticator, kHasCableExtension, }; @@ -127,7 +127,7 @@ {RequestType::kGetAssertion, {AuthenticatorTransport::kInternal}, {}, - {TransportAvailabilityParam::kHasTouchIdCredential}, + {TransportAvailabilityParam::kHasPlatformCredential}, Step::kNotStarted}, {RequestType::kGetAssertion, {AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy}, @@ -154,7 +154,7 @@ {RequestType::kGetAssertion, kAllTransports, AuthenticatorTransport::kUsbHumanInterfaceDevice, - {TransportAvailabilityParam::kHasTouchIdCredential}, + {TransportAvailabilityParam::kHasPlatformCredential}, Step::kNotStarted}, // The KeyChain does not contain an allowed Touch ID credential. @@ -197,13 +197,13 @@ {RequestType::kGetAssertion, {AuthenticatorTransport::kUsbHumanInterfaceDevice}, base::nullopt, - {TransportAvailabilityParam::kHasTouchIdCredential}, + {TransportAvailabilityParam::kHasPlatformCredential}, Step::kUsbInsertAndActivate}, {RequestType::kGetAssertion, {AuthenticatorTransport::kUsbHumanInterfaceDevice, AuthenticatorTransport::kNearFieldCommunication}, base::nullopt, - {TransportAvailabilityParam::kHasTouchIdCredential}, + {TransportAvailabilityParam::kHasPlatformCredential}, Step::kTransportSelection}, // If caBLE is one of the allowed transports, it has second-highest @@ -287,9 +287,9 @@ transports_info.request_type = test_case.request_type; transports_info.available_transports = test_case.available_transports; - if (base::Contains(test_case.transport_params, - TransportAvailabilityParam::kHasTouchIdCredential)) - transports_info.has_recognized_mac_touch_id_credential = true; + transports_info.has_recognized_platform_authenticator_credential = + base::Contains(test_case.transport_params, + TransportAvailabilityParam::kHasPlatformCredential); if (base::Contains( test_case.transport_params,
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 85952d7..9d4fbfe 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1609934346-e8075e70051f1cf5498240cc23c791e5411fb4de.profdata +chrome-linux-master-1609977525-bd4b14e8a3331d25b143eda6470a50c1959dbc36.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index fecb2e5..a3a29da 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1609945018-bd62f654af21e53a7b023fe22e6c76c3ab0d03ca.profdata +chrome-win32-master-1609977525-c6db9a955637b88d5134fbbd1dcc888c0f8d0465.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index ec79b5a..255143d 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1609945018-70431859900ba317039e4e8fedf6f4732373dd6e.profdata +chrome-win64-master-1609966729-f10b4c89116276ddc6d9d2f94d5dc003384dbd78.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 50bb6d8..bdc743b 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -165,7 +165,6 @@ "//chrome/common/net", "//chrome/common/privacy_budget", "//chrome/common/profiler", - "//chrome/common/qr_code_generator", "//chrome/common/search:mojo_bindings", "//chrome/installer/util:with_no_strings", "//components/cast_certificate",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 33b93446..298bf428 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -882,6 +882,11 @@ const base::Feature kWebShare{"WebShare", base::FEATURE_ENABLED_BY_DEFAULT}; #endif +#if defined(OS_MAC) +// Enables Web Share (navigator.share) for macOS +const base::Feature kWebShare{"WebShare", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + // Enables setting time limit for Chrome and PWA's on child user device. // Requires |kPerAppTimeLimits| to be enabled. #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index ee33fee..2593dc3 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -601,7 +601,7 @@ extern const base::Feature kWebRtcRemoteEventLogGzipped; #endif -#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) +#if defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_MAC) COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kWebShare; #endif
diff --git a/chrome/common/extensions/docs/examples/README.chromium b/chrome/common/extensions/docs/examples/README.chromium deleted file mode 100644 index 034abed..0000000 --- a/chrome/common/extensions/docs/examples/README.chromium +++ /dev/null
@@ -1,5 +0,0 @@ -Name: Extensions examples -URL: None -License: Apache 2.0, MIT, X11, BSD, and GPL v2 licenses -License File: NOT_SHIPPED -Security Critical: no
diff --git a/chrome/common/extensions/docs/examples/README.txt b/chrome/common/extensions/docs/examples/README.txt deleted file mode 100644 index de6e8e3..0000000 --- a/chrome/common/extensions/docs/examples/README.txt +++ /dev/null
@@ -1,7 +0,0 @@ -Chromium Extension Examples - -The directory structure is as follows: -* api/ - trivial extensions focused on a single API package -* howto/ - simple extensions showing how to perform a particular task -* tutorials/ - multi-step walkthroughs referenced inline in the docs -* extensions/ - full featured extensions spanning multiple API packages
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic/icon.png b/chrome/common/extensions/docs/examples/api/bookmarks/basic/icon.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/bookmarks/basic/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json b/chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json deleted file mode 100644 index 2135c3cbf..0000000 --- a/chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "My Bookmarks", - "version": "1.1", - "description": "A browser action with a popup dump of all bookmarks, including search, add, edit and delete.", - "permissions": [ - "bookmarks" - ], - "browser_action": { - "default_title": "My Bookmarks", - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2, - "content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'" -}
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html b/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html deleted file mode 100644 index 2a3370b..0000000 --- a/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html +++ /dev/null
@@ -1,13 +0,0 @@ -<html> -<head> - <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> - <script src="popup.js"></script> -</head> -<body style="width: 400px"> - <div>Search Bookmarks: <input id="search"></div> - <div id="bookmarks"></div> - <div id="editdialog"></div> - <div id="deletedialog"></div> - <div id="adddialog"></div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.js b/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.js deleted file mode 100644 index ca72daaf..0000000 --- a/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.js +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Search the bookmarks when entering the search keyword. -$(function() { - $('#search').change(function() { - $('#bookmarks').empty(); - dumpBookmarks($('#search').val()); - }); -}); -// Traverse the bookmark tree, and print the folder and nodes. -function dumpBookmarks(query) { - var bookmarkTreeNodes = chrome.bookmarks.getTree( - function(bookmarkTreeNodes) { - $('#bookmarks').append(dumpTreeNodes(bookmarkTreeNodes, query)); - }); -} -function dumpTreeNodes(bookmarkNodes, query) { - var list = $('<ul>'); - var i; - for (i = 0; i < bookmarkNodes.length; i++) { - list.append(dumpNode(bookmarkNodes[i], query)); - } - return list; -} -function dumpNode(bookmarkNode, query) { - if (bookmarkNode.title) { - if (query && !bookmarkNode.children) { - if (String(bookmarkNode.title).indexOf(query) == -1) { - return $('<span></span>'); - } - } - var anchor = $('<a>'); - anchor.attr('href', bookmarkNode.url); - anchor.text(bookmarkNode.title); - /* - * When clicking on a bookmark in the extension, a new tab is fired with - * the bookmark url. - */ - anchor.click(function() { - chrome.tabs.create({url: bookmarkNode.url}); - }); - var span = $('<span>'); - var options = bookmarkNode.children ? - $('<span>[<a href="#" id="addlink">Add</a>]</span>') : - $('<span>[<a id="editlink" href="#">Edit</a> <a id="deletelink" ' + - 'href="#">Delete</a>]</span>'); - var edit = bookmarkNode.children ? $('<table><tr><td>Name</td><td>' + - '<input id="title"></td></tr><tr><td>URL</td><td><input id="url">' + - '</td></tr></table>') : $('<input>'); - // Show add and edit links when hover over. - span.hover(function() { - span.append(options); - $('#deletelink').click(function() { - $('#deletedialog').empty().dialog({ - autoOpen: false, - title: 'Confirm Deletion', - resizable: false, - height: 140, - modal: true, - overlay: { - backgroundColor: '#000', - opacity: 0.5 - }, - buttons: { - 'Yes, Delete It!': function() { - chrome.bookmarks.remove(String(bookmarkNode.id)); - span.parent().remove(); - $(this).dialog('destroy'); - }, - Cancel: function() { - $(this).dialog('destroy'); - } - } - }).dialog('open'); - }); - $('#addlink').click(function() { - $('#adddialog').empty().append(edit).dialog({autoOpen: false, - closeOnEscape: true, title: 'Add New Bookmark', modal: true, - buttons: { - 'Add' : function() { - chrome.bookmarks.create({parentId: bookmarkNode.id, - title: $('#title').val(), url: $('#url').val()}); - $('#bookmarks').empty(); - $(this).dialog('destroy'); - window.dumpBookmarks(); - }, - 'Cancel': function() { - $(this).dialog('destroy'); - } - }}).dialog('open'); - }); - $('#editlink').click(function() { - edit.val(anchor.text()); - $('#editdialog').empty().append(edit).dialog({autoOpen: false, - closeOnEscape: true, title: 'Edit Title', modal: true, - show: 'slide', buttons: { - 'Save': function() { - chrome.bookmarks.update(String(bookmarkNode.id), { - title: edit.val() - }); - anchor.text(edit.val()); - options.show(); - $(this).dialog('destroy'); - }, - 'Cancel': function() { - $(this).dialog('destroy'); - } - }}).dialog('open'); - }); - options.fadeIn(); - }, - // unhover - function() { - options.remove(); - }).append(anchor); - } - var li = $(bookmarkNode.title ? '<li>' : '<div>').append(span); - if (bookmarkNode.children && bookmarkNode.children.length > 0) { - li.append(dumpTreeNodes(bookmarkNode.children, query)); - } - return li; -} - -document.addEventListener('DOMContentLoaded', function () { - dumpBookmarks(); -});
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.js b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.js deleted file mode 100644 index 80f6ec79..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.js +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright (c) 2011 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. - -// Called when the user clicks on the browser action. -chrome.browserAction.onClicked.addListener(function(tab) { - // No tabs or host permissions needed! - console.log('Turning ' + tab.url + ' red!'); - chrome.tabs.executeScript({ - code: 'document.body.style.backgroundColor="red"' - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json deleted file mode 100644 index b901108..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "name": "Page Redder", - "description": "Make the current page red", - "version": "2.0", - "permissions": [ - "activeTab" - ], - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "browser_action": { - "default_title": "Make this page red" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/print/background.js b/chrome/common/extensions/docs/examples/api/browserAction/print/background.js deleted file mode 100644 index 92209e1..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/print/background.js +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Called when the user clicks on the browser action. -chrome.browserAction.onClicked.addListener(function(tab) { - chrome.tabs.executeScript( - tab.id, - {code: 'window.print();'}); -});
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json deleted file mode 100644 index e6feef4..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "Print this page", - "description": "Adds a print button to the browser.", - "version": "1.2", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "permissions": [ - "activeTab" - ], - "browser_action": { - "default_title": "Print this page", - "default_icon": "print_16x16.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.png b/chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.png deleted file mode 100644 index 360c8eb..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.js b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.js deleted file mode 100644 index 9289794..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.js +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2011 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. - -'use strict'; - -chrome.runtime.onInstalled.addListener(function() { - chrome.storage.sync.set({number: 1}, function() { - console.log('The number is set to 1.'); - }); -}); - -function updateIcon() { - chrome.storage.sync.get('number', function(data) { - var current = data.number; - chrome.browserAction.setIcon({path: 'icon' + current + '.png'}); - current++; - if (current > 5) - current = 1; - chrome.storage.sync.set({number: current}, function() { - console.log('The number is set to ' + current); - }); - }); -}; - -chrome.browserAction.onClicked.addListener(updateIcon); -updateIcon();
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.png deleted file mode 100644 index da75c5f..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.png deleted file mode 100644 index a60a52d..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.png deleted file mode 100644 index 217e30f..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.png deleted file mode 100644 index 32dfa18..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json deleted file mode 100644 index 597e0036..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "name": "A browser action which changes its icon when clicked", - "description": "Click browser action icon to change color!", - "version": "1.3", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "permissions": ["storage"], - "browser_action": { - "name": "Click to change the icon's color" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.png b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.png deleted file mode 100644 index 46819c7..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json deleted file mode 100644 index cecb2bc..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "name": "A browser action with a popup that changes the page color", - "description": "Change the current page color", - "version": "1.0", - "permissions": [ - "activeTab" - ], - "browser_action": { - "default_title": "Set this page's color.", - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html deleted file mode 100644 index bf1b42b..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html +++ /dev/null
@@ -1,55 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Set Page Color Popup</title> - <style> - body { - overflow: hidden; - margin: 0px; - padding: 0px; - background: white; - } - - div:first-child { - margin-top: 0px; - } - - div { - cursor: pointer; - text-align: center; - padding: 1px 3px; - font-family: sans-serif; - font-size: 0.8em; - width: 100px; - margin-top: 1px; - background: #cccccc; - } - div:hover { - background: #aaaaaa; - } - #red { - border: 1px solid red; - color: red; - } - #blue { - border: 1px solid blue; - color: blue; - } - #green { - border: 1px solid green; - color: green; - } - #yellow { - border: 1px solid yellow; - color: yellow; - } - </style> - <script src="popup.js"></script> - </head> - <body> - <div id="red">red</div> - <div id="blue">blue</div> - <div id="green">green</div> - <div id="yellow">yellow</div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.js b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.js deleted file mode 100644 index 3c04801..0000000 --- a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.js +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -function click(e) { - chrome.tabs.executeScript(null, - {code:"document.body.style.backgroundColor='" + e.target.id + "'"}); - window.close(); -} - -document.addEventListener('DOMContentLoaded', function () { - var divs = document.querySelectorAll('div'); - for (var i = 0; i < divs.length; i++) { - divs[i].addEventListener('click', click); - } -});
diff --git a/chrome/common/extensions/docs/examples/api/browsingData/basic/icon.png b/chrome/common/extensions/docs/examples/api/browsingData/basic/icon.png deleted file mode 100644 index 8a72625..0000000 --- a/chrome/common/extensions/docs/examples/api/browsingData/basic/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browsingData/basic/manifest.json b/chrome/common/extensions/docs/examples/api/browsingData/basic/manifest.json deleted file mode 100644 index d228729..0000000 --- a/chrome/common/extensions/docs/examples/api/browsingData/basic/manifest.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name" : "BrowsingData API: Basics", - "version" : "1.1", - "description" : "A trivial usage example.", - "permissions": [ - "browsingData" - ], - "browser_action": { - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.css b/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.css deleted file mode 100644 index 52b1af4..0000000 --- a/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.css +++ /dev/null
@@ -1,72 +0,0 @@ -/** - * Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -body { - margin: 5px 10px 10px; -} - -h1 { - color: #53637D; - font: 26px/1.2 Helvetica, sans-serif; - font-size: 200%; - margin: 0; - padding-bottom: 4px; - text-shadow: white 0 1px 2px; -} - -label { - color: #222; - font: 18px/1.4 Helvetica, sans-serif; - margin: 0.5em 0; - display: inline-block; -} - -form { - transition: transform 0.25s ease; - width: 563px; -} - -button { - display: block; - border-radius: 2px; - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); - -webkit-user-select: none; - background: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5); - border: 1px solid #AAA; - color: #444; - margin-bottom: 0; - min-width: 4em; - padding: 3px 12px; - margin-top: 0; - font-size: 1.1em; -} - -.overlay { - display: block; - text-align: center; - position: absolute; - left: 50%; - top: 50%; - width: 500px; - padding: 20px; - margin: -40px 0 0 -270px; - opacity: 0; - background: rgba(0, 0, 0, 0.75); - border-radius: 5px; - color: #FFF; - font: 1.5em/1.2 Helvetica Neue, sans-serif; - transition: all 1.0s ease; - transform: scale(0); -} - -.overlay a { - color: #FFF; -} - -.overlay.visible { - opacity: 1; - transform: scale(1); -}
diff --git a/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.html b/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.html deleted file mode 100644 index 64ed40e..0000000 --- a/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Popup</title> - <link href="popup.css" rel="stylesheet"> - <script src="popup.js"></script> - </head> - <body> - <h1>BrowsingData API Sample</h1> - <div role="main"> - <form> - <label for="timeframe">Remove all browsing data from:</label> - <select id="timeframe"> - <option value="hour">the past hour</option> - <option value="day">the past day</option> - <option value="week">the past week</option> - <option value="4weeks">the past four weeks</option> - <option value="forever">the beginning of time</option> - </select> - <button id="button">OBLITERATE!</button> - </form> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.js b/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.js deleted file mode 100644 index ee7b2654..0000000 --- a/chrome/common/extensions/docs/examples/api/browsingData/basic/popup.js +++ /dev/null
@@ -1,137 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * This class wraps the popup's form, and performs the proper clearing of data - * based on the user's selections. It depends on the form containing a single - * select element with an id of 'timeframe', and a single button with an id of - * 'button'. When you write actual code you should probably be a little more - * accepting of variance, but this is just a sample app. :) - * - * Most of this is boilerplate binding the controller to the UI. The bits that - * specifically will be useful when using the BrowsingData API are contained in - * `parseMilliseconds_`, `handleCallback_`, and `handleClick_`. - * - * @constructor - */ -var PopupController = function () { - this.button_ = document.getElementById('button'); - this.timeframe_ = document.getElementById('timeframe'); - this.addListeners_(); -}; - -PopupController.prototype = { - /** - * A cached reference to the button element. - * - * @type {Element} - * @private - */ - button_: null, - - /** - * A cached reference to the select element. - * - * @type {Element} - * @private - */ - timeframe_: null, - - /** - * Adds event listeners to the button in order to capture a user's click, and - * perform some action in response. - * - * @private - */ - addListeners_: function () { - this.button_.addEventListener('click', this.handleClick_.bind(this)); - }, - - /** - * Given a string, return milliseconds since epoch. If the string isn't - * valid, returns undefined. - * - * @param {string} timeframe One of 'hour', 'day', 'week', '4weeks', or - * 'forever'. - * @returns {number} Milliseconds since epoch. - * @private - */ - parseMilliseconds_: function (timeframe) { - var now = new Date().getTime(); - var milliseconds = { - 'hour': 60 * 60 * 1000, - 'day': 24 * 60 * 60 * 1000, - 'week': 7 * 24 * 60 * 60 * 1000, - '4weeks': 4 * 7 * 24 * 60 * 60 * 1000 - }; - - if (milliseconds[timeframe]) - return now - milliseconds[timeframe]; - - if (timeframe === 'forever') - return 0; - - return null; - }, - - /** - * Handle a success/failure callback from the `browsingData` API methods, - * updating the UI appropriately. - * - * @private - */ - handleCallback_: function () { - var success = document.createElement('div'); - success.classList.add('overlay'); - success.setAttribute('role', 'alert'); - success.textContent = 'Data has been cleared.'; - document.body.appendChild(success); - - setTimeout(function() { success.classList.add('visible'); }, 10); - setTimeout(function() { - if (close === false) - success.classList.remove('visible'); - else - window.close(); - }, 4000); - }, - - /** - * When a user clicks the button, this method is called: it reads the current - * state of `timeframe_` in order to pull a timeframe, then calls the clearing - * method with appropriate arguments. - * - * @private - */ - handleClick_: function () { - var removal_start = this.parseMilliseconds_(this.timeframe_.value); - if (removal_start !== undefined) { - this.button_.setAttribute('disabled', 'disabled'); - this.button_.innerText = 'Clearing...'; - chrome.browsingData.remove( - {'since': removal_start}, { - 'appcache': true, - 'cache': true, - 'cacheStorage': true, - 'cookies': true, - 'downloads': true, - 'fileSystems': true, - 'formData': true, - 'history': true, - 'indexedDB': true, - 'localStorage': true, - 'serverBoundCertificates': true, - 'serviceWorkers': true, - 'pluginData': true, - 'passwords': true, - 'webSQL': true - }, - this.handleCallback_.bind(this)); - } - } -}; - -document.addEventListener('DOMContentLoaded', function () { - window.PC = new PopupController(); -});
diff --git a/chrome/common/extensions/docs/examples/api/commands/background.js b/chrome/common/extensions/docs/examples/api/commands/background.js deleted file mode 100644 index 5661f24..0000000 --- a/chrome/common/extensions/docs/examples/api/commands/background.js +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -chrome.commands.onCommand.addListener(function(command) { - console.log('onCommand event received for message: ', command); -});
diff --git a/chrome/common/extensions/docs/examples/api/commands/browser_action.html b/chrome/common/extensions/docs/examples/api/commands/browser_action.html deleted file mode 100644 index 499473a..0000000 --- a/chrome/common/extensions/docs/examples/api/commands/browser_action.html +++ /dev/null
@@ -1 +0,0 @@ -This is a sample browser action popup. \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/commands/manifest.json b/chrome/common/extensions/docs/examples/api/commands/manifest.json deleted file mode 100644 index a22622c..0000000 --- a/chrome/common/extensions/docs/examples/api/commands/manifest.json +++ /dev/null
@@ -1,28 +0,0 @@ -{ - "name": "Sample Extension Commands extension", - "description": "Press Ctrl+Shift+F to open the browser action popup, press Ctrl+Shift+Y to send an event.", - "version": "1.0", - "manifest_version": 2, - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "browser_action": { - "default_popup": "browser_action.html" - }, - "commands": { - "toggle-feature": { - "suggested_key": { - "default": "Ctrl+Shift+Y", - "mac": "MacCtrl+Shift+Y" - }, - "description": "Send a 'toggle-feature' event to the extension" - }, - "_execute_browser_action": { - "suggested_key": { - "default": "Ctrl+Shift+F", - "mac": "MacCtrl+Shift+F" - } - } - } -}
diff --git a/chrome/common/extensions/docs/examples/api/contentSettings/contentSettings.png b/chrome/common/extensions/docs/examples/api/contentSettings/contentSettings.png deleted file mode 100644 index 80657a9..0000000 --- a/chrome/common/extensions/docs/examples/api/contentSettings/contentSettings.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/contentSettings/manifest.json b/chrome/common/extensions/docs/examples/api/contentSettings/manifest.json deleted file mode 100644 index adf1daef..0000000 --- a/chrome/common/extensions/docs/examples/api/contentSettings/manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name" : "Content settings", - "version" : "0.2", - "description" : "Shows the content settings for the current site.", - "permissions": [ "contentSettings", "tabs" ], - "browser_action": { - "default_icon": "contentSettings.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/contentSettings/popup.html b/chrome/common/extensions/docs/examples/api/contentSettings/popup.html deleted file mode 100644 index ae2be39..0000000 --- a/chrome/common/extensions/docs/examples/api/contentSettings/popup.html +++ /dev/null
@@ -1,80 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Popup</title> - <style> - dt { white-space: nowrap } - </style> - <script src="popup.js"></script> - </head> - <body> - <fieldset> - <dl> - <dt><label for="cookies">Cookies: </label></dt> - <dd><select id="cookies" disabled> - <option value="allow">Allow</option> - <option value="session_only">Session only</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="images">Images: </label></dt> - <dd><select id="images" disabled> - <option value="allow">Allow</option> - <option value="block">Block</option> - </select> - <dt><label for="javascript">Javascript: </label></dt> - <dd><select id="javascript" disabled> - <option value="allow">Allow</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="location">Location: </label></dt> - <dd><select id="location" disabled> - <option value="allow">Allow</option> - <option value="ask">Ask</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="plugins">Plugins: </label></dt> - <dd><select id="plugins" disabled> - <option value="allow">Allow</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="popups">Pop-ups: </label></dt> - <dd><select id="popups" disabled> - <option value="allow">Allow</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="notifications">Notifications: </label></dt> - <dd><select id="notifications" disabled> - <option value="allow">Allow</option> - <option value="ask">Ask</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="microphone">Microphone: </label></dt> - <dd><select id="microphone" disabled> - <option value="allow">Allow</option> - <option value="ask">Ask</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="camera">Camera: </label></dt> - <dd><select id="camera" disabled> - <option value="allow">Allow</option> - <option value="ask">Ask</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="unsandboxedPlugins">Unsandboxed plugin access: </label></dt> - <dd><select id="unsandboxedPlugins" disabled> - <option value="allow">Allow</option> - <option value="ask">Ask</option> - <option value="block">Block</option> - </select></dd> - <dt><label for="automaticDownloads">Automatic Downloads: </label></dt> - <dd><select id="automaticDownloads" disabled> - <option value="allow">Allow</option> - <option value="ask">Ask</option> - <option value="block">Block</option> - </select></dd> - </dl> - </fieldset> - - - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/contentSettings/popup.js b/chrome/common/extensions/docs/examples/api/contentSettings/popup.js deleted file mode 100644 index c623a8c..0000000 --- a/chrome/common/extensions/docs/examples/api/contentSettings/popup.js +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright (c) 2011 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. - -var incognito; -var url; - -function settingChanged() { - var type = this.id; - var setting = this.value; - var pattern = /^file:/.test(url) ? url : url.replace(/\/[^\/]*?$/, '/*'); - console.log(type+' setting for '+pattern+': '+setting); - // HACK: [type] is not recognised by the docserver's sample crawler, so - // mention an explicit - // type: chrome.contentSettings.cookies.set - See http://crbug.com/299634 - chrome.contentSettings[type].set({ - 'primaryPattern': pattern, - 'setting': setting, - 'scope': (incognito ? 'incognito_session_only' : 'regular') - }); -} - -document.addEventListener('DOMContentLoaded', function () { - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - var current = tabs[0]; - incognito = current.incognito; - url = current.url; - var types = [ - 'cookies', 'images', 'javascript', 'location', 'popups', 'notifications', - 'microphone', 'camera', 'automaticDownloads' - ]; - types.forEach(function(type) { - // HACK: [type] is not recognised by the docserver's sample crawler, so - // mention an explicit - // type: chrome.contentSettings.cookies.get - See http://crbug.com/299634 - chrome.contentSettings[type] && chrome.contentSettings[type].get({ - 'primaryUrl': url, - 'incognito': incognito - }, - function(details) { - document.getElementById(type).disabled = false; - document.getElementById(type).value = details.setting; - }); - }); - }); - - var selects = document.querySelectorAll('select'); - for (var i = 0; i < selects.length; i++) { - selects[i].addEventListener('change', settingChanged); - } -}); -
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json b/chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json deleted file mode 100644 index c59cec1..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json +++ /dev/null
@@ -1,10 +0,0 @@ -{ - "name": "Context Menus Sample", - "description": "Shows some of the features of the Context Menus API", - "version": "0.6", - "permissions": ["contextMenus"], - "background": { - "scripts": ["sample.js"] - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js b/chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js deleted file mode 100644 index be77af0..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright (c) 2010 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. - -// A generic onclick callback function. -function genericOnClick(info, tab) { - console.log("item " + info.menuItemId + " was clicked"); - console.log("info: " + JSON.stringify(info)); - console.log("tab: " + JSON.stringify(tab)); -} - -// Create one test item for each context type. -var contexts = ["page","selection","link","editable","image","video", - "audio"]; -for (var i = 0; i < contexts.length; i++) { - var context = contexts[i]; - var title = "Test '" + context + "' menu item"; - var id = chrome.contextMenus.create({"title": title, "contexts":[context], - "onclick": genericOnClick}); - console.log("'" + context + "' item:" + id); -} - - -// Create a parent item and two children. -var parent = chrome.contextMenus.create({"title": "Test parent item"}); -var child1 = chrome.contextMenus.create( - {"title": "Child 1", "parentId": parent, "onclick": genericOnClick}); -var child2 = chrome.contextMenus.create( - {"title": "Child 2", "parentId": parent, "onclick": genericOnClick}); -console.log("parent:" + parent + " child1:" + child1 + " child2:" + child2); - - -// Create some radio items. -function radioOnClick(info, tab) { - console.log("radio item " + info.menuItemId + - " was clicked (previous checked state was " + - info.wasChecked + ")"); -} -var radio1 = chrome.contextMenus.create({"title": "Radio 1", "type": "radio", - "onclick":radioOnClick}); -var radio2 = chrome.contextMenus.create({"title": "Radio 2", "type": "radio", - "onclick":radioOnClick}); -console.log("radio1:" + radio1 + " radio2:" + radio2); - - -// Create some checkbox items. -function checkboxOnClick(info, tab) { - console.log(JSON.stringify(info)); - console.log("checkbox item " + info.menuItemId + - " was clicked, state is now: " + info.checked + - "(previous state was " + info.wasChecked + ")"); - -} -var checkbox1 = chrome.contextMenus.create( - {"title": "Checkbox1", "type": "checkbox", "onclick":checkboxOnClick}); -var checkbox2 = chrome.contextMenus.create( - {"title": "Checkbox2", "type": "checkbox", "onclick":checkboxOnClick}); -console.log("checkbox1:" + checkbox1 + " checkbox2:" + checkbox2); - - -// Intentionally create an invalid item, to show off error checking in the -// create callback. -console.log("About to try creating an invalid item - an error about " + - "item 999 should show up"); -chrome.contextMenus.create({"title": "Oops", "parentId":999}, function() { - if (chrome.extension.lastError) { - console.log("Got expected error: " + chrome.extension.lastError.message); - } -});
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/event_page/manifest.json b/chrome/common/extensions/docs/examples/api/contextMenus/event_page/manifest.json deleted file mode 100644 index 8279823d..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/event_page/manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name": "Context Menus Sample (with Event Page)", - "description": "Shows some of the features of the Context Menus API using an event page", - "version": "0.7", - "permissions": ["contextMenus"], - "background": { - "persistent": false, - "scripts": ["sample.js"] - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/event_page/sample.js b/chrome/common/extensions/docs/examples/api/contextMenus/event_page/sample.js deleted file mode 100644 index 227dd0c..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/event_page/sample.js +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The onClicked callback function. -function onClickHandler(info, tab) { - if (info.menuItemId == "radio1" || info.menuItemId == "radio2") { - console.log("radio item " + info.menuItemId + - " was clicked (previous checked state was " + - info.wasChecked + ")"); - } else if (info.menuItemId == "checkbox1" || info.menuItemId == "checkbox2") { - console.log(JSON.stringify(info)); - console.log("checkbox item " + info.menuItemId + - " was clicked, state is now: " + info.checked + - " (previous state was " + info.wasChecked + ")"); - - } else { - console.log("item " + info.menuItemId + " was clicked"); - console.log("info: " + JSON.stringify(info)); - console.log("tab: " + JSON.stringify(tab)); - } -}; - -chrome.contextMenus.onClicked.addListener(onClickHandler); - -// Set up context menu tree at install time. -chrome.runtime.onInstalled.addListener(function() { - // Create one test item for each context type. - var contexts = ["page","selection","link","editable","image","video", - "audio"]; - for (var i = 0; i < contexts.length; i++) { - var context = contexts[i]; - var title = "Test '" + context + "' menu item"; - var id = chrome.contextMenus.create({"title": title, "contexts":[context], - "id": "context" + context}); - console.log("'" + context + "' item:" + id); - } - - // Create a parent item and two children. - chrome.contextMenus.create({"title": "Test parent item", "id": "parent"}); - chrome.contextMenus.create( - {"title": "Child 1", "parentId": "parent", "id": "child1"}); - chrome.contextMenus.create( - {"title": "Child 2", "parentId": "parent", "id": "child2"}); - console.log("parent child1 child2"); - - // Create some radio items. - chrome.contextMenus.create({"title": "Radio 1", "type": "radio", - "id": "radio1"}); - chrome.contextMenus.create({"title": "Radio 2", "type": "radio", - "id": "radio2"}); - console.log("radio1 radio2"); - - // Create some checkbox items. - chrome.contextMenus.create( - {"title": "Checkbox1", "type": "checkbox", "id": "checkbox1"}); - chrome.contextMenus.create( - {"title": "Checkbox2", "type": "checkbox", "id": "checkbox2"}); - console.log("checkbox1 checkbox2"); - - // Intentionally create an invalid item, to show off error checking in the - // create callback. - console.log("About to try creating an invalid item - an error about " + - "duplicate item child1 should show up"); - chrome.contextMenus.create({"title": "Oops", "id": "child1"}, function() { - if (chrome.extension.lastError) { - console.log("Got expected error: " + chrome.extension.lastError.message); - } - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/background.js b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/background.js deleted file mode 100644 index a70763d..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/background.js +++ /dev/null
@@ -1,51 +0,0 @@ -// 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. - -'use strict'; -// Add a listener to create the initial context menu items, -// context menu items only need to be created at runtime.onInstalled -chrome.runtime.onInstalled.addListener(function() { - for (let key of Object.keys(kLocales)) { - chrome.contextMenus.create({ - id: key, - title: kLocales[key], - type: 'normal', - contexts: ['selection'], - }); - } -}); - -chrome.contextMenus.onClicked.addListener(function(item, tab) { - let url = - 'https://google.' + item.menuItemId + '/search?q=' + item.selectionText; - chrome.tabs.create({url: url, index: tab.index + 1}); -}); - -chrome.storage.onChanged.addListener(function(list, sync) { - let newlyDisabled = []; - let newlyEnabled = []; - let currentRemoved = list.removedContextMenu.newValue; - let oldRemoved = list.removedContextMenu.oldValue || []; - for (let key of Object.keys(kLocales)) { - if (currentRemoved.includes(key) && !oldRemoved.includes(key)) { - newlyDisabled.push(key); - } else if (oldRemoved.includes(key) && !currentRemoved.includes(key)) { - newlyEnabled.push({ - id: key, - title: kLocales[key] - }); - } - } - for (let locale of newlyEnabled) { - chrome.contextMenus.create({ - id: locale.id, - title: locale.title, - type: 'normal', - contexts: ['selection'], - }); - } - for (let locale of newlyDisabled) { - chrome.contextMenus.remove(locale); - } -});
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle128.png b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle128.png deleted file mode 100644 index cd1903dd..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle16.png b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle16.png deleted file mode 100644 index 77540d1..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle48.png b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle48.png deleted file mode 100644 index d01e5d9..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/globalGoogle48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/locales.js b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/locales.js deleted file mode 100644 index f02e6ae..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/locales.js +++ /dev/null
@@ -1,18 +0,0 @@ -// 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. - -const kLocales = { - 'com.au': 'Australia', - 'com.br': 'Brazil', - 'ca': 'Canada', - 'cn': 'China', - 'fr': 'France', - 'it': 'Italy', - 'co.in': 'India', - 'co.jp': 'Japan', - 'com.ms': 'Mexico', - 'ru': 'Russia', - 'co.za': 'South Africa', - 'co.uk': 'United Kingdom' -};
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/manifest.json b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/manifest.json deleted file mode 100644 index df745d5..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/manifest.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name": "Global Google Search", - "description": "Use the context menu to search a different country's Google", - "version": "1.0", - "manifest_version": 2, - "options_page": "options.html", - "permissions": ["contextMenus", "storage"], - "background": { - "scripts": [ "locales.js", "background.js"], - "persistent": false - }, - "browser_action": { - "default_popup": "options.html" - }, - "icons": { - "16": "globalGoogle16.png", - "48": "globalGoogle48.png", - "128": "globalGoogle128.png" - } -}
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/options.html b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/options.html deleted file mode 100644 index b6dcbbaf7..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/options.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Global Context Search</title> - <style> - body { - min-width: 300px; - font-size: 15px; - } - input { - margin: 5px; - outline: none; - } - </style> - </head> - - <body> - <h2>Global Google Search</h2> - <h3>Country Options</h3> - <form id="form"> - </form> - <button type='submit' value='Submit' id='optionsSubmit'>Submit</button> - </body> - <script src="locales.js"></script> - <script src="options.js"></script> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/options.js b/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/options.js deleted file mode 100644 index 3b30672..0000000 --- a/chrome/common/extensions/docs/examples/api/contextMenus/global_context_search/options.js +++ /dev/null
@@ -1,40 +0,0 @@ -// 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. - -function createForm() { - chrome.storage.sync.get(['removedContextMenu'], function(list) { - let removed = list.removedContextMenu || []; - let form = document.getElementById('form'); - for (let key of Object.keys(kLocales)) { - let div = document.createElement('div'); - let checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.checked = true; - if (removed.includes(key)) { - checkbox.checked = false; - } - checkbox.name = key; - checkbox.value = kLocales[key]; - let span = document.createElement('span'); - span.textContent = kLocales[key]; - div.appendChild(checkbox); - div.appendChild(span); - form.appendChild(div); - } - }); -} - -createForm(); - -document.getElementById('optionsSubmit').onclick = function() { - let checkboxes = document.getElementsByTagName('input'); - let removed = []; - for (i=0; i<checkboxes.length; i++) { - if (checkboxes[i].checked == false) { - removed.push(checkboxes[i].name); - } - } - chrome.storage.sync.set({removedContextMenu: removed}); - window.close(); -}
diff --git a/chrome/common/extensions/docs/examples/api/cookies/background.js b/chrome/common/extensions/docs/examples/api/cookies/background.js deleted file mode 100644 index 0e42ddb5..0000000 --- a/chrome/common/extensions/docs/examples/api/cookies/background.js +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -chrome.cookies.onChanged.addListener(function(info) { - console.log("onChanged" + JSON.stringify(info)); -}); - -function focusOrCreateTab(url) { - chrome.windows.getAll({"populate":true}, function(windows) { - var existing_tab = null; - for (var i in windows) { - var tabs = windows[i].tabs; - for (var j in tabs) { - var tab = tabs[j]; - if (tab.url == url) { - existing_tab = tab; - break; - } - } - } - if (existing_tab) { - chrome.tabs.update(existing_tab.id, {"selected":true}); - } else { - chrome.tabs.create({"url":url, "selected":true}); - } - }); -} - -chrome.browserAction.onClicked.addListener(function(tab) { - var manager_url = chrome.extension.getURL("manager.html"); - focusOrCreateTab(manager_url); -});
diff --git a/chrome/common/extensions/docs/examples/api/cookies/cookie.png b/chrome/common/extensions/docs/examples/api/cookies/cookie.png deleted file mode 100644 index 21b5073..0000000 --- a/chrome/common/extensions/docs/examples/api/cookies/cookie.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/cookies/manager.html b/chrome/common/extensions/docs/examples/api/cookies/manager.html deleted file mode 100644 index b1d93b50..0000000 --- a/chrome/common/extensions/docs/examples/api/cookies/manager.html +++ /dev/null
@@ -1,43 +0,0 @@ -<html> -<head> -<style> -table { - border-collapse:collapse; -} - -td { - border: 1px solid black; - padding-left: 5px; -} - -td.button { - border: none; -} - -td.cookie_count { - text-align: right; -} - -</style> -<script src="manager.js"></script> -</head> -<body> - <h2>Cookies! ... Nom Nom Nom...</h2> - <button id="remove_button">DELETE ALL!</button> - <div id="filter_div"> - Filter: <input id="filter" type="text"> - <button>x</button> - </div> - <br /> - <div id="summary_div"> - Showing <span id="filter_count"></span> of <span id="total_count"></span> cookie domains. - <span id="delete_all_button"></span> - </div> - <br /> - <table id="cookies"> - <tr class="header"> - <th>Name</th> - <th>#Cookies</th> - </tr> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/cookies/manager.js b/chrome/common/extensions/docs/examples/api/cookies/manager.js deleted file mode 100644 index bcf3500..0000000 --- a/chrome/common/extensions/docs/examples/api/cookies/manager.js +++ /dev/null
@@ -1,260 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -if (!chrome.cookies) { - chrome.cookies = chrome.experimental.cookies; -} - -// A simple Timer class. -function Timer() { - this.start_ = new Date(); - - this.elapsed = function() { - return (new Date()) - this.start_; - } - - this.reset = function() { - this.start_ = new Date(); - } -} - -// Compares cookies for "key" (name, domain, etc.) equality, but not "value" -// equality. -function cookieMatch(c1, c2) { - return (c1.name == c2.name) && (c1.domain == c2.domain) && - (c1.hostOnly == c2.hostOnly) && (c1.path == c2.path) && - (c1.secure == c2.secure) && (c1.httpOnly == c2.httpOnly) && - (c1.session == c2.session) && (c1.storeId == c2.storeId); -} - -// Returns an array of sorted keys from an associative array. -function sortedKeys(array) { - var keys = []; - for (var i in array) { - keys.push(i); - } - keys.sort(); - return keys; -} - -// Shorthand for document.querySelector. -function select(selector) { - return document.querySelector(selector); -} - -// An object used for caching data about the browser's cookies, which we update -// as notifications come in. -function CookieCache() { - this.cookies_ = {}; - - this.reset = function() { - this.cookies_ = {}; - } - - this.add = function(cookie) { - var domain = cookie.domain; - if (!this.cookies_[domain]) { - this.cookies_[domain] = []; - } - this.cookies_[domain].push(cookie); - }; - - this.remove = function(cookie) { - var domain = cookie.domain; - if (this.cookies_[domain]) { - var i = 0; - while (i < this.cookies_[domain].length) { - if (cookieMatch(this.cookies_[domain][i], cookie)) { - this.cookies_[domain].splice(i, 1); - } else { - i++; - } - } - if (this.cookies_[domain].length == 0) { - delete this.cookies_[domain]; - } - } - }; - - // Returns a sorted list of cookie domains that match |filter|. If |filter| is - // null, returns all domains. - this.getDomains = function(filter) { - var result = []; - sortedKeys(this.cookies_).forEach(function(domain) { - if (!filter || domain.indexOf(filter) != -1) { - result.push(domain); - } - }); - return result; - } - - this.getCookies = function(domain) { - return this.cookies_[domain]; - }; -} - - -var cache = new CookieCache(); - - -function removeAllForFilter() { - var filter = select("#filter").value; - var timer = new Timer(); - cache.getDomains(filter).forEach(function(domain) { - removeCookiesForDomain(domain); - }); -} - -function removeAll() { - var all_cookies = []; - cache.getDomains().forEach(function(domain) { - cache.getCookies(domain).forEach(function(cookie) { - all_cookies.push(cookie); - }); - }); - cache.reset(); - var count = all_cookies.length; - var timer = new Timer(); - for (var i = 0; i < count; i++) { - removeCookie(all_cookies[i]); - } - timer.reset(); - chrome.cookies.getAll({}, function(cookies) { - for (var i in cookies) { - cache.add(cookies[i]); - removeCookie(cookies[i]); - } - }); -} - -function removeCookie(cookie) { - var url = "http" + (cookie.secure ? "s" : "") + "://" + cookie.domain + - cookie.path; - chrome.cookies.remove({"url": url, "name": cookie.name}); -} - -function removeCookiesForDomain(domain) { - var timer = new Timer(); - cache.getCookies(domain).forEach(function(cookie) { - removeCookie(cookie); - }); -} - -function resetTable() { - var table = select("#cookies"); - while (table.rows.length > 1) { - table.deleteRow(table.rows.length - 1); - } -} - -var reload_scheduled = false; - -function scheduleReloadCookieTable() { - if (!reload_scheduled) { - reload_scheduled = true; - setTimeout(reloadCookieTable, 250); - } -} - -function reloadCookieTable() { - reload_scheduled = false; - - var filter = select("#filter").value; - - var domains = cache.getDomains(filter); - - select("#filter_count").innerText = domains.length; - select("#total_count").innerText = cache.getDomains().length; - - select("#delete_all_button").innerHTML = ""; - if (domains.length) { - var button = document.createElement("button"); - button.onclick = removeAllForFilter; - button.innerText = "delete all " + domains.length; - select("#delete_all_button").appendChild(button); - } - - resetTable(); - var table = select("#cookies"); - - domains.forEach(function(domain) { - var cookies = cache.getCookies(domain); - var row = table.insertRow(-1); - row.insertCell(-1).innerText = domain; - var cell = row.insertCell(-1); - cell.innerText = cookies.length; - cell.setAttribute("class", "cookie_count"); - - var button = document.createElement("button"); - button.innerText = "delete"; - button.onclick = (function(dom){ - return function() { - removeCookiesForDomain(dom); - }; - }(domain)); - var cell = row.insertCell(-1); - cell.appendChild(button); - cell.setAttribute("class", "button"); - }); -} - -function focusFilter() { - select("#filter").focus(); -} - -function resetFilter() { - var filter = select("#filter"); - filter.focus(); - if (filter.value.length > 0) { - filter.value = ""; - reloadCookieTable(); - } -} - -var ESCAPE_KEY = 27; -window.onkeydown = function(event) { - if (event.keyCode == ESCAPE_KEY) { - resetFilter(); - } -} - -function listener(info) { - cache.remove(info.cookie); - if (!info.removed) { - cache.add(info.cookie); - } - scheduleReloadCookieTable(); -} - -function startListening() { - chrome.cookies.onChanged.addListener(listener); -} - -function stopListening() { - chrome.cookies.onChanged.removeListener(listener); -} - -function onload() { - focusFilter(); - var timer = new Timer(); - chrome.cookies.getAll({}, function(cookies) { - startListening(); - start = new Date(); - for (var i in cookies) { - cache.add(cookies[i]); - } - timer.reset(); - reloadCookieTable(); - }); -} - -document.addEventListener('DOMContentLoaded', function() { - onload(); - document.body.addEventListener('click', focusFilter); - document.querySelector('#remove_button').addEventListener('click', removeAll); - document.querySelector('#filter_div input').addEventListener( - 'input', reloadCookieTable); - document.querySelector('#filter_div button').addEventListener( - 'click', resetFilter); -});
diff --git a/chrome/common/extensions/docs/examples/api/cookies/manifest.json b/chrome/common/extensions/docs/examples/api/cookies/manifest.json deleted file mode 100644 index eb7da26..0000000 --- a/chrome/common/extensions/docs/examples/api/cookies/manifest.json +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "name" : "Cookie API Test Extension", - "version" : "0.8", - "description" : "Testing Cookie API", - "permissions": [ "cookies", "tabs", "http://*/*", "https://*/*" ], - "icons": { "16": "cookie.png", "48": "cookie.png", "128": "cookie.png" }, - "browser_action": { - "default_icon": "cookie.png" - }, - "background": { - "scripts": ["background.js"] - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/debugger/live-headers/background.js b/chrome/common/extensions/docs/examples/api/debugger/live-headers/background.js deleted file mode 100644 index 45c0bbe..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/live-headers/background.js +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -chrome.browserAction.onClicked.addListener(function(tab) { - chrome.debugger.attach({tabId:tab.id}, version, - onAttach.bind(null, tab.id)); -}); - -var version = "1.0"; - -function onAttach(tabId) { - if (chrome.runtime.lastError) { - alert(chrome.runtime.lastError.message); - return; - } - - chrome.windows.create( - {url: "headers.html?" + tabId, type: "popup", width: 800, height: 600}); -}
diff --git a/chrome/common/extensions/docs/examples/api/debugger/live-headers/headers.html b/chrome/common/extensions/docs/examples/api/debugger/live-headers/headers.html deleted file mode 100644 index 3c042e9..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/live-headers/headers.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- -Copyright (c) 2012 The Chromium Authors. All rights reserved. -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<html> -<head> -<style> -body { - font-family: monospace; - word-wrap: break-word; -} - -#container { - white-space: pre; -} - -.request { - border-top: 1px solid black; - margin-bottom: 10px; -} - -</style> - -<script src="headers.js"></script> -</head> - -<body> -<div id="container"></div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/debugger/live-headers/headers.js b/chrome/common/extensions/docs/examples/api/debugger/live-headers/headers.js deleted file mode 100644 index eac021e4..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/live-headers/headers.js +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var tabId = parseInt(window.location.search.substring(1)); - -window.addEventListener("load", function() { - chrome.debugger.sendCommand({tabId:tabId}, "Network.enable"); - chrome.debugger.onEvent.addListener(onEvent); -}); - -window.addEventListener("unload", function() { - chrome.debugger.detach({tabId:tabId}); -}); - -var requests = {}; - -function onEvent(debuggeeId, message, params) { - if (tabId != debuggeeId.tabId) - return; - - if (message == "Network.requestWillBeSent") { - var requestDiv = requests[params.requestId]; - if (!requestDiv) { - var requestDiv = document.createElement("div"); - requestDiv.className = "request"; - requests[params.requestId] = requestDiv; - var urlLine = document.createElement("div"); - urlLine.textContent = params.request.url; - requestDiv.appendChild(urlLine); - } - - if (params.redirectResponse) - appendResponse(params.requestId, params.redirectResponse); - - var requestLine = document.createElement("div"); - requestLine.textContent = "\n" + params.request.method + " " + - parseURL(params.request.url).path + " HTTP/1.1"; - requestDiv.appendChild(requestLine); - document.getElementById("container").appendChild(requestDiv); - } else if (message == "Network.responseReceived") { - appendResponse(params.requestId, params.response); - } -} - -function appendResponse(requestId, response) { - var requestDiv = requests[requestId]; - requestDiv.appendChild(formatHeaders(response.requestHeaders)); - - var statusLine = document.createElement("div"); - statusLine.textContent = "\nHTTP/1.1 " + response.status + " " + - response.statusText; - requestDiv.appendChild(statusLine); - requestDiv.appendChild(formatHeaders(response.headers)); -} - -function formatHeaders(headers) { - var text = ""; - for (name in headers) - text += name + ": " + headers[name] + "\n"; - var div = document.createElement("div"); - div.textContent = text; - return div; -} - -function parseURL(url) { - var result = {}; - var match = url.match( - /^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i); - if (!match) - return result; - result.scheme = match[1].toLowerCase(); - result.host = match[2]; - result.port = match[3]; - result.path = match[4] || "/"; - result.fragment = match[5]; - return result; -} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/debugger/live-headers/icon.png b/chrome/common/extensions/docs/examples/api/debugger/live-headers/icon.png deleted file mode 100644 index e35e317e..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/live-headers/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/debugger/live-headers/manifest.json b/chrome/common/extensions/docs/examples/api/debugger/live-headers/manifest.json deleted file mode 100644 index 19b6554..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/live-headers/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "Live HTTP headers", - "description": "Displays the live log with the http requests headers", - "version": "0.7", - "permissions": [ - "debugger" - ], - "background": { - "scripts": ["background.js"] - }, - "browser_action": { - "default_icon": "icon.png", - "default_title": "Live HTTP headers" - }, - "manifest_version": 2 -} -
diff --git a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/background.js b/chrome/common/extensions/docs/examples/api/debugger/pause-resume/background.js deleted file mode 100644 index c5399a4..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/background.js +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright (c) 2011 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. - -var attachedTabs = {}; -var version = "1.0"; - -chrome.debugger.onEvent.addListener(onEvent); -chrome.debugger.onDetach.addListener(onDetach); - -chrome.browserAction.onClicked.addListener(function(tab) { - var tabId = tab.id; - var debuggeeId = {tabId:tabId}; - - if (attachedTabs[tabId] == "pausing") - return; - - if (!attachedTabs[tabId]) - chrome.debugger.attach(debuggeeId, version, onAttach.bind(null, debuggeeId)); - else if (attachedTabs[tabId]) - chrome.debugger.detach(debuggeeId, onDetach.bind(null, debuggeeId)); -}); - -function onAttach(debuggeeId) { - if (chrome.runtime.lastError) { - alert(chrome.runtime.lastError.message); - return; - } - - var tabId = debuggeeId.tabId; - chrome.browserAction.setIcon({tabId: tabId, path:"debuggerPausing.png"}); - chrome.browserAction.setTitle({tabId: tabId, title:"Pausing JavaScript"}); - attachedTabs[tabId] = "pausing"; - chrome.debugger.sendCommand( - debuggeeId, "Debugger.enable", {}, - onDebuggerEnabled.bind(null, debuggeeId)); -} - -function onDebuggerEnabled(debuggeeId) { - chrome.debugger.sendCommand(debuggeeId, "Debugger.pause"); -} - -function onEvent(debuggeeId, method) { - var tabId = debuggeeId.tabId; - if (method == "Debugger.paused") { - attachedTabs[tabId] = "paused"; - chrome.browserAction.setIcon({tabId:tabId, path:"debuggerContinue.png"}); - chrome.browserAction.setTitle({tabId:tabId, title:"Resume JavaScript"}); - } -} - -function onDetach(debuggeeId) { - var tabId = debuggeeId.tabId; - delete attachedTabs[tabId]; - chrome.browserAction.setIcon({tabId:tabId, path:"debuggerPause.png"}); - chrome.browserAction.setTitle({tabId:tabId, title:"Pause JavaScript"}); -}
diff --git a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerContinue.png b/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerContinue.png deleted file mode 100644 index 3a344c8..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerContinue.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerPause.png b/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerPause.png deleted file mode 100644 index 8f7ff3d7..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerPause.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerPausing.png b/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerPausing.png deleted file mode 100644 index 68932fa..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/debuggerPausing.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/manifest.json b/chrome/common/extensions/docs/examples/api/debugger/pause-resume/manifest.json deleted file mode 100644 index fdc7e3d..0000000 --- a/chrome/common/extensions/docs/examples/api/debugger/pause-resume/manifest.json +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "name": "JavaScript pause/resume", - "description": "Pauses / resumes JavaScript execution", - "version": "0.7", - "permissions": [ - "debugger" - ], - "background": { - "scripts": ["background.js"] - }, - "browser_action": { - "default_icon": "debuggerPause.png", - "default_title": "Pause JavaScript" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/default_command_override/background.js b/chrome/common/extensions/docs/examples/api/default_command_override/background.js deleted file mode 100644 index 5d31360..0000000 --- a/chrome/common/extensions/docs/examples/api/default_command_override/background.js +++ /dev/null
@@ -1,17 +0,0 @@ -// 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. -chrome.commands.onCommand.addListener(function(command) { - chrome.tabs.query({currentWindow: true}, function(tabs) { - // Sort tabs according to their index in the window. - tabs.sort((a, b) => { return a.index < b.index; }); - let activeIndex = tabs.findIndex((tab) => { return tab.active; }); - let lastTab = tabs.length - 1; - let newIndex = -1; - if (command === 'flip-tabs-forward') - newIndex = activeIndex === 0 ? lastTab : activeIndex - 1; - else // 'flip-tabs-backwards' - newIndex = activeIndex === lastTab ? 0 : activeIndex + 1; - chrome.tabs.update(tabs[newIndex].id, {active: true, highlighted: true}); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper128.png b/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper128.png deleted file mode 100644 index 1d1dcb8..0000000 --- a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper16.png b/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper16.png deleted file mode 100644 index 695f64e..0000000 --- a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper32.png b/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper32.png deleted file mode 100644 index 67ef0d3..0000000 --- a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper48.png b/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper48.png deleted file mode 100644 index 4bf7680..0000000 --- a/chrome/common/extensions/docs/examples/api/default_command_override/images/tabFlipper48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/default_command_override/manifest.json b/chrome/common/extensions/docs/examples/api/default_command_override/manifest.json deleted file mode 100644 index 803f2b9c..0000000 --- a/chrome/common/extensions/docs/examples/api/default_command_override/manifest.json +++ /dev/null
@@ -1,36 +0,0 @@ -{ - "name": "Tab Flipper", - "description": "Press Ctrl+Shift+Right or Ctrl+Shift+Left (Command+Shift+Right or Command+Shift+Left on a Mac) to flip through window tabs", - "version": "1.0", - "manifest_version": 2, - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "browser_action": { - "default_icon": "images/tabFlipper16.png", - "default_title": "Press Ctrl(Win)/Command(Mac)+Shift+ Left or Right to Flip Tabs" - }, - "commands": { - "flip-tabs-forward": { - "suggested_key": { - "default": "Ctrl+Shift+Right", - "mac": "Command+Shift+Right" - }, - "description": "Flip tabs forward" - }, - "flip-tabs-backwards": { - "suggested_key": { - "default": "Ctrl+Shift+Left", - "mac": "Command+Shift+Left" - }, - "description": "Flip tabs backwards" - } - }, - "icons": { - "16": "images/tabFlipper16.png", - "32": "images/tabFlipper32.png", - "48": "images/tabFlipper48.png", - "128": "images/tabFlipper128.png" - } -}
diff --git a/chrome/common/extensions/docs/examples/api/desktopCapture/app.js b/chrome/common/extensions/docs/examples/api/desktopCapture/app.js deleted file mode 100644 index c470940..0000000 --- a/chrome/common/extensions/docs/examples/api/desktopCapture/app.js +++ /dev/null
@@ -1,137 +0,0 @@ -// Copyright 2013 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. - -'use strict'; - -const DESKTOP_MEDIA = ['screen', 'window', 'tab', 'audio']; - -var pending_request_id = null; -var pc1 = null; -var pc2 = null; - -// Launch the chooseDesktopMedia(). -document.querySelector('#start').addEventListener('click', function(event) { - pending_request_id = chrome.desktopCapture.chooseDesktopMedia( - DESKTOP_MEDIA, onAccessApproved); -}); - -document.querySelector('#cancel').addEventListener('click', function(event) { - if (pending_request_id != null) { - chrome.desktopCapture.cancelChooseDesktopMedia(pending_request_id); - } -}); - -document.querySelector('#startFromBackgroundPage') - .addEventListener('click', function(event) { - chrome.runtime.sendMessage( - {}, function(response) { console.log(response.farewell); }); - }); - -// Launch webkitGetUserMedia() based on selected media id. -function onAccessApproved(id, options) { - if (!id) { - console.log('Access rejected.'); - return; - } - - var audioConstraint = { - mandatory: { - chromeMediaSource: 'desktop', - chromeMediaSourceId: id - } - }; - - console.log(options.canRequestAudioTrack); - if (!options.canRequestAudioTrack) - audioConstraint = false; - - navigator.webkitGetUserMedia({ - audio: audioConstraint, - video: { - mandatory: { - chromeMediaSource: 'desktop', - chromeMediaSourceId: id, - maxWidth:screen.width, - maxHeight:screen.height} } - }, gotStream, getUserMediaError); -} - -function getUserMediaError(error) { - console.log('navigator.webkitGetUserMedia() errot: ', error); -} - -// Capture video/audio of media and initialize RTC communication. -function gotStream(stream) { - console.log('Received local stream', stream); - var video = document.querySelector('video'); - try { - video.srcObject = stream; - } catch (error) { - video.src = URL.createObjectURL(stream); - } - stream.onended = function() { console.log('Ended'); }; - - pc1 = new RTCPeerConnection(); - pc1.onicecandidate = function(event) { - onIceCandidate(pc1, event); - }; - pc2 = new RTCPeerConnection(); - pc2.onicecandidate = function(event) { - onIceCandidate(pc2, event); - }; - pc1.oniceconnectionstatechange = function(event) { - onIceStateChange(pc1, event); - }; - pc2.oniceconnectionstatechange = function(event) { - onIceStateChange(pc2, event); - }; - pc2.onaddstream = gotRemoteStream; - - pc1.addStream(stream); - - pc1.createOffer(onCreateOfferSuccess, function() {}); -} - -function onCreateOfferSuccess(desc) { - pc1.setLocalDescription(desc); - pc2.setRemoteDescription(desc); - // Since the 'remote' side has no media stream we need - // to pass in the right constraints in order for it to - // accept the incoming offer of audio and video. - var sdpConstraints = { - 'mandatory': { - 'OfferToReceiveAudio': true, - 'OfferToReceiveVideo': true - } - }; - pc2.createAnswer(onCreateAnswerSuccess, function(){}, sdpConstraints); -} - -function gotRemoteStream(event) { - // Call the polyfill wrapper to attach the media stream to this element. - console.log('hitting this code'); - try { - remoteVideo.srcObject = event.stream; - } catch (error) { - remoteVideo.src = URL.createObjectURL(event.stream); - } -} - -function onCreateAnswerSuccess(desc) { - pc2.setLocalDescription(desc); - pc1.setRemoteDescription(desc); -} - -function onIceCandidate(pc, event) { - if (event.candidate) { - var remotePC = (pc === pc1) ? pc2 : pc1; - remotePC.addIceCandidate(new RTCIceCandidate(event.candidate)); - } -} - -function onIceStateChange(pc, event) { - if (pc) { - console.log('ICE state change event: ', event); - } -}
diff --git a/chrome/common/extensions/docs/examples/api/desktopCapture/background.js b/chrome/common/extensions/docs/examples/api/desktopCapture/background.js deleted file mode 100644 index 30e4779cf..0000000 --- a/chrome/common/extensions/docs/examples/api/desktopCapture/background.js +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2013 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. - -chrome.app.runtime.onLaunched.addListener(function() { - chrome.app.window.create('index.html', { - bounds: { - width: 1080, - height: 550 - } - }); -}); - -chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { - chrome.desktopCapture.chooseDesktopMedia( - ["screen", "window"], - function(id) { - sendResponse({"id": id}); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/desktopCapture/icon.png b/chrome/common/extensions/docs/examples/api/desktopCapture/icon.png deleted file mode 100644 index c252ed6..0000000 --- a/chrome/common/extensions/docs/examples/api/desktopCapture/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/desktopCapture/index.html b/chrome/common/extensions/docs/examples/api/desktopCapture/index.html deleted file mode 100644 index fca9053..0000000 --- a/chrome/common/extensions/docs/examples/api/desktopCapture/index.html +++ /dev/null
@@ -1,31 +0,0 @@ -<html> -<head> -<style> - body { - background: white; - display: -webkit-flex; - -webkit-justify-content: center; - -webkit-align-items: center; - -webkit-flex-direction: column; - } - video { - width: 480px; - height: 360px; - border: 1px solid #e2e2e2; - box-shadow: 0 1px 1px rgba(0,0,0,0.2); - } -</style> -</head> -<body> - <div> - <video id="video" autoplay></video> - <video id="remoteVideo" autoplay></video> - </div> - <p> - <button id="start">Start</button> - <button id="cancel">Cancel</button> - <button id="startFromBackgroundPage">Start from background page</button> - </p> - <script src="app.js"></script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/desktopCapture/manifest.json b/chrome/common/extensions/docs/examples/api/desktopCapture/manifest.json deleted file mode 100644 index 6a59859..0000000 --- a/chrome/common/extensions/docs/examples/api/desktopCapture/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjd3VZe2un2t/ju5HGcZrbD862LLhtukwtXeySPzbQaq9zEyFzr+pVd1EeAW7ZPUA86K9/mpWiDycoSMMj9hpm+QQqBnQDrPPtBJfogkFvWsgDQaw6SXZmErTlzz1wukn/0YLQrPLJ7JPj3zGzWcoVj9AhOjQeDpq2E9P3lz85mHwG0RrxgpknP1wGNNkXl/y4WDaWHZyoX1zgcn2r3bzTdb77RWiA9pduXSn6d14GA9B9CdQA4bTDmc9HY1WaVGK0oDX2A2eJEllHqdeBJmpqPqds4cIhm0Gq6lKvxB61I2UZlbCaSIMfTTxBnt+r7NPgpxHBKJIF1xOCpuGtWuc0wIDAQAB", - "name": "Desktop Capture Example", - "description": "Show desktop media picker UI", - "version": "1", - "manifest_version": 3, - "icons": { - "16": "icon.png", - "128": "icon.png" - }, - "app": { - "background": { - "scripts": ["background.js"] - } - }, - "permissions": [ - "desktopCapture" - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/icon.png b/chrome/common/extensions/docs/examples/api/deviceInfo/basic/icon.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/manifest.json b/chrome/common/extensions/docs/examples/api/deviceInfo/basic/manifest.json deleted file mode 100644 index 4d376d8..0000000 --- a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "My Devices", - "version": "1.1", - "description": "A browser action with a popup dump of all devices signed into the same account as the current profile.", - "permissions": [ - "signedInDevices" - ], - "browser_action": { - "default_title": "My Devices", - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2, - "content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'" -}
diff --git a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/popup.html b/chrome/common/extensions/docs/examples/api/deviceInfo/basic/popup.html deleted file mode 100644 index 4b46611..0000000 --- a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/popup.html +++ /dev/null
@@ -1,9 +0,0 @@ -<html> -<head> - <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> - <script src="popup.js"></script> -</head> -<body style="width: 400px"> - <div id="deviceinfos"></div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/popup.js b/chrome/common/extensions/docs/examples/api/deviceInfo/basic/popup.js deleted file mode 100644 index 3a8265d8..0000000 --- a/chrome/common/extensions/docs/examples/api/deviceInfo/basic/popup.js +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2013 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. - -function dumpDevices(devices) { - $('#deviceinfos').empty(); - $('#deviceinfos').append(outputDevicesToList(devices)); -} - -function outputDevicesToList(devices) { - var table = $('<table border="1">'); - table.append($("<tr>" + - "<th>" + "Name" + "</th>" + - "<th>" + "OS" + "</th>" + - "<th>" + "Id" + "</th>" + - "<th>" + "Type" + "</th>" + - "<th>" + "Chrome Version" + "</th>" + - "</tr>")); - for (i = 0; i < devices.length; i++) { - table.append($("<tr>" + - "<td>" + devices[i].name + "</td>" + - "<td>" + devices[i].os + "</td>" + - "<td>" + devices[i].id + "</td>" + - "<td>" + devices[i].type + "</td>" + - "<td>" + devices[i].chromeVersion + "</td>" + - "</tr>")); - } - return table; -} - -// Add an event listener to listen for changes to device info. The -// callback would redisplay the list of devices. -chrome.signedInDevices.onDeviceInfoChange.addListener(dumpDevices); - -function populateDevices() { - // Get the list of devices and display it. - chrome.signedInDevices.get(false, dumpDevices); -} - -document.addEventListener('DOMContentLoaded', function () { - populateDevices(); -});
diff --git a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/background.js b/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/background.js deleted file mode 100644 index 8496dcb..0000000 --- a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/background.js +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright (c) 2011 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. - -const tab_log = function(json_args) { - var args = JSON.parse(unescape(json_args)); - console[args[0]].apply(console, Array.prototype.slice.call(args, 1)); -} - -chrome.extension.onRequest.addListener(function(request) { - if (request.command !== 'sendToConsole') - return; - chrome.tabs.executeScript(request.tabId, { - code: "("+ tab_log + ")('" + request.args + "');", - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/devtools.html b/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/devtools.html deleted file mode 100644 index 553696e7..0000000 --- a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/devtools.html +++ /dev/null
@@ -1,10 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Devtools Page</title> - <script src="devtools.js"></script> - <script src="./background.js" type="text/javascript"></script> - </head> - <body> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/devtools.js b/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/devtools.js deleted file mode 100644 index 554d3807..0000000 --- a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/devtools.js +++ /dev/null
@@ -1,185 +0,0 @@ -// Copyright (c) 2011 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. - -function Console() { -} - -Console.Type = { - LOG: "log", - DEBUG: "debug", - INFO: "info", - WARN: "warn", - ERROR: "error", - GROUP: "group", - GROUP_COLLAPSED: "groupCollapsed", - GROUP_END: "groupEnd" -}; - -Console.addMessage = function(type, format, args) { - chrome.extension.sendRequest({ - command: "sendToConsole", - tabId: chrome.devtools.tabId, - args: escape(JSON.stringify(Array.prototype.slice.call(arguments, 0))) - }); -}; - -// Generate Console output methods, i.e. Console.log(), Console.debug() etc. -(function() { - var console_types = Object.getOwnPropertyNames(Console.Type); - for (var type = 0; type < console_types.length; ++type) { - var method_name = Console.Type[console_types[type]]; - Console[method_name] = Console.addMessage.bind(Console, method_name); - } -})(); - -function ChromeFirePHP() { -}; - -ChromeFirePHP.handleFirePhpHeaders = function(har_entry) { - var response_headers = har_entry.response.headers; - var wf_header_map = {}; - var had_wf_headers = false; - - for (var i = 0; i < response_headers.length; ++i) { - var header = response_headers[i]; - if (/^X-Wf-/.test(header.name)) { - wf_header_map[header.name] = header.value; - had_wf_headers = true; - } - } - - var proto_header = wf_header_map["X-Wf-Protocol-1"]; - if (!had_wf_headers || !this._checkProtoVersion(proto_header)) - return; - - var message_objects = this._buildMessageObjects(wf_header_map); - message_objects.sort(function(a, b) { - var aFile = a.File || ""; - var bFile = b.File || ""; - if (aFile !== bFile) - return aFile.localeCompare(bFile); - var aLine = a.Line !== undefined ? a.Line : -1; - var bLine = b.Line !== undefined ? b.Line : -1; - return aLine - bLine; - }); - - var context = { pageRef: har_entry.pageref }; - for (var i = 0; i < message_objects.length; ++i) - this._processLogMessage(message_objects[i], context); - if (context.groupStarted) - Console.groupEnd(); -}; - -ChromeFirePHP._processLogMessage = function(message, context) { - var meta = message[0]; - if (!meta) { - Console.error("No Meta in FirePHP message"); - return; - } - - var body = message[1]; - var type = meta.Type; - if (!type) { - Console.error("No Type for FirePHP message"); - return; - } - - switch (type) { - case "LOG": - case "INFO": - case "WARN": - case "ERROR": - if (!context.groupStarted) { - context.groupStarted = true; - Console.groupCollapsed(context.pageRef || ""); - } - Console.addMessage(Console.Type[type], "%s%o", - (meta.Label ? meta.Label + ": " : ""), body); - break; - case "EXCEPTION": - case "TABLE": - case "TRACE": - case "GROUP_START": - case "GROUP_END": - // FIXME: implement - break; - } -}; - -ChromeFirePHP._buildMessageObjects = function(header_map) -{ - const normal_header_prefix = "X-Wf-1-1-1-"; - - return this._collectMessageObjectsForPrefix(header_map, normal_header_prefix); -}; - -ChromeFirePHP._collectMessageObjectsForPrefix = function(header_map, prefix) { - var results = []; - const header_regexp = /(?:\d+)?\|(.+)/; - var json = ""; - for (var i = 1; ; ++i) { - var name = prefix + i; - var value = header_map[name]; - if (!value) - break; - - var match = value.match(header_regexp); - if (!match) { - Console.error("Failed to parse FirePHP log message: " + value); - break; - } - var json_part = match[1]; - json += json_part.substring(0, json_part.lastIndexOf("|")); - if (json_part.charAt(json_part.length - 1) === "\\") - continue; - try { - var message = JSON.parse(json); - results.push(message); - } catch(e) { - Console.error("Failed to parse FirePHP log message: " + json); - } - json = ""; - } - return results; -}; - -ChromeFirePHP._checkProtoVersion = function(proto_header) { - if (!proto_header) { - Console.warn("WildFire protocol header not found"); - return; - } - - var match = /http:\/\/meta\.wildfirehq\.org\/Protocol\/([^\/]+)\/(.+)/.exec( - proto_header); - if (!match) { - Console.warn("Invalid WildFire protocol header"); - return; - } - var proto_name = match[1]; - var proto_version = match[2]; - if (proto_name !== "JsonStream" || proto_version !== "0.2") { - Console.warn( - "Unknown FirePHP protocol version: %s (expecting JsonStream/0.2)", - proto_name + "/" + proto_version); - return false; - } - return true; -}; - -chrome.devtools.network.addRequestHeaders({ - "X-FirePHP-Version": "0.0.6" -}); - -chrome.devtools.network.getHAR(function(result) { - var entries = result.entries; - if (!entries.length) { - Console.warn("ChromeFirePHP suggests that you reload the page to track" + - " FirePHP messages for all the requests"); - } - for (var i = 0; i < entries.length; ++i) - ChromeFirePHP.handleFirePhp_headers(entries[i]); - - chrome.devtools.network.onRequestFinished.addListener( - ChromeFirePHP.handleFirePhpHeaders.bind(ChromeFirePHP)); -});
diff --git a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/manifest.json b/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/manifest.json deleted file mode 100644 index 275dced..0000000 --- a/chrome/common/extensions/docs/examples/api/devtools/network/chrome-firephp/manifest.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "FirePHP for Chrome", - "version": "1.1", - "minimum_chrome_version": "10.0", - "description": "Extends the Developer Tools, adding support for parsing FirePHP messages from server", - "devtools_page": "devtools.html", - "background": { "scripts": ["background.js"] }, - "permissions": [ - "http://*/*", - "https://*/*" - ], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/devtools.html b/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/devtools.html deleted file mode 100644 index bcf0413f..0000000 --- a/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/devtools.html +++ /dev/null
@@ -1,5 +0,0 @@ -<html> -<body> -<script src="devtools.js"></script> -</body> -</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/devtools.js b/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/devtools.js deleted file mode 100644 index 5bf6a83..0000000 --- a/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/devtools.js +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The function below is executed in the context of the inspected page. -var page_getProperties = function() { - var data = window.jQuery && $0 ? jQuery.data($0) : {}; - // Make a shallow copy with a null prototype, so that sidebar does not - // expose prototype. - var props = Object.getOwnPropertyNames(data); - var copy = { __proto__: null }; - for (var i = 0; i < props.length; ++i) - copy[props[i]] = data[props[i]]; - return copy; -} - -chrome.devtools.panels.elements.createSidebarPane( - "jQuery Properties", - function(sidebar) { - function updateElementProperties() { - sidebar.setExpression("(" + page_getProperties.toString() + ")()"); - } - updateElementProperties(); - chrome.devtools.panels.elements.onSelectionChanged.addListener( - updateElementProperties); -});
diff --git a/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/manifest.json b/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/manifest.json deleted file mode 100644 index a60485d7..0000000 --- a/chrome/common/extensions/docs/examples/api/devtools/panels/chrome-query/manifest.json +++ /dev/null
@@ -1,7 +0,0 @@ -{ - "name": "Chrome Query", - "version": "1.1", - "description": "Extends the Developer Tools, adding a sidebar that displays the jQuery data associated with the selected DOM element.", - "devtools_page": "devtools.html", - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/README b/chrome/common/extensions/docs/examples/api/displaySource/tabCast/README deleted file mode 100644 index c775b70..0000000 --- a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/README +++ /dev/null
@@ -1,2 +0,0 @@ -Demo Chrome extension that utilizes chrome.displaySource API's. -The extension creates a WiFi Display Session from the captured tab media stream.
diff --git a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/background.js b/chrome/common/extensions/docs/examples/api/displaySource/tabCast/background.js deleted file mode 100644 index 830f273..0000000 --- a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/background.js +++ /dev/null
@@ -1,110 +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. - -var g_sessionInfo = {}; - -/** - * When extension icon clicked, get device list - * Then return the list to popup page - */ -chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { - if (message.browserActionClicked) { - getDeviceList(function(deviceList) { - sendResponse({ returnDeviceList: deviceList }); - }); - } - return true; -}); - -function getDeviceList(callback) { - chrome.displaySource.getAvailableSinks(callback); -} - -chrome.displaySource.onSessionTerminated.addListener(function(terminatedSink) { - chrome.runtime.sendMessage({ sessionTerminated: true, - currentSinkId: terminatedSink }); - - if (g_sessionInfo.stream) { - g_sessionInfo.stream.getTracks().forEach(function (track) { - track.stop(); }); - delete g_sessionInfo.stream; - } - delete g_sessionInfo.sinkId; -}); - -chrome.displaySource.onSinksUpdated.addListener(function(updatedSinks) { - console.log('Sinks updated'); - chrome.runtime.sendMessage({ sinksUpdated: true, - currentSinkId: g_sessionInfo.sinkId, - sinksList: updatedSinks}); -}); - -function start(sinkId) { - // If no session, proceed. - if (!g_sessionInfo.sinkId) { - g_sessionInfo.sinkId = parseInt(sinkId); - captureTabAndStartSession(g_sessionInfo.sinkId); - } -} - -function captureTabAndStartSession(sink_id) { - chrome.tabs.getCurrent(function(tab) { - var video_constraints = { - mandatory: { - chromeMediaSource: 'tab', - minWidth: 1920, - minHeight: 1080, - maxWidth: 1920, - maxHeight: 1080, - minFrameRate: 60, - maxFrameRate: 60 - } - }; - - var constraints = { - audio: true, - video: true, - videoConstraints: video_constraints - }; - - function onStream(stream) { - g_sessionInfo.stream = stream; - var session_info = { - sinkId: sink_id, - videoTrack: g_sessionInfo.stream.getVideoTracks()[0], - audioTrack: g_sessionInfo.stream.getAudioTracks()[0] - }; - - function onStarted() { - if (chrome.runtime.error) { - console.log('The Session to sink ' + g_sessionInfo.sinkId - + 'could not start, error: ' - + chrome.runtime.lastError.message); - } else { - console.log('The Session to sink ' + g_sessionInfo.sinkId - + ' has started.'); - } - } - console.log('Starting session to sink: ' + sink_id); - chrome.displaySource.startSession(session_info, onStarted); - } - - chrome.tabCapture.capture(constraints, onStream); - }); -} - -function stop() { - function onTerminated() { - if (chrome.runtime.lastError) { - console.log('The Session to sink ' + g_sessionInfo.sinkId - + 'could not terminate, error: ' - + chrome.runtime.lastError.message); - } else { - console.log('The Session to sink ' + g_sessionInfo.sinkId - + ' has terminated.'); - } - } - console.log('Terminating session to sink: ' + g_sessionInfo.sinkId); - chrome.displaySource.terminateSession(g_sessionInfo.sinkId, onTerminated); -}
diff --git a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.css b/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.css deleted file mode 100644 index 70cd202..0000000 --- a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.css +++ /dev/null
@@ -1,60 +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. - */ - -.connecting { - animation: glowing 1500ms infinite; - background-color: #004A7F; - border-radius: 10px; - border: none; - color: #FFFFFF; - cursor: pointer; - font-size: 20px; - margin: 1px; - outline: none; - padding: 5px 10px; - width: 170px; -} - -.disconnected { - background-color: #004A7F; - border-radius: 10px; - border: none; - color: #FFFFFF; - cursor: pointer; - font-size: 20px; - margin: 1px; - outline: none; - padding: 5px 10px; - width: 170px; -} - -.connected { - background-color: #0094FF; - border-radius: 10px; - border: none; - box-shadow: 0 0 20px #0094FF; - color: #FFFFFF; - cursor: pointer; - font-size: 20px; - margin: 1px; - outline: none; - padding: 5px 10px; - width: 170px; -} - -@keyframes glowing { - 0% { - background-color: #004A7F; - box-shadow: 0 0 3px #004A7F; - } - 50% { - background-color: #0094FF; - box-shadow: 0 0 10px #0094FF; - } - 100% { - background-color: #004A7F; - box-shadow: 0 0 3px #004A7F; - } -}
diff --git a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.html b/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.html deleted file mode 100644 index 69cc035..0000000 --- a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.html +++ /dev/null
@@ -1,16 +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. ---> -<!doctype html> -<html> -<head> - <title>chrome.displaySource API test</title> - <script src='main.js'></script> - <link rel='stylesheet' type='text/css' href='main.css'> -</head> -<body> - <div id='deviceList'></div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.js b/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.js deleted file mode 100644 index 4b08b26..0000000 --- a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/main.js +++ /dev/null
@@ -1,78 +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. - -chrome.runtime.sendMessage({ browserActionClicked : true }, function(response) { - var deviceList = response.returnDeviceList; - var backgroundPage = chrome.extension.getBackgroundPage(); - createButtonList(deviceList, backgroundPage); -}); - -chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) { - var deviceButton = document.getElementById(message.currentSinkId); - var backgroundPage = chrome.extension.getBackgroundPage(); - - if (message.sinksUpdated) { - var sinks = message.sinksList; - var changedSink = null; - - for (let sink of sinks) { - if (sink.id == message.currentSinkId) { - changedSink = sink; - } - } - - if (!changedSink) { - console.error('Failed to find sink: ' + message.currentSinkId); - return; - } - - if (changedSink.state == 'Connecting') { - changeButtonState(deviceButton, 'connecting', backgroundPage.stop); - } else if (changedSink.state == 'Connected') { - changeButtonState(deviceButton, 'connected', backgroundPage.stop); - } - } else if (message.sessionTerminated) { - changeButtonState(deviceButton, 'disconnected', backgroundPage.start); - } -}); - -function createButtonList(deviceList, backgroundPage) { - var divElement = document.getElementById('deviceList'); - if (!deviceList || !deviceList.length) { - var errorMessage = document.createTextNode('No available ' - + 'sink devices found'); - divElement.appendChild(errorMessage); - return; - } - - deviceList.forEach(function(device) { - if (!document.getElementById(device.id)) { - var deviceButton = document.createElement('input'); - - deviceButton.type = 'button'; - deviceButton.value = device.name; - deviceButton.id = device.id; - - if (device.state == 'Disconnected') { - changeButtonState(deviceButton, 'disconnected', backgroundPage.start); - } else if (device.state == 'Connecting') { - changeButtonState(deviceButton, 'connecting', backgroundPage.stop); - } else if (device.state == 'Connected') { - changeButtonState(deviceButton, 'connected', backgroundPage.stop); - } else { - console.error('Unexpected sink state.'); - return; - } - - divElement.appendChild(deviceButton); - } - }); -} - -function changeButtonState(button, styleName, method) { - button.className = styleName; - var sinkId = parseInt(button.id); - button.onclick = function() { method(sinkId) }; -} -
diff --git a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/manifest.json b/chrome/common/extensions/docs/examples/api/displaySource/tabCast/manifest.json deleted file mode 100644 index b3fc8aa1..0000000 --- a/chrome/common/extensions/docs/examples/api/displaySource/tabCast/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "tabCast", - "version": "0.1", - "manifest_version": 2, - "description": "Creates a WiFi Display Session from the captured tab media stream using chrome.displaySource API.", - "permissions": [ - "tabCapture", "tabs", "displaySource" - ], - "browser_action": { - "default_title": "Tab cast", - "default_popup": "main.html" - }, - "background": { - "scripts": ["background.js"], - "persistent": false - } -}
diff --git a/chrome/common/extensions/docs/examples/api/document_scan/README.md b/chrome/common/extensions/docs/examples/api/document_scan/README.md deleted file mode 100644 index 22c61ca..0000000 --- a/chrome/common/extensions/docs/examples/api/document_scan/README.md +++ /dev/null
@@ -1,10 +0,0 @@ -# Document Scanning API Sample - -This demo interfaces with the Chrome document scanning API to acquire scanned -images. - -## APIs - -* [Document scanning API](https://developer.chrome.com/apps/document_scan) -* [Runtime](https://developer.chrome.com/apps/runtime) -* [Window](https://developer.chrome.com/apps/app_window)
diff --git a/chrome/common/extensions/docs/examples/api/document_scan/background.js b/chrome/common/extensions/docs/examples/api/document_scan/background.js deleted file mode 100644 index 7f7faf23..0000000 --- a/chrome/common/extensions/docs/examples/api/document_scan/background.js +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2014 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. - -chrome.app.runtime.onLaunched.addListener(function() { - chrome.app.window.create('scan.html', { - singleton: true, - id: "ChromeApps-Sample-Document-Scan", - bounds: { - 'width': 480, - 'height': 640 - } - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/document_scan/manifest.json b/chrome/common/extensions/docs/examples/api/document_scan/manifest.json deleted file mode 100644 index 8f788d3..0000000 --- a/chrome/common/extensions/docs/examples/api/document_scan/manifest.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "Document Scanning API Sample", - "version": "0.1", - "manifest_version": 2, - "minimum_chrome_version": "37", - "app": { - "background": { - "scripts": ["background.js"] - } - }, - "permissions": [], - "optional_permissions": [ "documentScan" ] -}
diff --git a/chrome/common/extensions/docs/examples/api/document_scan/scan.css b/chrome/common/extensions/docs/examples/api/document_scan/scan.css deleted file mode 100644 index 899b0f6..0000000 --- a/chrome/common/extensions/docs/examples/api/document_scan/scan.css +++ /dev/null
@@ -1,36 +0,0 @@ -/* Copyright 2014 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. - */ - -#waitAnimation { - position: absolute; - left: 0px; - top: 0px; - height:100%; - width:100%; - z-index:1000; - background-color:black; - opacity:0.6; -} - -#waitSpinner { - position: absolute; - height:60px; - width:60px; - top: 50%; - left: 50%; - margin-left: -30px; - margin-top: -30px; - animation: rotation .6s infinite linear; - border-left:6px solid rgba(180,174,239,.15); - border-right:6px solid rgba(180,174,239,.15); - border-bottom:6px solid rgba(180,174,239,.15); - border-top:6px solid rgba(180,174,239,.8); - border-radius:100%; -} - -@keyframes rotation { - from {transform: rotate(0deg);} - to {transform: rotate(359deg);} -}
diff --git a/chrome/common/extensions/docs/examples/api/document_scan/scan.html b/chrome/common/extensions/docs/examples/api/document_scan/scan.html deleted file mode 100644 index a7b24b6..0000000 --- a/chrome/common/extensions/docs/examples/api/document_scan/scan.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Scanner Control</title> - <link rel="stylesheet" type="text/css" href="scan.css"> - </head> - <body> - <div id="waitAnimation" style="display: none;"> - <div id="waitSpinner"></div> - </div> - </img> - <button id="requestButton">Request App permissions</button> - <button id="scanButton">Scan</button> - <div id="scannedImages"> - </div> - <script src="scan.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/document_scan/scan.js b/chrome/common/extensions/docs/examples/api/document_scan/scan.js deleted file mode 100644 index 23d84957..0000000 --- a/chrome/common/extensions/docs/examples/api/document_scan/scan.js +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2014 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. - -var requestButton = document.getElementById("requestButton"); -var scanButton = document.getElementById('scanButton'); -var scannedImages = document.getElementById('scannedImages'); -var waitAnimation = document.getElementById('waitAnimation'); -var imageMimeType; - -function setOnlyChild(parent, child) { - while (parent.firstChild) { - parent.removeChild(parent.firstChild); - } - parent.appendChild(child); -} - -var gotPermission = function(result) { - waitAnimation.style.display = 'block'; - requestButton.style.display = 'none'; - scanButton.style.display = 'block'; - console.log('App was granted the "documentScan" permission.'); - waitAnimation.style.display = 'none'; -}; - -var permissionObj = {permissions: ['documentScan']}; - -requestButton.addEventListener('click', function() { - waitAnimation.style.display = 'block'; - chrome.permissions.request( permissionObj, function(result) { - if (result) { - gotPermission(); - } else { - console.log('App was not granted the "documentScan" permission.'); - console.log(chrome.runtime.lastError); - } - }); -}); - -var onScanCompleted = function(scan_results) { - waitAnimation.style.display = 'none'; - if (chrome.runtime.lastError) { - console.log('Scan failed: ' + chrome.runtime.lastError.message); - return; - } - numImages = scan_results.dataUrls.length; - console.log('Scan completed with ' + numImages + ' images.'); - for (var i = 0; i < numImages; i++) { - urlData = scan_results.dataUrls[i] - console.log('Scan ' + i + ' data length ' + - urlData.length + '.'); - console.log('URL is ' + urlData); - var scannedImage = document.createElement('img'); - scannedImage.src = urlData; - scannedImages.insertBefore(scannedImage, scannedImages.firstChild); - } -}; - -scanButton.addEventListener('click', function() { - var scanProperties = {}; - waitAnimation.style.display = 'block'; - chrome.documentScan.scan(scanProperties, onScanCompleted); -}); - -chrome.permissions.contains(permissionObj, function(result) { - if (result) { - gotPermission(); - } -});
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/bg.js b/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/bg.js deleted file mode 100644 index 3494607..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/bg.js +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function matches(rule, item) { - if (rule.matcher == 'js') - return eval(rule.match_param); - if (rule.matcher == 'hostname') { - var link = document.createElement('a'); - link.href = item.url.toLowerCase(); - var host = (rule.match_param.indexOf(':') < 0) ? link.hostname : link.host; - return (host.indexOf(rule.match_param.toLowerCase()) == - (host.length - rule.match_param.length)); - } - if (rule.matcher == 'default') - return item.filename == rule.match_param; - if (rule.matcher == 'url-regex') - return (new RegExp(rule.match_param)).test(item.url); - if (rule.matcher == 'default-regex') - return (new RegExp(rule.match_param)).test(item.filename); - return false; -} - -chrome.downloads.onDeterminingFilename.addListener(function(item, __suggest) { - function suggest(filename, conflictAction) { - __suggest({filename: filename, - conflictAction: conflictAction, - conflict_action: conflictAction}); - // conflict_action was renamed to conflictAction in - // https://chromium.googlesource.com/chromium/src/+/f1d784d6938b8fe8e0d257e41b26341992c2552c - // which was first picked up in branch 1580. - } - var rules = localStorage.rules; - try { - rules = JSON.parse(rules); - } catch (e) { - localStorage.rules = JSON.stringify([]); - } - for (var index = 0; index < rules.length; ++index) { - var rule = rules[index]; - if (rule.enabled && matches(rule, item)) { - if (rule.action == 'overwrite') { - suggest(item.filename, 'overwrite'); - } else if (rule.action == 'prompt') { - suggest(item.filename, 'prompt'); - } else if (rule.action == 'js') { - eval(rule.action_js); - } - break; - } - } -});
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/manifest.json b/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/manifest.json deleted file mode 100644 index 6bdb58ec..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/manifest.json +++ /dev/null
@@ -1,8 +0,0 @@ -{"name": "Download Filename Controller", - "description": "Download Filename Controller", - "version": "0.1", - "background": {"scripts": ["bg.js"], "persistent": false}, - "options_page": "options.html", - "permissions": ["downloads"], - "content_security_policy": "script-src 'self'; default-src 'self'", - "manifest_version": 2}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/options.html b/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/options.html deleted file mode 100644 index 01d5317f..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/options.html +++ /dev/null
@@ -1,39 +0,0 @@ -<!doctype html> -<html> -<head> -<title>Download Filename Controller</title> -<script src="options.js"></script> -</head> -<body> -<table id=rules></table> -<button id=new>New Rule</button> -<table hidden> -<tr id=rule-template hidden> - <td class=nowrap><button class=move-up>↑</button> - <button class=move-down>↓</button></td> - <td> - <select class=matcher> - <option value=hostname>Hostname</option> - <option value=url-regex>URL RegExp</option> - <option value=default>Default Filename</option> - <option value=default-regex>Default Filename RegExp</option> - <option value=js>Javascript</option> - </select> - <input type=text class=match-param> - <select class=action> - <option value=overwrite>Overwrite default filename</option> - <option value=prompt>Prompt if default filename exists</option> - <option value=js>Javascript</option> - </select> - <textarea class=action-js rows=5 cols=83>console.log(item.url) -console.log(item.filename) -// http://developer.chrome.com/extensions/downloads.html#type-DownloadItem -// http://developer.chrome.com/extensions/downloads.html#type-FilenameConflictAction -suggest('hello.txt', 'overwrite')</textarea></td> - <td><span class=nowrap><input type=checkbox class=enabled checked> - <label class=enabled-label>Enabled</label></span> - <button class=remove>Remove</button></td> -</tr> -</table> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/options.js b/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/options.js deleted file mode 100644 index d25ae42..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_filename_controller/options.js +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright (c) 2013 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. - -function Rule(data) { - var rules = document.getElementById('rules'); - this.node = document.getElementById('rule-template').cloneNode(true); - this.node.id = 'rule' + (Rule.next_id++); - this.node.rule = this; - rules.appendChild(this.node); - this.node.hidden = false; - - if (data) { - this.getElement('matcher').value = data.matcher; - this.getElement('match-param').value = data.match_param; - this.getElement('action').value = data.action; - this.getElement('action-js').value = data.action_js; - this.getElement('enabled').checked = data.enabled; - } - - this.getElement('enabled-label').htmlFor = this.getElement('enabled').id = - this.node.id + '-enabled'; - - this.render(); - - this.getElement('matcher').onchange = storeRules; - this.getElement('match-param').onkeyup = storeRules; - this.getElement('action').onchange = storeRules; - this.getElement('action-js').onkeyup = storeRules; - this.getElement('enabled').onchange = storeRules; - - var rule = this; - this.getElement('move-up').onclick = function() { - var sib = rule.node.previousSibling; - rule.node.parentNode.removeChild(rule.node); - sib.parentNode.insertBefore(rule.node, sib); - storeRules(); - }; - this.getElement('move-down').onclick = function() { - var parentNode = rule.node.parentNode; - var sib = rule.node.nextSibling.nextSibling; - parentNode.removeChild(rule.node); - if (sib) { - parentNode.insertBefore(rule.node, sib); - } else { - parentNode.appendChild(rule.node); - } - storeRules(); - }; - this.getElement('remove').onclick = function() { - rule.node.parentNode.removeChild(rule.node); - storeRules(); - }; - storeRules(); -} - -Rule.prototype.getElement = function(name) { - return document.querySelector('#' + this.node.id + ' .' + name); -} - -Rule.prototype.render = function() { - this.getElement('move-up').disabled = !this.node.previousSibling; - this.getElement('move-down').disabled = !this.node.nextSibling; - this.getElement('action-js').style.display = - (this.getElement('action').value == 'js') ? 'block' : 'none'; -} - -Rule.next_id = 0; - -function loadRules() { - var rules = localStorage.rules; - try { - JSON.parse(rules).forEach(function(rule) {new Rule(rule);}); - } catch (e) { - localStorage.rules = JSON.stringify([]); - } -} - -function storeRules() { - localStorage.rules = JSON.stringify(Array.prototype.slice.apply( - document.getElementById('rules').childNodes).map(function(node) { - node.rule.render(); - return {matcher: node.rule.getElement('matcher').value, - match_param: node.rule.getElement('match-param').value, - action: node.rule.getElement('action').value, - action_js: node.rule.getElement('action-js').value, - enabled: node.rule.getElement('enabled').checked}; - })); -} - -window.onload = function() { - loadRules(); - document.getElementById('new').onclick = function() { - new Rule(); - }; -}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_links/manifest.json b/chrome/common/extensions/docs/examples/api/downloads/download_links/manifest.json deleted file mode 100644 index f252f0d..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_links/manifest.json +++ /dev/null
@@ -1,9 +0,0 @@ -{ - "name": "Download Selected Links", - "description": "Select links on a page and download them.", - "version": "0.1", - "minimum_chrome_version": "16.0.884", - "permissions": ["downloads", "<all_urls>"], - "browser_action": {"default_popup": "popup.html"}, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_links/popup.html b/chrome/common/extensions/docs/examples/api/downloads/download_links/popup.html deleted file mode 100644 index cba0b76..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_links/popup.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<head> -<script src='popup.js'></script> -</head> -<body> -<input type=text id=filter placeholder=Filter> -<input type=checkbox id=regex> -<label for=regex>Regex</label><br> -<button id=download0>Download All!</button> -<table id=links> - <tr> - <th><input type=checkbox checked id=toggle_all></th> - <th align=left>URL</th> - </tr> -</table> -<button id=download1>Download All!</button> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_links/popup.js b/chrome/common/extensions/docs/examples/api/downloads/download_links/popup.js deleted file mode 100644 index c889245..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_links/popup.js +++ /dev/null
@@ -1,117 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This extension demonstrates using chrome.downloads.download() to -// download URLs. - -var allLinks = []; -var visibleLinks = []; - -// Display all visible links. -function showLinks() { - var linksTable = document.getElementById('links'); - while (linksTable.children.length > 1) { - linksTable.removeChild(linksTable.children[linksTable.children.length - 1]) - } - for (var i = 0; i < visibleLinks.length; ++i) { - var row = document.createElement('tr'); - var col0 = document.createElement('td'); - var col1 = document.createElement('td'); - var checkbox = document.createElement('input'); - checkbox.checked = true; - checkbox.type = 'checkbox'; - checkbox.id = 'check' + i; - col0.appendChild(checkbox); - col1.innerText = visibleLinks[i]; - col1.style.whiteSpace = 'nowrap'; - col1.onclick = function() { - checkbox.checked = !checkbox.checked; - } - row.appendChild(col0); - row.appendChild(col1); - linksTable.appendChild(row); - } -} - -// Toggle the checked state of all visible links. -function toggleAll() { - var checked = document.getElementById('toggle_all').checked; - for (var i = 0; i < visibleLinks.length; ++i) { - document.getElementById('check' + i).checked = checked; - } -} - -// Download all visible checked links. -function downloadCheckedLinks() { - for (var i = 0; i < visibleLinks.length; ++i) { - if (document.getElementById('check' + i).checked) { - chrome.downloads.download({url: visibleLinks[i]}, - function(id) { - }); - } - } - window.close(); -} - -// Re-filter allLinks into visibleLinks and reshow visibleLinks. -function filterLinks() { - var filterValue = document.getElementById('filter').value; - if (document.getElementById('regex').checked) { - visibleLinks = allLinks.filter(function(link) { - return link.match(filterValue); - }); - } else { - var terms = filterValue.split(' '); - visibleLinks = allLinks.filter(function(link) { - for (var termI = 0; termI < terms.length; ++termI) { - var term = terms[termI]; - if (term.length != 0) { - var expected = (term[0] != '-'); - if (!expected) { - term = term.substr(1); - if (term.length == 0) { - continue; - } - } - var found = (-1 !== link.indexOf(term)); - if (found != expected) { - return false; - } - } - } - return true; - }); - } - showLinks(); -} - -// Add links to allLinks and visibleLinks, sort and show them. send_links.js is -// injected into all frames of the active tab, so this listener may be called -// multiple times. -chrome.extension.onRequest.addListener(function(links) { - for (var index in links) { - allLinks.push(links[index]); - } - allLinks.sort(); - visibleLinks = allLinks; - showLinks(); -}); - -// Set up event handlers and inject send_links.js into all frames in the active -// tab. -window.onload = function() { - document.getElementById('filter').onkeyup = filterLinks; - document.getElementById('regex').onchange = filterLinks; - document.getElementById('toggle_all').onchange = toggleAll; - document.getElementById('download0').onclick = downloadCheckedLinks; - document.getElementById('download1').onclick = downloadCheckedLinks; - - chrome.windows.getCurrent(function (currentWindow) { - chrome.tabs.query({active: true, windowId: currentWindow.id}, - function(activeTabs) { - chrome.tabs.executeScript( - activeTabs[0].id, {file: 'send_links.js', allFrames: true}); - }); - }); -};
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_links/send_links.js b/chrome/common/extensions/docs/examples/api/downloads/download_links/send_links.js deleted file mode 100644 index 29a06a6..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_links/send_links.js +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Send back to the popup a sorted deduped list of valid link URLs on this page. -// The popup injects this script into all frames in the active tab. - -var links = [].slice.apply(document.getElementsByTagName('a')); -links = links.map(function(element) { - // Return an anchor's href attribute, stripping any URL fragment (hash '#'). - // If the html specifies a relative path, chrome converts it to an absolute - // URL. - var href = element.href; - var hashIndex = href.indexOf('#'); - if (hashIndex >= 0) { - href = href.substr(0, hashIndex); - } - return href; -}); - -links.sort(); - -// Remove duplicates and invalid URLs. -var kBadPrefix = 'javascript'; -for (var i = 0; i < links.length;) { - if (((i > 0) && (links[i] == links[i - 1])) || - (links[i] == '') || - (kBadPrefix == links[i].toLowerCase().substr(0, kBadPrefix.length))) { - links.splice(i, 1); - } else { - ++i; - } -} - -chrome.extension.sendRequest(links);
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/_locales/en/messages.json b/chrome/common/extensions/docs/examples/api/downloads/download_manager/_locales/en/messages.json deleted file mode 100644 index 83d05e7..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/_locales/en/messages.json +++ /dev/null
@@ -1,290 +0,0 @@ -{"extName": { - "message": "Download Manager Button", - "description": "Extension name"}, - "extDesc": { - "message": "Browser Action Download Manager User Interface for Google Chrome", - "description": "Extension description"}, - "badChromeVersion": { - "message": "The downloads API is only available on the canary, dev, and beta channels.", - "description": ""}, - "tabTitle": { - "message": "Downloads", - "description": "tab title"}, - "searchPlaceholder": { - "message": "Search Downloads", - "description": ""}, - "clearAllTitle": { - "message": "Erase All Visible Downloads", - "description": ""}, - "openDownloadsFolderTitle": { - "message": "Open Downloads Folder", - "description": ""}, - "zeroItems": { - "message": "There are zero download items.", - "description": ""}, - "searching": { - "message": "Teleporting lots of goats...", - "description": ""}, - "zeroSearchResults": { - "message": "Zero matches", - "description": ""}, - "managementPermissionInfo": { - "message": "Some files were downloaded by an extension.", - "description": ""}, - "grantManagementPermission": { - "message": "Show links to extensions that download files.", - "description": ""}, - "showOlderDownloads": { - "message": "Show Older Downloads", - "description": ""}, - "loadingOlderDownloads": { - "message": "Loading Older Downloads...", - "description": ""}, - "openTitle": { - "message": "Open", - "description": ""}, - "pauseTitle": { - "message": "Pause", - "description": ""}, - "resumeTitle": { - "message": "Resume", - "description": ""}, - "cancelTitle": { - "message": "Cancel", - "description": ""}, - "removeFileTitle": { - "message": "Remove file", - "description": ""}, - "eraseTitle": { - "message": "Erase", - "description": ""}, - "retryTitle": { - "message": "Retry", - "description": ""}, - "referrerTitle": { - "message": "Referrer", - "description": ""}, - "month0abbr": {"message": "Jan","description": ""}, - "month1abbr": {"message": "Feb","description": ""}, - "month2abbr": {"message": "Mar","description": ""}, - "month3abbr": {"message": "Apr","description": ""}, - "month4abbr": {"message": "May","description": ""}, - "month5abbr": {"message": "Jun","description": ""}, - "month6abbr": {"message": "Jul","description": ""}, - "month7abbr": {"message": "Aug","description": ""}, - "month8abbr": {"message": "Sep","description": ""}, - "month9abbr": {"message": "Oct","description": ""}, - "month10abbr": {"message": "Nov","description": ""}, - "month11abbr": {"message": "Dec","description": ""}, - "openWhenCompleteFinishing": { - "message": "Opening in just a moment", - "description": ""}, - "timeLeftFinishing": { - "message": "finishing...", - "description": ""}, - "openWhenCompleteDays": { - "message": "Opening in $days$d $hours$h", - "description": "", - "placeholders": { - "days": { - "content": "$1", - "example": "2"}, - "hours": { - "content": "$2", - "example": "23"}}}, - "timeLeftDays": { - "message": "$days$d $hours$h left", - "description": "", - "placeholders": { - "days": { - "content": "$1", - "example": "2"}, - "hours": { - "content": "$2", - "example": "23"}}}, - "openWhenCompleteHours": { - "message": "Opening in $hours$h $mins$m", - "description": "", - "placeholders": { - "hours": { - "content": "$1", - "example": "23"}, - "mins": { - "content": "$2", - "example": "59"}}}, - "timeLeftHours": { - "message": "$hours$h $mins$m left", - "description": "", - "placeholders": { - "hours": { - "content": "$1", - "example": "23"}, - "mins": { - "content": "$2", - "example": "59"}}}, - "openWhenCompleteMinutes": { - "message": "Opening in $mins$m $sec$s", - "description": "", - "placeholders": { - "mins": { - "content": "$1", - "example": "59"}, - "sec": { - "content": "$2", - "example": "59"}}}, - "timeLeftMinutes": { - "message": "$mins$m $sec$s left", - "description": "", - "placeholders": { - "mins": { - "content": "$1", - "example": "59"}, - "sec": { - "content": "$2", - "example": "59"}}}, - "openWhenCompleteSeconds": { - "message": "Opening in $sec$s", - "description": "", - "placeholders": { - "sec": { - "content": "$1", - "example": "59"}}}, - "timeLeftSeconds": { - "message": "$sec$s left", - "description": "", - "placeholders": { - "sec": { - "content": "$1", - "example": "59"}}}, - "error_FILE_FAILED": { - "message": "File Failed", - "description": ""}, - "error_FILE_ACCESS_DENIED": { - "message": "File-System Access Denied", - "description": ""}, - "error_FILE_NO_SPACE": { - "message": "No Space On Disk", - "description": ""}, - "error_FILE_NAME_TOO_LONG": { - "message": "Filename Too Long", - "description": ""}, - "error_FILE_TOO_LARGE": { - "message": "File Too Large", - "description": ""}, - "error_FILE_VIRUS_INFECTED": { - "message": "Virus Infected", - "description": ""}, - "error_FILE_TRANSIENT_ERROR": { - "message": "Transient File-System Error", - "description": ""}, - "error_FILE_BLOCKED": { - "message": "File Blocked", - "description": ""}, - "error_FILE_SECURITY_CHECK_FAILED": { - "message": "Security Check Failed", - "description": ""}, - "error_FILE_TOO_SHORT": { - "message": "File Too Short", - "description": ""}, - "error_NETWORK_FAILED": { - "message": "Network Failure", - "description": ""}, - "error_NETWORK_TIMEOUT": { - "message": "Network Timeout", - "description": ""}, - "error_NETWORK_DISCONNECTED": { - "message": "Network Disconnected", - "description": ""}, - "error_NETWORK_SERVER_DOWN": { - "message": "Server Down", - "description": ""}, - "error_SERVER_FAILED": { - "message": "Server Failure", - "description": ""}, - "error_SERVER_NO_RANGE": { - "message": "Server No Range", - "description": ""}, - "error_SERVER_PRECONDITION": { - "message": "Server Precondition Failure", - "description": ""}, - "error_SERVER_BAD_CONTENT": { - "message": "Bad Content", - "description": ""}, - "error_USER_CANCELED": { - "message": "Cancelled", - "description": ""}, - "error_USER_SHUTDOWN": { - "message": "Cancelled", - "description": ""}, - "error_CRASH": { - "message": "Crash", - "description": ""}, - "error_1": { - "message": "File Failed", - "description": ""}, - "error_2": { - "message": "File-System Access Denied", - "description": ""}, - "error_3": { - "message": "No Space On Disk", - "description": ""}, - "error_5": { - "message": "Filename Too Long", - "description": ""}, - "error_6": { - "message": "File Too Large", - "description": ""}, - "error_7": { - "message": "Virus Infected", - "description": ""}, - "error_10": { - "message": "Transient File-System Error", - "description": ""}, - "error_11": { - "message": "File Blocked", - "description": ""}, - "error_12": { - "message": "Security Check Failed", - "description": ""}, - "error_13": { - "message": "File Too Short", - "description": ""}, - "error_20": { - "message": "Network Failure", - "description": ""}, - "error_21": { - "message": "Network Timeout", - "description": ""}, - "error_22": { - "message": "Network Disconnected", - "description": ""}, - "error_23": { - "message": "Server Down", - "description": ""}, - "error_30": { - "message": "Server Failure", - "description": ""}, - "error_31": { - "message": "Server No Range", - "description": ""}, - "error_32": { - "message": "Server Precondition Failure", - "description": ""}, - "error_33": { - "message": "Bad Content", - "description": ""}, - "error_40": { - "message": "Cancelled", - "description": ""}, - "error_41": { - "message": "Cancelled", - "description": ""}, - "error_50": { - "message": "Crash", - "description": ""}, - "errorRemoved": { - "message": "Removed", - "description": ""}, - "showInFolderTitle": { - "message": "Show in Folder", - "description": "Alt text for show in folder icon"}}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/background.js b/chrome/common/extensions/docs/examples/api/downloads/download_manager/background.js deleted file mode 100644 index b1f8f2cd..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/background.js +++ /dev/null
@@ -1,267 +0,0 @@ -// Copyright (c) 2013 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. - -if (chrome.downloads.setShelfEnabled) - chrome.downloads.setShelfEnabled(false); - -var colors = { - progressColor: '#0d0', - arrow: '#555', - danger: 'red', - complete: 'green', - paused: 'grey', - background: 'white', -}; - -function drawLine(ctx, x1, y1, x2, y2) { - ctx.beginPath(); - ctx.moveTo(x1, y1); - ctx.lineTo(x2, y2); - ctx.stroke(); -} - -Math.TAU = 2 * Math.PI; // http://tauday.com/tau-manifesto - -function drawProgressArc(ctx, startAngle, endAngle) { - var center = ctx.canvas.width/2; - ctx.lineWidth = Math.round(ctx.canvas.width*0.1); - ctx.beginPath(); - ctx.moveTo(center, center); - ctx.arc(center, center, center * 0.9, startAngle, endAngle, false); - ctx.fill(); - ctx.stroke(); -} - -function drawUnknownProgressSpinner(ctx) { - var center = ctx.canvas.width/2; - const segments = 16; - var segArc = Math.TAU / segments; - for (var seg = 0; seg < segments; ++seg) { - ctx.fillStyle = ctx.strokeStyle = ( - ((seg % 2) == 0) ? colors.progressColor : colors.background); - drawProgressArc(ctx, (seg-4)*segArc, (seg-3)*segArc); - } -} - -function drawProgressSpinner(ctx, stage) { - ctx.fillStyle = ctx.strokeStyle = colors.progressColor; - var clocktop = -Math.TAU/4; - drawProgressArc(ctx, clocktop, clocktop + (stage * Math.TAU)); -} - -function drawArrow(ctx) { - ctx.beginPath(); - ctx.lineWidth = Math.round(ctx.canvas.width*0.1); - ctx.lineJoin = 'round'; - ctx.strokeStyle = ctx.fillStyle = colors.arrow; - var center = ctx.canvas.width/2; - var minw2 = center*0.2; - var maxw2 = center*0.60; - var height2 = maxw2; - ctx.moveTo(center-minw2, center-height2); - ctx.lineTo(center+minw2, center-height2); - ctx.lineTo(center+minw2, center); - ctx.lineTo(center+maxw2, center); - ctx.lineTo(center, center+height2); - ctx.lineTo(center-maxw2, center); - ctx.lineTo(center-minw2, center); - ctx.lineTo(center-minw2, center-height2); - ctx.lineTo(center+minw2, center-height2); - ctx.stroke(); - ctx.fill(); -} - -function drawDangerBadge(ctx) { - var s = ctx.canvas.width/100; - ctx.fillStyle = colors.danger; - ctx.strokeStyle = colors.background; - ctx.lineWidth = Math.round(s*5); - var edge = ctx.canvas.width-ctx.lineWidth; - ctx.beginPath(); - ctx.moveTo(s*75, s*55); - ctx.lineTo(edge, edge); - ctx.lineTo(s*55, edge); - ctx.lineTo(s*75, s*55); - ctx.lineTo(edge, edge); - ctx.fill(); - ctx.stroke(); -} - -function drawPausedBadge(ctx) { - var s = ctx.canvas.width/100; - ctx.beginPath(); - ctx.strokeStyle = colors.background; - ctx.lineWidth = Math.round(s*5); - ctx.rect(s*55, s*55, s*15, s*35); - ctx.fillStyle = colors.paused; - ctx.fill(); - ctx.stroke(); - ctx.rect(s*75, s*55, s*15, s*35); - ctx.fill(); - ctx.stroke(); -} - -function drawCompleteBadge(ctx) { - var s = ctx.canvas.width/100; - ctx.beginPath(); - ctx.arc(s*75, s*75, s*15, 0, Math.TAU, false); - ctx.fillStyle = colors.complete; - ctx.fill(); - ctx.strokeStyle = colors.background; - ctx.lineWidth = Math.round(s*5); - ctx.stroke(); -} - -function drawIcon(side, options) { - var canvas = document.createElement('canvas'); - canvas.width = canvas.height = side; - document.body.appendChild(canvas); - var ctx = canvas.getContext('2d'); - if (options.anyInProgress) { - if (options.anyMissingTotalBytes) { - drawUnknownProgressSpinner(ctx); - } else { - drawProgressSpinner(ctx, (options.totalBytesReceived / - options.totalTotalBytes)); - } - } - drawArrow(ctx); - if (options.anyDangerous) { - drawDangerBadge(ctx); - } else if (options.anyPaused) { - drawPausedBadge(ctx); - } else if (options.anyRecentlyCompleted) { - drawCompleteBadge(ctx); - } - return canvas; -} - -function maybeOpen(id) { - var openWhenComplete = []; - try { - openWhenComplete = JSON.parse(localStorage.openWhenComplete); - } catch (e) { - localStorage.openWhenComplete = JSON.stringify(openWhenComplete); - } - var openNowIndex = openWhenComplete.indexOf(id); - if (openNowIndex >= 0) { - chrome.downloads.open(id); - openWhenComplete.splice(openNowIndex, 1); - localStorage.openWhenComplete = JSON.stringify(openWhenComplete); - } -} - -function setBrowserActionIcon(options) { - var canvas1 = drawIcon(19, options); - var canvas2 = drawIcon(38, options); - var imageData = {}; - imageData['' + canvas1.width] = canvas1.getContext('2d').getImageData( - 0, 0, canvas1.width, canvas1.height); - imageData['' + canvas2.width] = canvas2.getContext('2d').getImageData( - 0, 0, canvas2.width, canvas2.height); - chrome.browserAction.setIcon({imageData:imageData}); - canvas1.parentNode.removeChild(canvas1); - canvas2.parentNode.removeChild(canvas2); -} - -function pollProgress() { - pollProgress.tid = -1; - chrome.downloads.search({}, function(items) { - var popupLastOpened = parseInt(localStorage.popupLastOpened); - var options = {anyMissingTotalBytes: false, - anyInProgress: false, - anyRecentlyCompleted: false, - anyPaused: false, - anyDangerous: false, - totalBytesReceived: 0, - totalTotalBytes: 0}; - items.forEach(function(item) { - if (item.state == 'in_progress') { - options.anyInProgress = true; - if (item.totalBytes) { - options.totalTotalBytes += item.totalBytes; - options.totalBytesReceived += item.bytesReceived; - } else { - options.anyMissingTotalBytes = true; - } - var dangerous = ((item.danger != 'safe') && - (item.danger != 'accepted')); - options.anyDangerous = options.anyDangerous || dangerous; - options.anyPaused = options.anyPaused || item.paused; - } else if ((item.state == 'complete') && item.endTime && !item.error) { - options.anyRecentlyCompleted = ( - options.anyRecentlyCompleted || - ((new Date(item.endTime)).getTime() >= popupLastOpened)); - maybeOpen(item.id); - } - }); - - var targetIcon = JSON.stringify(options); - if (sessionStorage.currentIcon != targetIcon) { - setBrowserActionIcon(options); - sessionStorage.currentIcon = targetIcon; - } - - if (options.anyInProgress && - (pollProgress.tid < 0)) { - pollProgress.start(); - } - }); -} -pollProgress.tid = -1; -pollProgress.MS = 200; - -pollProgress.start = function() { - if (pollProgress.tid < 0) { - pollProgress.tid = setTimeout(pollProgress, pollProgress.MS); - } -}; - -function isNumber(n) { - return !isNaN(parseFloat(n)) && isFinite(n); -} - -if (!isNumber(localStorage.popupLastOpened)) { - localStorage.popupLastOpened = '' + (new Date()).getTime(); -} - -chrome.downloads.onCreated.addListener(function(item) { - pollProgress(); -}); - -pollProgress(); - -function openWhenComplete(downloadId) { - var ids = []; - try { - ids = JSON.parse(localStorage.openWhenComplete); - } catch (e) { - localStorage.openWhenComplete = JSON.stringify(ids); - } - pollProgress.start(); - if (ids.indexOf(downloadId) >= 0) { - return; - } - ids.push(downloadId); - localStorage.openWhenComplete = JSON.stringify(ids); -} - -chrome.runtime.onMessage.addListener(function(request) { - if (request == 'poll') { - pollProgress.start(); - } - if (request == 'icons') { - [16, 19, 38, 128].forEach(function(s) { - var canvas = drawIcon(s); - chrome.downloads.download({ - url: canvas.toDataURL('image/png', 1.0), - filename: 'icon' + s + '.png', - }); - canvas.parentNode.removeChild(canvas); - }); - } - if (isNumber(request.openWhenComplete)) { - openWhenComplete(request.openWhenComplete); - } -});
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon128.png b/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon128.png deleted file mode 100644 index 4d3610d..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon19.png b/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon19.png deleted file mode 100644 index 0aa6033..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon38.png b/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon38.png deleted file mode 100644 index 84563d75..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icon38.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icons.html b/chrome/common/extensions/docs/examples/api/downloads/download_manager/icons.html deleted file mode 100644 index fca4bf2..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icons.html +++ /dev/null
@@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<title>Icon Generator</title> -<script src='icons.js'></script> -</head> -<body> -<button id=download>Generate Manifest Icons</button> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icons.js b/chrome/common/extensions/docs/examples/api/downloads/download_manager/icons.js deleted file mode 100644 index d1bc098..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/icons.js +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright (c) 2013 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. - -window.onload = function() { - var download = document.getElementById('download'); - download.onclick = function() { - chrome.runtime.sendMessage('icons'); - download.disabled = true; - return false; - }; -};
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/manifest.json b/chrome/common/extensions/docs/examples/api/downloads/download_manager/manifest.json deleted file mode 100644 index 156e69c..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{"name": "__MSG_extName__", - "version": "0.3", - "manifest_version": 2, - "description": "__MSG_extDesc__", - "icons": {"128": "icon128.png"}, - "browser_action": { - "default_icon": { - "19": "icon19.png", - "38": "icon38.png"}, - "default_title": "__MSG_extName__", - "default_popup": "popup.html"}, - "background": {"persistent": false, "scripts": ["background.js"]}, - "default_locale": "en", - "optional_permissions": ["management"], - "permissions": ["downloads", "downloads.open", "downloads.shelf"]}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.css b/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.css deleted file mode 100644 index 72c73fc..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.css +++ /dev/null
@@ -1,226 +0,0 @@ -/* Copyright (c) 2013 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. */ - -#outer, -#empty, -#open-folder, -.file-url, -.time-left, -.more-left { - display: inline-block; -} - -#q-outer { - display:inline-block; - height:1.7em; - overflow:hidden; -} - -#q { - margin-right: 2em; -} - -#head { - position: fixed; - z-index: 2; - width: 100%; - left: 0; - top: 0; - background: white; - border-bottom: 1px solid grey; -} - -#search-zero, -#items { - margin-top: 2em; -} - -#head, -#empty, -#searching, -#search-zero, -.item, -.start-time, -.complete-size, -.error, -.file-url-head, -.removed, -.open-filename, -.progress, -.time-left, -.url, -#text-width-probe { - white-space: nowrap; -} - -#head, -.item { - text-align: left; -} - -#empty { - vertical-align: bottom; - height: 2em; -} - -#q { - margin-left: 3%; -} - -.by-ext img, -svg { - width: 2em; - height: 2em; -} - -svg rect.border { - fill-opacity: 0; - stroke-width: 6; -} - -#open-folder svg, -.show-folder svg { - stroke: brown; - fill: white; - stroke-width: 3; -} - -#clear-all svg { - fill: white; - stroke-width: 3; -} - -#clear-all svg, -.remove-file svg, -.erase svg { - stroke: black; -} - -#older, -#loading-older, -.item { - margin-top: 1em; -} - -.more { - position: absolute; - border: 1px solid grey; - background: white; - z-index: 3; -} - -.complete-size, -.error, -.removed, -.open-filename, -.progress, -.time-left { - margin-right: 0.4em; -} - -.error { - color: darkred; -} - -.referrer svg { - stroke: blue; - fill-opacity: 0; - stroke-width: 7; -} - -.removed, -.open-filename { - max-width: 400px; - overflow: hidden; - display: inline-block; -} - -.remove-file svg { - fill-opacity: 0; - stroke-width: 5; -} - -.remove-file svg line { - stroke-width: 7; - stroke: red; -} - -.erase svg ellipse, -.erase svg line { - fill-opacity: 0; - stroke-width: 5; -} - -.pause svg { - stroke: #333; -} - -.resume svg { - stroke: rgb(68, 187, 68); - fill: rgb(68, 187, 68); -} - -.cancel svg line { - stroke-width: 7; -} - -.cancel svg { - stroke: rgb(204, 68, 68); -} - -.meter { - height: 0.5em; - position: relative; - background: grey; -} - -.meter > span { - display: block; - height: 100%; - background-color: rgb(43, 194, 83); - background-image: -webkit-gradient( - linear, left bottom, left top, - color-stop(0, rgb(43,194,83)), - color-stop(1, rgb(84,240,84))); - position: relative; - overflow: hidden; -} - -.meter > span:after { - content: ''; - position: absolute; - top: 0; left: 0; bottom: 0; right: 0; - background-image: -webkit-gradient( - linear, 0 0, 100% 100%, - color-stop(.25, rgba(255, 255, 255, .2)), - color-stop(.25, transparent), - color-stop(.5, transparent), - color-stop(.5, rgba(255, 255, 255, .2)), - color-stop(.75, rgba(255, 255, 255, .2)), - color-stop(.75, transparent), - to(transparent)); - z-index: 1; - -webkit-background-size: 50px 50px; - background-size: 50px 50px; - animation: move 2s linear infinite; - overflow: hidden; -} - -@keyframes move { - 0% { background-position: 0 0; } - 100% { background-position: 50px 50px; } -} - -.url { - color: grey; - max-width: 700px; - overflow: hidden; - display: block; -} - -#text-width-probe { - position: absolute; - top: -100px; - left: 0; -}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.html b/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.html deleted file mode 100644 index 95933be..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.html +++ /dev/null
@@ -1,110 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title></title> - <script src="popup.js"></script> - <link rel="stylesheet" type="text/css" href="popup.css"> - <link rel="icon" href="icon19.png"> -</head> -<body> -<div id="outer"> - <div id="head"> - <a id="bad-chrome-version" hidden - href="https://www.google.com/intl/en/chrome/browser/beta.html"></a> - <span id="empty" hidden></span> - <div id="q-outer"> - <input type="search" id="q" incremental><br> - </div> - <a href="#" id="clear-all"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <ellipse rx="30" ry="8" cx="50" cy="55" /> - <ellipse rx="20" ry="5" cx="50" cy="80" /> - <line x1="20" y1="55" x2="30" y2="83" /> - <line x1="40" y1="60" x2="43" y2="83" /> - <line x1="60" y1="60" x2="56" y2="83" /> - <line x1="80" y1="55" x2="69" y2="83" /> - <polygon points="25,20 35,20 35,40 40,40 30,55 20,40 25,40" /> - <polygon points="45,20 55,20 55,40 60,40 50,55 40,40 45,40" /> - <polygon points="65,20 75,20 75,40 80,40 70,55 60,40 65,40" /> - </g></svg></a> - <a href="#" id="open-folder"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <polygon points="20,20 20,80 60,80 60,30 35,30 35,20" /> - <polygon points="20,80 60,80 80,45 40,45" /> - </g></svg></a> - </div> - <div id="searching" hidden></div> - <div id="search-zero" hidden></div> - <div id="items"></div> - <a href="#" id="older" hidden></a> - <span id="loading-older" hidden></span> - <div id="request-management-permission" hidden><div - id="management-permission-info"></div> - <a href="#" id="grant-management-permission"></a> - </div> -</div> - -<div class="item" hidden> - <img class="icon" src="icon38.png"> - <div class="more" hidden> - <span class="more-left"> - <div class="start-time"></div> - <div class="complete-size"></div> - </span> - <a href="#" class="referrer"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <ellipse cx="35" cy="50" rx="20" ry="20" /> - <ellipse cx="60" cy="50" rx="20" ry="20" /> - </g></svg></a> - <a href="#" class="by-ext"><img /></a> - <a href="#" class="show-folder"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <polygon points="20,20 20,80 60,80 60,30 35,30 35,20" /> - <polygon points="20,80 60,80 80,45 40,45" /> - </g></svg></a> - <a href="#" class="remove-file"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <polygon points="20,45 45,20 75,20 75,75 20,75, 20,45 45,45 45,20" /> - <line x1="45" y1="45" x2="80" y2="80" /> - <line x1="80" y1="45" x2="45" y2="80" /> - </g></svg></a> - <a href="#" class="erase"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <ellipse rx="30" ry="10" cx="50" cy="40" /> - <ellipse rx="20" ry="10" cx="50" cy="70" /> - <line x1="20" y1="35" x2="30" y2="75" /> - <line x1="80" y1="35" x2="65" y2="75" /> - <line x1="50" y1="50" x2="50" y2="80" /> - </g></svg></a> - </div> - <a href="#" class="pause"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <rect x="25" y="25" rx="20" ry="20" width="15" height="50" /> - <rect x="55" y="25" rx="20" ry="20" width="15" height="50" /> - </g></svg></a> - <a href="#" class="resume"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <polygon points="25,25 75,50 25,75"> - </g></svg></a> - <a href="#" class="cancel"><svg viewBox="0 0 100 100"><g> - <rect x="5" y="5" rx="20" ry="20" width="90" height="90" class="border" /> - <line x1="25" y1="25" x2="75" y2="75" /> - <line x1="75" y1="25" x2="25" y2="75" /> - </g></svg></a> - <span class="file-url"> - <div class="file-url-head"> - <span class="removed"></span> - <a href="#" class="open-filename"></a> - <span class="error"></span> - <span class="in-progress"> - <span class="progress"></span> - <span class="time-left"></span> - </span> - </div> - <div class="meter"><span /></div> - <a href="#" class="url" download=""></a> - </span> -</div> -<span id="text-width-probe"></span> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.js b/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.js deleted file mode 100644 index 412a3af..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_manager/popup.js +++ /dev/null
@@ -1,781 +0,0 @@ -// Copyright (c) 2013 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. - -function pointInElement(p, elem) { - return ((p.x >= elem.offsetLeft) && - (p.x <= (elem.offsetLeft + elem.offsetWidth)) && - (p.y >= elem.offsetTop) && - (p.y <= (elem.offsetTop + elem.offsetHeight))); -}; - -function setLastOpened() { - localStorage.popupLastOpened = (new Date()).getTime(); - chrome.runtime.sendMessage('poll'); -}; - -function loadI18nMessages() { - function setProperty(selector, prop, msg) { - document.querySelector(selector)[prop] = chrome.i18n.getMessage(msg); - } - - setProperty('title', 'innerText', 'tabTitle'); - setProperty('#q', 'placeholder', 'searchPlaceholder'); - setProperty('#clear-all', 'title', 'clearAllTitle'); - setProperty('#open-folder', 'title', 'openDownloadsFolderTitle'); - setProperty('#empty', 'innerText', 'zeroItems'); - setProperty('#searching', 'innerText', 'searching'); - setProperty('#search-zero', 'innerText', 'zeroSearchResults'); - setProperty('#management-permission-info', 'innerText', - 'managementPermissionInfo'); - setProperty('#grant-management-permission', 'innerText', - 'grantManagementPermission'); - setProperty('#older', 'innerText', 'showOlderDownloads'); - setProperty('#loading-older', 'innerText', 'loadingOlderDownloads'); - setProperty('.pause', 'title', 'pauseTitle'); - setProperty('.resume', 'title', 'resumeTitle'); - setProperty('.cancel', 'title', 'cancelTitle'); - setProperty('.show-folder', 'title', 'showInFolderTitle'); - setProperty('.erase', 'title', 'eraseTitle'); - setProperty('.url', 'title', 'retryTitle'); - setProperty('.referrer', 'title', 'referrerTitle'); - setProperty('.open-filename', 'title', 'openTitle'); - setProperty('#bad-chrome-version', 'innerText', 'badChromeVersion'); - setProperty('.remove-file', 'title', 'removeFileTitle'); - - document.querySelector('.progress').style.minWidth = - getTextWidth(formatBytes(1024 * 1024 * 1023.9) + '/' + - formatBytes(1024 * 1024 * 1023.9)) + 'px'; - - // This only covers {timeLeft,openWhenComplete}{Finishing,Days}. If - // ...Hours/Minutes/Seconds could be longer for any locale, then this should - // test them. - var max_time_left_width = 0; - for (var i = 0; i < 4; ++i) { - max_time_left_width = Math.max(max_time_left_width, getTextWidth( - formatTimeLeft(0 == (i % 2), - (i < 2) ? 0 : ((100 * 24) + 23) * 60 * 60 * 1000))); - } - document.querySelector('body div.item span.time-left').style.minWidth = - max_time_left_width + 'px'; -}; - -function getTextWidth(s) { - var probe = document.getElementById('text-width-probe'); - probe.innerText = s; - return probe.offsetWidth; -}; - -function formatDateTime(date) { - var now = new Date(); - var zpad_mins = ':' + (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); - if (date.getYear() != now.getYear()) { - return '' + (1900 + date.getYear()); - } else if ((date.getMonth() != now.getMonth()) || - (date.getDate() != now.getDate())) { - return date.getDate() + ' ' + chrome.i18n.getMessage( - 'month' + date.getMonth() + 'abbr'); - } else if (date.getHours() == 12) { - return '12' + zpad_mins + 'pm'; - } else if (date.getHours() > 12) { - return (date.getHours() - 12) + zpad_mins + 'pm'; - } - return date.getHours() + zpad_mins + 'am'; -} - -function formatBytes(n) { - if (n < 1024) { - return n + 'B'; - } - var prefixes = 'KMGTPEZY'; - var mul = 1024; - for (var i = 0; i < prefixes.length; ++i) { - if (n < (1024 * mul)) { - return (parseInt(n / mul) + '.' + parseInt(10 * ((n / mul) % 1)) + - prefixes[i] + 'B'); - } - mul *= 1024; - } - return '!!!'; -} - -function formatTimeLeft(openWhenComplete, ms) { - var prefix = openWhenComplete ? 'openWhenComplete' : 'timeLeft'; - if (ms < 1000) { - return chrome.i18n.getMessage(prefix + 'Finishing'); - } - var days = parseInt(ms / (24 * 60 * 60 * 1000)); - var hours = parseInt(ms / (60 * 60 * 1000)) % 24; - if (days) { - return chrome.i18n.getMessage(prefix + 'Days', [days, hours]); - } - var minutes = parseInt(ms / (60 * 1000)) % 60; - if (hours) { - return chrome.i18n.getMessage(prefix + 'Hours', [hours, minutes]); - } - var seconds = parseInt(ms / 1000) % 60; - if (minutes) { - return chrome.i18n.getMessage(prefix + 'Minutes', [minutes, seconds]); - } - return chrome.i18n.getMessage(prefix + 'Seconds', [seconds]); -} - -function ratchetWidth(w) { - var current = parseInt(document.body.style.minWidth) || 0; - document.body.style.minWidth = Math.max(w, current) + 'px'; -} - -function ratchetHeight(h) { - var current = parseInt(document.body.style.minHeight) || 0; - document.body.style.minHeight = Math.max(h, current) + 'px'; -} - -function binarySearch(array, target, cmp) { - var low = 0, high = array.length - 1, i, comparison; - while (low <= high) { - i = (low + high) >> 1; - comparison = cmp(target, array[i]); - if (comparison < 0) { - low = i + 1; - } else if (comparison > 0) { - high = i - 1; - } else { - return i; - } - } - return i; -}; - -function arrayFrom(seq) { - return Array.prototype.slice.apply(seq); -}; - -function DownloadItem(data) { - var item = this; - for (var prop in data) { - item[prop] = data[prop]; - } - item.startTime = new Date(item.startTime); - if (item.canResume == undefined) { - DownloadItem.canResumeHack = true; - } - - item.div = document.querySelector('body>div.item').cloneNode(true); - item.div.id = 'item' + item.id; - item.div.item = item; - - var items_div = document.getElementById('items'); - if ((items_div.childNodes.length == 0) || - (item.startTime.getTime() < items_div.childNodes[ - items_div.childNodes.length - 1].item.startTime.getTime())) { - items_div.appendChild(item.div); - } else if (item.startTime.getTime() > - items_div.childNodes[0].item.startTime.getTime()) { - items_div.insertBefore(item.div, items_div.childNodes[0]); - } else { - var adjacent_div = items_div.childNodes[ - binarySearch(arrayFrom(items_div.childNodes), - item.startTime.getTime(), - function(target, other) { - return target - other.item.startTime.getTime(); - })]; - var adjacent_item = adjacent_div.item; - if (adjacent_item.startTime.getTime() < item.startTime.getTime()) { - items_div.insertBefore(item.div, adjacent_div); - } else { - items_div.insertBefore(item.div, adjacent_div.nextSibling); - } - } - - item.getElement('referrer').onclick = function() { - chrome.tabs.create({url: item.referrer}); - return false; - }; - item.getElement('by-ext').onclick = function() { - chrome.tabs.create({url: 'chrome://extensions#' + item.byExtensionId}); - return false; - } - item.getElement('open-filename').onclick = function() { - item.open(); - return false; - }; - item.getElement('pause').onclick = function() { - item.pause(); - return false; - }; - item.getElement('cancel').onclick = function() { - item.cancel(); - return false; - }; - item.getElement('resume').onclick = function() { - item.resume(); - return false; - }; - item.getElement('show-folder').onclick = function() { - item.show(); - return false; - }; - item.getElement('remove-file').onclick = function() { - item.removeFile(); - return false; - }; - item.getElement('erase').onclick = function() { - item.erase(); - return false; - }; - - item.more_mousemove = function(evt) { - var mouse = {x:evt.x, y:evt.y+document.body.scrollTop}; - if (item.getElement('more') && - (pointInElement(mouse, item.div) || - pointInElement(mouse, item.getElement('more')))) { - return; - } - if (item.getElement('more')) { - item.getElement('more').hidden = true; - } - window.removeEventListener('mousemove', item.more_mousemove); - }; - [item.div, item.getElement('more')].concat( - item.getElement('more').children).forEach(function(elem) { - elem.onmouseover = function() { - arrayFrom(items_div.children).forEach(function(other) { - if (other.item != item) { - other.item.getElement('more').hidden = true; - } - }); - item.getElement('more').hidden = false; - item.getElement('more').style.top = - (item.div.offsetTop + item.div.offsetHeight) + 'px'; - item.getElement('more').style.left = item.div.offsetLeft + 'px'; - if (window.innerHeight < (parseInt(item.getElement('more').style.top) + - item.getElement('more').offsetHeight)) { - item.getElement('more').style.top = ( - item.div.offsetTop - item.getElement('more').offsetHeight) + 'px'; - } - window.addEventListener('mousemove', item.more_mousemove); - }; - }); - - if (item.referrer) { - item.getElement('referrer').href = item.referrer; - } else { - item.getElement('referrer').hidden = true; - } - item.getElement('url').href = item.url; - item.getElement('url').innerText = item.url; - item.render(); -} -DownloadItem.canResumeHack = false; - -DownloadItem.prototype.getElement = function(name) { - return document.querySelector('#item' + this.id + ' .' + name); -}; - -DownloadItem.prototype.render = function() { - var item = this; - var now = new Date(); - var in_progress = (item.state == 'in_progress') - var openable = (item.state != 'interrupted') && item.exists && !item.deleted; - - item.startTime = new Date(item.startTime); - if (DownloadItem.canResumeHack) { - item.canResume = in_progress && item.paused; - } - if (item.filename) { - item.basename = item.filename.substring(Math.max( - item.filename.lastIndexOf('\\'), - item.filename.lastIndexOf('/')) + 1); - } - if (item.estimatedEndTime) { - item.estimatedEndTime = new Date(item.estimatedEndTime); - } - if (item.endTime) { - item.endTime = new Date(item.endTime); - } - - if (item.filename && !item.icon_url) { - chrome.downloads.getFileIcon( - item.id, - {'size': 32}, - function(icon_url) { - item.getElement('icon').hidden = !icon_url; - if (icon_url) { - item.icon_url = icon_url; - item.getElement('icon').src = icon_url; - } - }); - } - - item.getElement('removed').style.display = openable ? 'none' : 'inline'; - item.getElement('open-filename').style.display = ( - openable ? 'inline' : 'none'); - item.getElement('in-progress').hidden = !in_progress; - item.getElement('pause').style.display = ( - !in_progress || item.paused) ? 'none' : 'inline-block'; - item.getElement('resume').style.display = ( - !in_progress || !item.canResume) ? 'none' : 'inline-block'; - item.getElement('cancel').style.display = ( - !in_progress ? 'none' : 'inline-block'); - item.getElement('remove-file').hidden = ( - (item.state != 'complete') || - !item.exists || - item.deleted || - !chrome.downloads.removeFile); - item.getElement('erase').hidden = in_progress; - - var could_progress = in_progress || item.canResume; - item.getElement('progress').style.display = ( - could_progress ? 'inline-block' : 'none'); - item.getElement('meter').hidden = !could_progress || !item.totalBytes; - - item.getElement('removed').innerText = item.basename; - item.getElement('open-filename').innerText = item.basename; - - function setByExtension(show) { - if (show) { - item.getElement('by-ext').title = item.byExtensionName; - item.getElement('by-ext').href = - 'chrome://extensions#' + item.byExtensionId; - item.getElement('by-ext img').src = - 'chrome://extension-icon/' + item.byExtensionId + '/48/1'; - } else { - item.getElement('by-ext').hidden = true; - } - } - if (item.byExtensionId && item.byExtensionName) { - chrome.permissions.contains({permissions: ['management']}, - function(result) { - if (result) { - setByExtension(true); - } else { - setByExtension(false); - if (!localStorage.managementPermissionDenied) { - document.getElementById('request-management-permission').hidden = - false; - document.getElementById('grant-management-permission').onclick = - function() { - chrome.permissions.request({permissions: ['management']}, - function(granted) { - setByExtension(granted); - if (!granted) { - localStorage.managementPermissionDenied = true; - } - }); - return false; - }; - } - } - }); - } else { - setByExtension(false); - } - - if (!item.getElement('error').hidden) { - if (item.error) { - // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is - // released, set minimum_chrome_version and remove the error_N messages. - item.getElement('error').innerText = chrome.i18n.getMessage( - 'error_' + item.error); - if (!item.getElement('error').innerText) { - item.getElement('error').innerText = item.error; - } - } else if (!openable) { - item.getElement('error').innerText = chrome.i18n.getMessage( - 'errorRemoved'); - } - } - - item.getElement('complete-size').innerText = formatBytes( - item.bytesReceived); - if (item.totalBytes && (item.state != 'complete')) { - item.getElement('progress').innerText = ( - item.getElement('complete-size').innerText + '/' + - formatBytes(item.totalBytes)); - item.getElement('meter').children[0].style.width = parseInt( - 100 * item.bytesReceived / item.totalBytes) + '%'; - } - - if (in_progress) { - if (item.estimatedEndTime && !item.paused) { - var openWhenComplete = false; - try { - openWhenComplete = JSON.parse(localStorage.openWhenComplete).indexOf( - item.id) >= 0; - } catch (e) { - } - item.getElement('time-left').innerText = formatTimeLeft( - openWhenComplete, item.estimatedEndTime.getTime() - now.getTime()); - } else { - item.getElement('time-left').innerText = String.fromCharCode(160); - } - } - - if (item.startTime) { - item.getElement('start-time').innerText = formatDateTime( - item.startTime); - } - - ratchetWidth(item.getElement('icon').offsetWidth + - item.getElement('file-url').offsetWidth + - item.getElement('cancel').offsetWidth + - item.getElement('pause').offsetWidth + - item.getElement('resume').offsetWidth); - ratchetWidth(item.getElement('more').offsetWidth); - - this.maybeAccept(); -}; - -DownloadItem.prototype.onChanged = function(delta) { - for (var key in delta) { - if (key != 'id') { - this[key] = delta[key].current; - } - } - this.render(); - if (delta.state) { - setLastOpened(); - } - if ((this.state == 'in_progress') && !this.paused) { - DownloadManager.startPollingProgress(); - } -}; - -DownloadItem.prototype.onErased = function() { - window.removeEventListener('mousemove', this.more_mousemove); - document.getElementById('items').removeChild(this.div); -}; - -DownloadItem.prototype.show = function() { - chrome.downloads.show(this.id); -}; - -DownloadItem.prototype.open = function() { - if (this.state == 'complete') { - chrome.downloads.open(this.id); - return; - } - chrome.runtime.sendMessage({openWhenComplete:this.id}); -}; - -DownloadItem.prototype.removeFile = function() { - chrome.downloads.removeFile(this.id); - this.deleted = true; - this.render(); -}; - -DownloadItem.prototype.erase = function() { - chrome.downloads.erase({id: this.id}); -}; - -DownloadItem.prototype.pause = function() { - chrome.downloads.pause(this.id); -}; - -DownloadItem.prototype.resume = function() { - chrome.downloads.resume(this.id); -}; - -DownloadItem.prototype.cancel = function() { - chrome.downloads.cancel(this.id); -}; - -DownloadItem.prototype.maybeAccept = function() { - // This function is safe to call at any time for any item, and it will always - // do the right thing, which is to display the danger prompt only if the item - // is in_progress and dangerous, and if the prompt is not already displayed. - if ((this.state != 'in_progress') || - (this.danger == 'safe') || - (this.danger == 'accepted') || - DownloadItem.prototype.maybeAccept.accepting_danger) { - return; - } - ratchetWidth(400); - ratchetHeight(200); - DownloadItem.prototype.maybeAccept.accepting_danger = true; - // On Mac, window.onload is run while the popup is animating in, before it is - // considered "visible". Prompts will not be displayed over an invisible - // window, so the popup will become stuck. Just wait a little bit for the - // window to finish animating in. http://crbug.com/280107 - // This has been fixed, so this setTimeout can be removed when the fix has - // been released to stable, and minimum_chrome_version can be set. - var id = this.id; - setTimeout(function() { - chrome.downloads.acceptDanger(id, function() { - DownloadItem.prototype.maybeAccept.accepting_danger = false; - arrayFrom(document.getElementById('items').childNodes).forEach( - function(item_div) { item_div.item.maybeAccept(); }); - }); - }, 500); -}; -DownloadItem.prototype.maybeAccept.accepting_danger = false; - -var DownloadManager = {}; - -DownloadManager.showingOlder = false; - -DownloadManager.getItem = function(id) { - var item_div = document.getElementById('item' + id); - return item_div ? item_div.item : null; -}; - -DownloadManager.getOrCreate = function(data) { - var item = DownloadManager.getItem(data.id); - return item ? item : new DownloadItem(data); -}; - -DownloadManager.forEachItem = function(cb) { - // Calls cb(item, index) in the order that they are displayed, i.e. in order - // of decreasing startTime. - arrayFrom(document.getElementById('items').childNodes).forEach( - function(item_div, index) { cb(item_div.item, index); }); -}; - -DownloadManager.startPollingProgress = function() { - if (DownloadManager.startPollingProgress.tid < 0) { - DownloadManager.startPollingProgress.tid = setTimeout( - DownloadManager.startPollingProgress.pollProgress, - DownloadManager.startPollingProgress.MS); - } -} -DownloadManager.startPollingProgress.MS = 200; -DownloadManager.startPollingProgress.tid = -1; -DownloadManager.startPollingProgress.pollProgress = function() { - DownloadManager.startPollingProgress.tid = -1; - chrome.downloads.search({state: 'in_progress', paused: false}, - function(results) { - if (!results.length) - return; - results.forEach(function(result) { - var item = DownloadManager.getOrCreate(result); - for (var prop in result) { - item[prop] = result[prop]; - } - item.render(); - if ((item.state == 'in_progress') && !item.paused) { - DownloadManager.startPollingProgress(); - } - }); - }); -}; - -DownloadManager.showNew = function() { - var any_items = (document.getElementById('items').childNodes.length > 0); - document.getElementById('empty').style.display = - any_items ? 'none' : 'inline-block'; - document.getElementById('head').style.borderBottomWidth = - (any_items ? 1 : 0) + 'px'; - document.getElementById('clear-all').hidden = !any_items; - - var query_search = document.getElementById('q'); - query_search.hidden = !any_items; - - if (!any_items) { - return; - } - var old_ms = (new Date()).getTime() - kOldMs; - var any_hidden = false; - var any_showing = false; - // First show up to kShowNewMax items newer than kOldMs. If there aren't any - // items newer than kOldMs, then show up to kShowNewMax items of any age. If - // there are any hidden items, show the Show Older button. - DownloadManager.forEachItem(function(item, index) { - item.div.hidden = !DownloadManager.showingOlder && ( - (item.startTime.getTime() < old_ms) || (index >= kShowNewMax)); - any_hidden = any_hidden || item.div.hidden; - any_showing = any_showing || !item.div.hidden; - }); - if (!any_showing) { - any_hidden = false; - DownloadManager.forEachItem(function(item, index) { - item.div.hidden = !DownloadManager.showingOlder && (index >= kShowNewMax); - any_hidden = any_hidden || item.div.hidden; - any_showing = any_showing || !item.div.hidden; - }); - } - document.getElementById('older').hidden = !any_hidden; - - query_search.focus(); -}; - -DownloadManager.showOlder = function() { - DownloadManager.showingOlder = true; - var loading_older_span = document.getElementById('loading-older'); - document.getElementById('older').hidden = true; - loading_older_span.hidden = false; - chrome.downloads.search({}, function(results) { - results.forEach(function(result) { - var item = DownloadManager.getOrCreate(result); - item.div.hidden = false; - }); - loading_older_span.hidden = true; - }); -}; - -DownloadManager.onSearch = function() { - // split string by space, but ignore space in quotes - // http://stackoverflow.com/questions/16261635 - var query = document.getElementById('q').value.match(/(?:[^\s"]+|"[^"]*")+/g); - if (!query) { - DownloadManager.showNew(); - document.getElementById('search-zero').hidden = true; - } else { - query = query.map(function(term) { - // strip quotes - return (term.match(/\s/) && - term[0].match(/["']/) && - term[term.length - 1] == term[0]) ? - term.substr(1, term.length - 2) : term; - }); - var searching = document.getElementById('searching'); - searching.hidden = false; - chrome.downloads.search({query: query}, function(results) { - document.getElementById('older').hidden = true; - DownloadManager.forEachItem(function(item) { - item.div.hidden = true; - }); - results.forEach(function(result) { - DownloadManager.getOrCreate(result).div.hidden = false; - }); - searching.hidden = true; - document.getElementById('search-zero').hidden = (results.length != 0); - }); - } -}; - -DownloadManager.clearAll = function() { - DownloadManager.forEachItem(function(item) { - if (!item.div.hidden) { - item.erase(); - // The onErased handler should circle back around to loadItems. - } - }); -}; - -var kShowNewMax = 50; -var kOldMs = 1000 * 60 * 60 * 24 * 7; - -// These settings can be tuned by modifying localStorage in dev-tools. -if ('kShowNewMax' in localStorage) { - kShowNewMax = parseInt(localStorage.kShowNewMax); -} -if ('kOldMs' in localStorage) { - kOldMs = parseInt(localStorage.kOldMs); -} - -DownloadManager.loadItems = function() { - // Request up to kShowNewMax + 1, but only display kShowNewMax; the +1 is a - // probe to see if there are any older downloads. - // TODO(benjhayden) When https://codereview.chromium.org/16924017/ is - // released, set minimum_chrome_version and remove this try/catch. - try { - chrome.downloads.search({ - orderBy: ['-startTime'], - limit: kShowNewMax + 1}, - function(results) { - DownloadManager.loadItems.items = results; - DownloadManager.loadItems.onLoaded(); - }); - } catch (exc) { - chrome.downloads.search({ - orderBy: '-startTime', - limit: kShowNewMax + 1}, - function(results) { - DownloadManager.loadItems.items = results; - DownloadManager.loadItems.onLoaded(); - }); - } -}; -DownloadManager.loadItems.items = []; -DownloadManager.loadItems.window_loaded = false; - -DownloadManager.loadItems.onLoaded = function() { - if (!DownloadManager.loadItems.window_loaded) { - return; - } - DownloadManager.loadItems.items.forEach(function(item) { - DownloadManager.getOrCreate(item); - }); - DownloadManager.loadItems.items = []; - DownloadManager.showNew(); -}; - -DownloadManager.loadItems.onWindowLoaded = function() { - DownloadManager.loadItems.window_loaded = true; - DownloadManager.loadItems.onLoaded(); -}; - -// If this extension is installed on a stable-channel chrome, where the -// downloads API is not available, do not use the downloads API, and link to the -// beta channel. -if (chrome.downloads) { - // Start searching ASAP, don't wait for onload. - DownloadManager.loadItems(); - - chrome.downloads.onCreated.addListener(function(item) { - DownloadManager.getOrCreate(item); - DownloadManager.showNew(); - DownloadManager.startPollingProgress(); - }); - - chrome.downloads.onChanged.addListener(function(delta) { - var item = DownloadManager.getItem(delta.id); - if (item) { - item.onChanged(delta); - } - }); - - chrome.downloads.onErased.addListener(function(id) { - var item = DownloadManager.getItem(id); - if (!item) { - return; - } - item.onErased(); - DownloadManager.loadItems(); - }); - - window.onload = function() { - ratchetWidth( - document.getElementById('q-outer').offsetWidth + - document.getElementById('clear-all').offsetWidth + - document.getElementById('open-folder').offsetWidth); - setLastOpened(); - loadI18nMessages(); - DownloadManager.loadItems.onWindowLoaded(); - document.getElementById('older').onclick = function() { - DownloadManager.showOlder(); - return false; - }; - document.getElementById('q').onsearch = function() { - DownloadManager.onSearch(); - }; - document.getElementById('clear-all').onclick = function() { - DownloadManager.clearAll(); - return false; - }; - if (chrome.downloads.showDefaultFolder) { - document.getElementById('open-folder').onclick = function() { - chrome.downloads.showDefaultFolder(); - return false; - }; - } else { - document.getElementById('open-folder').hidden = true; - } - }; -} else { - // The downloads API is not available. - // TODO(benjhayden) Remove this when minimum_chrome_version is set. - window.onload = function() { - loadI18nMessages(); - var bad_version = document.getElementById('bad-chrome-version'); - bad_version.hidden = false; - bad_version.onclick = function() { - chrome.tabs.create({url: bad_version.href}); - return false; - }; - document.getElementById('empty').style.display = 'none'; - document.getElementById('q').style.display = 'none'; - document.getElementById('open-folder').style.display = 'none'; - document.getElementById('clear-all').style.display = 'none'; - }; -}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_open/_locales/en/messages.json b/chrome/common/extensions/docs/examples/api/downloads/download_open/_locales/en/messages.json deleted file mode 100644 index eae1fbe9..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_open/_locales/en/messages.json +++ /dev/null
@@ -1,9 +0,0 @@ -{"extName": { - "message": "Download and Open Button", - "description": "Extension name"}, - "extDesc": { - "message": "Download and Open Context Menu Button", - "description": "Extension description"}, - "openContextMenuTitle": { - "message": "Download and Open", - "description": "context menu button text"}}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_open/background.js b/chrome/common/extensions/docs/examples/api/downloads/download_open/background.js deleted file mode 100644 index bfc40ec5..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_open/background.js +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright (c) 2013 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. - -function getOpeningIds() { - var ids = []; - try { - ids = JSON.parse(localStorage.openWhenComplete); - } catch (e) { - localStorage.openWhenComplete = JSON.stringify(ids); - } - return ids; -} - -function setOpeningIds(ids) { - localStorage.openWhenComplete = JSON.stringify(ids); -} - -chrome.downloads.onChanged.addListener(function(delta) { - if (!delta.state || - (delta.state.current != 'complete')) { - return; - } - var ids = getOpeningIds(); - if (ids.indexOf(delta.id) < 0) { - return; - } - chrome.downloads.open(delta.id); - ids.splice(ids.indexOf(delta.id), 1); - setOpeningIds(ids); -}); - -chrome.contextMenus.onClicked.addListener(function(info, tab) { - chrome.downloads.download({url: info.linkUrl}, function(downloadId) { - var ids = getOpeningIds(); - if (ids.indexOf(downloadId) >= 0) { - return; - } - ids.push(downloadId); - setOpeningIds(ids); - }); -}); - -chrome.contextMenus.create({ - id: 'open', - title: chrome.i18n.getMessage('openContextMenuTitle'), - contexts: ['link'], -});
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_open/icon128.png b/chrome/common/extensions/docs/examples/api/downloads/download_open/icon128.png deleted file mode 100644 index 50b99a1..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_open/icon128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_open/icon16.png b/chrome/common/extensions/docs/examples/api/downloads/download_open/icon16.png deleted file mode 100644 index 0f3aceb..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_open/icon16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/downloads/download_open/manifest.json b/chrome/common/extensions/docs/examples/api/downloads/download_open/manifest.json deleted file mode 100644 index 98a49ab..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/download_open/manifest.json +++ /dev/null
@@ -1,8 +0,0 @@ -{"name": "__MSG_extName__", - "version": "0.1", - "manifest_version": 2, - "description": "__MSG_extDesc__", - "icons": {"16": "icon16.png", "128": "icon128.png"}, - "background": {"persistent": false, "scripts": ["background.js"]}, - "default_locale": "en", - "permissions": ["contextMenus", "downloads", "downloads.open"]}
diff --git a/chrome/common/extensions/docs/examples/api/downloads/downloads_overwrite/bg.js b/chrome/common/extensions/docs/examples/api/downloads/downloads_overwrite/bg.js deleted file mode 100644 index f01c7b1..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/downloads_overwrite/bg.js +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Force all downloads to overwrite any existing files instead of inserting -// ' (1)', ' (2)', etc. - -chrome.downloads.onDeterminingFilename.addListener(function(item, suggest) { - suggest({filename: item.filename, - conflict_action: 'overwrite', - conflictAction: 'overwrite'}); - // conflict_action was renamed to conflictAction in - // https://chromium.googlesource.com/chromium/src/+/f1d784d6938b8fe8e0d257e41b26341992c2552c - // which was first picked up in branch 1580. -});
diff --git a/chrome/common/extensions/docs/examples/api/downloads/downloads_overwrite/manifest.json b/chrome/common/extensions/docs/examples/api/downloads/downloads_overwrite/manifest.json deleted file mode 100644 index c1f8999d..0000000 --- a/chrome/common/extensions/docs/examples/api/downloads/downloads_overwrite/manifest.json +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "name": "Downloads Overwrite Existing Files", - "description": "All downloads overwrite existing files instead of adding ' (1)', ' (2)', etc.", - "version": "1", - "minimum_chrome_version": "26.0.1428", - "background": { - "scripts": ["bg.js"], - "persistent": false - }, - "permissions": [ - "downloads" - ], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/eventPage/basic/background.js b/chrome/common/extensions/docs/examples/api/eventPage/basic/background.js deleted file mode 100644 index fe937e0f5..0000000 --- a/chrome/common/extensions/docs/examples/api/eventPage/basic/background.js +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Global variables only exist for the life of the page, so they get reset -// each time the page is unloaded. -var counter = 1; - -var lastTabId = -1; -function sendMessage() { - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - lastTabId = tabs[0].id; - chrome.tabs.sendMessage(lastTabId, "Background page started."); - }); -} - -sendMessage(); -chrome.browserAction.setBadgeText({text: "ON"}); -console.log("Loaded."); - -chrome.runtime.onInstalled.addListener(function() { - console.log("Installed."); - - // localStorage is persisted, so it's a good place to keep state that you - // need to persist across page reloads. - localStorage.counter = 1; - - // Register a webRequest rule to redirect bing to google. - var wr = chrome.declarativeWebRequest; - chrome.declarativeWebRequest.onRequest.addRules([{ - id: "0", - conditions: [new wr.RequestMatcher({url: {hostSuffix: "bing.com"}})], - actions: [new wr.RedirectRequest({redirectUrl: "http://google.com"})] - }]); -}); - -chrome.bookmarks.onRemoved.addListener(function(id, info) { - alert("I never liked that site anyway."); -}); - -chrome.browserAction.onClicked.addListener(function() { - // The event page will unload after handling this event (assuming nothing - // else is keeping it awake). The content script will become the main way to - // interact with us. - chrome.tabs.create({url: "http://google.com"}, function(tab) { - chrome.tabs.executeScript(tab.id, {file: "content.js"}, function() { - // Note: we also sent a message above, upon loading the event page, - // but the content script will not be loaded at that point, so we send - // another here. - sendMessage(); - }); - }); -}); - -chrome.commands.onCommand.addListener(function(command) { - chrome.tabs.create({url: "http://www.google.com/"}); -}); - -chrome.runtime.onMessage.addListener(function(msg, _, sendResponse) { - if (msg.setAlarm) { - // For testing only. delayInMinutes will be rounded up to at least 1 in a - // packed or released extension. - chrome.alarms.create({delayInMinutes: 0.1}); - } else if (msg.delayedResponse) { - // Note: setTimeout itself does NOT keep the page awake. We return true - // from the onMessage event handler, which keeps the message channel open - - // in turn keeping the event page awake - until we call sendResponse. - setTimeout(function() { - sendResponse("Got your message."); - }, 5000); - return true; - } else if (msg.getCounters) { - sendResponse({counter: counter++, - persistentCounter: localStorage.counter++}); - } - // If we don't return anything, the message channel will close, regardless - // of whether we called sendResponse. -}); - -chrome.alarms.onAlarm.addListener(function() { - alert("Time's up!"); -}); - -chrome.runtime.onSuspend.addListener(function() { - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - // After the unload event listener runs, the page will unload, so any - // asynchronous callbacks will not fire. - alert("This does not show up."); - }); - console.log("Unloading."); - chrome.browserAction.setBadgeText({text: ""}); - chrome.tabs.sendMessage(lastTabId, "Background page unloaded."); -});
diff --git a/chrome/common/extensions/docs/examples/api/eventPage/basic/content.js b/chrome/common/extensions/docs/examples/api/eventPage/basic/content.js deleted file mode 100644 index 3bb880cc..0000000 --- a/chrome/common/extensions/docs/examples/api/eventPage/basic/content.js +++ /dev/null
@@ -1,50 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -document.body.innerHTML = ""; - -function addButton(name, cb) { - var a = document.createElement("button"); - a.innerText = name; - a.onclick = cb; - document.body.appendChild(document.createElement("br")); - document.body.appendChild(a); -} - -function log(str) { - console.log(str); - logDiv.innerHTML += str + "<br>"; -} - -addButton("Clear logs", function() { - logDiv.innerHTML = ""; -}); - -addButton("Send message with delayed response", function() { - chrome.runtime.sendMessage({delayedResponse: true}, function(response) { - log("Background page responded: " + response); - }); -}); - -addButton("Show counters", function() { - chrome.runtime.sendMessage({getCounters: true}, function(response) { - log("In-memory counter is: " + response.counter); - log("Persisted counter is: " + response.persistentCounter); - }); -}); - -addButton("Set an alarm", function() { - chrome.runtime.sendMessage({setAlarm: true}); -}); - -chrome.runtime.onMessage.addListener(function(msg, _, sendResponse) { - log("Got message from background page: " + msg); -}); - -var logDiv = document.createElement("div"); -logDiv.style.border = "1px dashed black"; -document.body.appendChild(document.createElement("br")); -document.body.appendChild(logDiv); - -log("Ready.");
diff --git a/chrome/common/extensions/docs/examples/api/eventPage/basic/icon.png b/chrome/common/extensions/docs/examples/api/eventPage/basic/icon.png deleted file mode 100644 index 821bc49..0000000 --- a/chrome/common/extensions/docs/examples/api/eventPage/basic/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/eventPage/basic/manifest.json b/chrome/common/extensions/docs/examples/api/eventPage/basic/manifest.json deleted file mode 100644 index 7a6e1f43..0000000 --- a/chrome/common/extensions/docs/examples/api/eventPage/basic/manifest.json +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "name": "Event Page Example", - "description": "Demonstrates usage and features of the event page", - "version": "1.0", - "manifest_version": 2, - "permissions": ["alarms", "tabs", "bookmarks", "declarativeWebRequest", "*://*/*"], - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "browser_action": { - "default_icon" : "icon.png", - "default_title": "Start Event Page" - }, - "commands": { - "open-google": { - "description": "Open a tab to google.com", - "suggested_key": { "default": "Ctrl+Shift+L" } - }, - "_execute_browser_action": { - "suggested_key": { "default": "Ctrl+Shift+K" } - } - } -}
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/manifest.json b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/manifest.json deleted file mode 100644 index 66241fc3..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/manifest.json +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "name" : "`extension.isAllowedFileSchemeAccess` and `extension.isAllowedIncognitoAccess` Example", - "version" : "1.0.0", - "description" : "Demonstrates the `extension.isAllowedFileSchemeAccess` and `extesion.isAllowedIncognitoAccess` APIs", - "permissions" : [ "file://*" ], - "browser_action" : { - "default_popup": "popup.html", - "default_icon" : "sample-19.png" - }, - "icons" : { - "16" : "sample-16.png", - "48" : "sample-48.png", - "128" : "sample-128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/popup.html b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/popup.html deleted file mode 100644 index 29f8071..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/popup.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2011 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. ---> -<html> - <head> - <title>extension.isAllowedAccess Sample</title> - <link rel="stylesheet" href="./sample.css"> - </head> - <body> - <h1>extension.isAllowedAccess Sample</h1> - <section> - <ol> - <li><p> - <span>1</span> chrome.extension.isAllowedFileSchemeAccess: - <code id="file">unknown</code> (unpacked extensions always have - file scheme access, you'll need to install this as a packed - extension to toggle it properly) - </p></li> - <li><p> - <span>2</span> chrome.extension.isAllowedIncognitoAccess: - <code id="incognito">unknown</code> - </p></li> - </ol> - </section> - <script src="./popup.js"></script> - <script> - </script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/popup.js b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/popup.js deleted file mode 100644 index 27a7f400..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/popup.js +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright (c) 2011 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. - -chrome.extension.isAllowedFileSchemeAccess(function(state) { - var el = document.getElementById('file'); - el.textContent = el.className = state ? 'true': 'false'; -}); -chrome.extension.isAllowedIncognitoAccess(function(state) { - var el = document.getElementById('incognito'); - el.textContent = el.className = state ? 'true': 'false'; -});
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-128.png b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-128.png deleted file mode 100644 index 19a29c81..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-16.png b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-16.png deleted file mode 100644 index 5308fc9..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-19.png b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-19.png deleted file mode 100644 index 108b2a7..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-48.png b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-48.png deleted file mode 100644 index 617bc3db..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample.css b/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample.css deleted file mode 100644 index 2f35d4a..0000000 --- a/chrome/common/extensions/docs/examples/api/extension/isAllowedAccess/sample.css +++ /dev/null
@@ -1,61 +0,0 @@ -body { - margin: 5px 10px 10px; -} - -h1 { - color: #53637D; - font: 26px/1.2 Helvetica, sans-serif; - font-size: 200%; - margin: 0; - padding-bottom: 4px; - text-shadow: white 0 1px 2px; -} - -body > section { - border-radius: 5px; - background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #EAEEF3), - -webkit-linear-gradient(left, #EAEEF3, #EAEEF3 97%, #D3D7DB); - font: 14px/1 Arial,Sans Serif; - padding: 10px; - width: 563px; - max-height: 400px; - overflow-y: auto; - box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5); -} - -body > section > ol { - padding: 0; - margin: 0; - list-style: none inside; -} - -body > section > ol > li { - position: relative; - margin: 0.5em 0 0.5em 40px; -} - -code { - word-wrap: break-word; - background: rgba(255,255,0, 0.5); -} - code.true { - background: rgba(0, 255, 0, 0.5); - } - code.false { - background: rgba(255, 0, 0, 0.5); - } - -li > p > span:first-child { - position: absolute; - top: 0px; - left: -40px; - width: 30px; - text-align: right; - font: 30px/1 Helvetica, sans-serif; - font-weight: 700; -} - -p { - min-height: 30px; - line-height: 1.2; -}
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js b/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js deleted file mode 100644 index 303a52e..0000000 --- a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/background.js +++ /dev/null
@@ -1,257 +0,0 @@ -// Copyright 2014 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. - -'use strict'; - -// Metadata is stored in files as serialized to JSON maps. See contents of -// example1.fake and example2.fake. - -// Multiple volumes can be opened at the same time. The key is the -// fileSystemId, which is the same as the file's displayPath. -// The value is a Volume object. -var volumes = {}; - -// Defines a volume object that contains information about a mounted file -// system. -function Volume(entry, metadata, openedFiles) { - // Used for restoring the opened file entry after resuming the event page. - this.entry = entry; - - // The volume metadata. - this.metadata = []; - for (var path in metadata) { - this.metadata[path] = metadata[path]; - // Date object is serialized in JSON as string. - this.metadata[path].modificationTime = - new Date(metadata[path].modificationTime); - } - - // A map with currently opened files. The key is a requestId value from the - // openFileRequested event, and the value is the file path. - this.openedFiles = openedFiles; -}; - -function onUnmountRequested(options, onSuccess, onError) { - restoreState(options.fileSystemId, function() { - if (Object.keys(volumes[options.fileSystemId].openedFiles).length != 0) { - onError('IN_USE'); - return; - } - - chrome.fileSystemProvider.unmount( - {fileSystemId: options.fileSystemId}, - function() { - if (chrome.runtime.lastError) { - onError(chrome.runtime.lastError.message); - return; - } - delete volumes[options.fileSystemId]; - saveState(); // Remove volume from local storage state. - onSuccess(); - }); - }, onError); -}; - -function onGetMetadataRequested(options, onSuccess, onError) { - restoreState(options.fileSystemId, function () { - var entryMetadata = - volumes[options.fileSystemId].metadata[options.entryPath]; - if (!entryMetadata) - error('NOT_FOUND'); - else - onSuccess(entryMetadata); - }, onError); -}; - -function onReadDirectoryRequested(options, onSuccess, onError) { - restoreState(options.fileSystemId, function () { - var directoryMetadata = - volumes[options.fileSystemId].metadata[options.directoryPath]; - if (!directoryMetadata) { - onError('NOT_FOUND'); - return; - } - if (!directoryMetadata.isDirectory) { - onError('NOT_A_DIRECTORY'); - return; - } - - // Retrieve directory contents from metadata. - var entries = []; - for (var entry in volumes[options.fileSystemId].metadata) { - // Do not add itself on the list. - if (entry == options.directoryPath) - continue; - // Check if the entry is a child of the requested directory. - if (entry.indexOf(options.directoryPath) != 0) - continue; - // Restrict to direct children only. - if (entry.substring(options.directoryPath.length + 1).indexOf('/') != -1) - continue; - - entries.push(volumes[options.fileSystemId].metadata[entry]); - } - onSuccess(entries, false /* Last call. */); - }, onError); -}; - -function onOpenFileRequested(options, onSuccess, onError) { - restoreState(options.fileSystemId, function () { - if (options.mode != 'READ' || options.create) { - onError('INVALID_OPERATION'); - } else { - volumes[options.fileSystemId].openedFiles[options.requestId] = - options.filePath; - onSuccess(); - } - }, onError); -}; - -function onCloseFileRequested(options, onSuccess, onError) { - restoreState(options.fileSystemId, function () { - if (!volumes[options.fileSystemId].openedFiles[options.openRequestId]) { - onError('INVALID_OPERATION'); - } else { - delete volumes[options.fileSystemId].openedFiles[options.openRequestId]; - onSuccess(); - } - }, onError); -}; - -function onReadFileRequested(options, onSuccess, onError) { - restoreState(options.fileSystemId, function () { - var filePath = - volumes[options.fileSystemId].openedFiles[options.openRequestId]; - if (!filePath) { - onError('INVALID_OPERATION'); - return; - } - - var contents = volumes[options.fileSystemId].metadata[filePath].contents; - - // Write the contents as ASCII text. - var buffer = new ArrayBuffer(options.length); - var bufferView = new Uint8Array(buffer); - for (var i = 0; i < options.length; i++) { - bufferView[i] = contents.charCodeAt(i); - } - - onSuccess(buffer, false /* Last call. */); - }, onError); -}; - -// Saves state in case of restarts, event page suspend, crashes, etc. -function saveState() { - var state = {}; - for (var volumeId in volumes) { - var entryId = chrome.fileSystem.retainEntry(volumes[volumeId].entry); - state[volumeId] = { - entryId: entryId - }; - } - chrome.storage.local.set({state: state}); -} - -// Restores metadata for the passed file system ID. -function restoreState(fileSystemId, onSuccess, onError) { - chrome.storage.local.get(['state'], function(result) { - // Check if metadata for the given file system is already in memory. - if (volumes[fileSystemId]) { - onSuccess(); - return; - } - - chrome.fileSystem.restoreEntry( - result.state[fileSystemId].entryId, - function(entry) { - readMetadataFromFile(entry, - function(metadata) { - chrome.fileSystemProvider.get(fileSystemId, function(info) { - if (chrome.runtime.lastError) { - onError(chrome.runtime.lastError.message); - return; - } - volumes[fileSystemId] = new Volume(entry, metadata, - info.openedFiles); - onSuccess(); - }); - }, onError); - }); - }); -} - -// Reads metadata from a file and returns it with the onSuccess callback. -function readMetadataFromFile(entry, onSuccess, onError) { - entry.file(function(file) { - var fileReader = new FileReader(); - fileReader.onload = function(event) { - onSuccess(JSON.parse(event.target.result)); - }; - - fileReader.onerror = function(event) { - onError('FAILED'); - }; - - fileReader.readAsText(file); - }); -} - -// Event called on opening a file with the extension or mime type -// declared in the manifest file. -chrome.app.runtime.onLaunched.addListener(function(event) { - event.items.forEach(function(item) { - readMetadataFromFile(item.entry, - function(metadata) { - // Mount the volume and save its information in local storage - // in order to be able to recover the metadata in case of - // restarts, system crashes, etc. - chrome.fileSystem.getDisplayPath(item.entry, function(displayPath) { - volumes[displayPath] = new Volume(item.entry, metadata, []); - chrome.fileSystemProvider.mount( - {fileSystemId: displayPath, displayName: item.entry.name}, - function() { - if (chrome.runtime.lastError) { - console.error('Failed to mount because of: ' + - chrome.runtime.lastError.message); - return; - }; - saveState(); - }); - }); - }, - function(error) { - console.error(error); - }); - }); -}); - -// Event called on a profile startup. -chrome.runtime.onStartup.addListener(function () { - chrome.storage.local.get(['state'], function(result) { - // Nothing to change. - if (!result.state) - return; - - chrome.storage.local.set({state: result.state}); - }); -}); - -// Save the state before suspending the event page, so we can resume it -// once new events arrive. -chrome.runtime.onSuspend.addListener(function() { - saveState(); -}); - -chrome.fileSystemProvider.onUnmountRequested.addListener( - onUnmountRequested); -chrome.fileSystemProvider.onGetMetadataRequested.addListener( - onGetMetadataRequested); -chrome.fileSystemProvider.onReadDirectoryRequested.addListener( - onReadDirectoryRequested); -chrome.fileSystemProvider.onOpenFileRequested.addListener( - onOpenFileRequested); -chrome.fileSystemProvider.onCloseFileRequested.addListener( - onCloseFileRequested); -chrome.fileSystemProvider.onReadFileRequested.addListener( - onReadFileRequested);
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/example1.fake b/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/example1.fake deleted file mode 100644 index 6d7cc11..0000000 --- a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/example1.fake +++ /dev/null
@@ -1,34 +0,0 @@ -{ - "/": { - "isDirectory": true, - "name": "", - "size": 0, - "modificationTime": "2014-06-26T08:47:11.591Z" - }, - "/file1.txt": { - "isDirectory": false, - "name": "file1.txt", - "size": 46, - "modificationTime": "2014-06-26T08:47:11.591Z", - "contents": "It works!\nEverything gets displayed correctly." - }, - "/file2": { - "isDirectory": false, - "name": "file2", - "size": 150, - "modificationTime": "2014-06-26T08:47:11.591Z" - }, - "/dir": { - "isDirectory": true, - "name": "dir", - "size": 0, - "modificationTime": "2014-06-26T08:47:11.591Z" - }, - "/dir/file3.txt": { - "isDirectory": false, - "name": "file3.txt", - "size": 21, - "modificationTime": "2014-06-26T08:47:11.591Z", - "contents": "Just another example." - } -}
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/example2.fake b/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/example2.fake deleted file mode 100644 index 385688c..0000000 --- a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/example2.fake +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "/": { - "isDirectory": true, - "name": "", - "size": 0, - "modificationTime": "2014-06-26T08:47:11.591Z" - }, - "/file.txt": { - "isDirectory": false, - "name": "file.txt", - "size": 9, - "modificationTime": "2014-06-26T08:47:11.591Z", - "contents": "It works!" - } -}
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/manifest.json b/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/manifest.json deleted file mode 100644 index 025b5d3..0000000 --- a/chrome/common/extensions/docs/examples/api/fileSystemProvider/archive/manifest.json +++ /dev/null
@@ -1,28 +0,0 @@ -{ - "name": "Fake Archive Handler App", - "version": "0.1", - "manifest_version": 2, - "description": "Demonstrate File System Provider API usage for apps.", - "permissions": [ - "fileSystemProvider", - {"fileSystem": ["retainEntries"]}, - "storage" - ], - "file_handlers": { - "fake": { - "types": ["application/fake"], - "extensions": ["fake"] - } - }, - "file_system_provider_capabilities": { - "multiple_mounts": true, - "source": "file" - }, - "app": { - "background": { - "scripts": [ - "background.js" - ] - } - } -}
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/background.js b/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/background.js deleted file mode 100644 index 8c08f42..0000000 --- a/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/background.js +++ /dev/null
@@ -1,142 +0,0 @@ -// Copyright 2014 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. - -'use strict'; - -// Fake data similar to a file system structure. -var MODIFICATION_DATE = new Date(); -var SHORT_CONTENTS = 'Just another example.'; -var LONGER_CONTENTS = 'It works!\nEverything gets displayed correctly.'; - -var METADATA = { - '/': {isDirectory: true, name: '', size: 0, - modificationTime: MODIFICATION_DATE}, - '/file1.txt': {isDirectory: false, name: 'file1.txt', - size: LONGER_CONTENTS.length, modificationTime: MODIFICATION_DATE, - contents: LONGER_CONTENTS}, - '/file2': {isDirectory: false, name: 'file2', size: 150, - modificationTime: MODIFICATION_DATE}, - '/dir': {isDirectory: true, name: 'dir', size: 0, - modificationTime: MODIFICATION_DATE}, - '/dir/file3.txt': {isDirectory: false, name: 'file3.txt', - size: SHORT_CONTENTS.length, modificationTime: MODIFICATION_DATE, - contents: SHORT_CONTENTS}}; - -// A map with currently opened files. As key it has requestId of -// openFileRequested and as a value the file path. -var openedFiles = {}; - -function onGetMetadataRequested(options, onSuccess, onError) { - if (!METADATA[options.entryPath]) - onError('NOT_FOUND'); - else - onSuccess(METADATA[options.entryPath]); -} - -function onReadDirectoryRequested(options, onSuccess, onError) { - if (!METADATA[options.directoryPath]) { - onError('NOT_FOUND'); - return; - } - if (!METADATA[options.directoryPath].isDirectory) { - onError('NOT_A_DIRECTORY'); - return; - } - - // Retrieve directory contents from METADATA. - var entries = []; - for (var entry in METADATA) { - // Do not add itself on the list. - if (entry == options.directoryPath) - continue; - // Check if the entry is a child of the requested directory. - if (entry.indexOf(options.directoryPath) != 0) - continue; - // Restrict to direct children only. - if (entry.substring(options.directoryPath.length + 1).indexOf('/') != -1) - continue; - - entries.push(METADATA[entry]); - } - onSuccess(entries, false /* Last call. */); -} - -function onOpenFileRequested(options, onSuccess, onError) { - if (options.mode != 'READ' || options.create) { - onError('INVALID_OPERATION'); - } else { - openedFiles[options.requestId] = options.filePath; - onSuccess(); - } -} - -function onCloseFileRequested(options, onSuccess, onError) { - if (!openedFiles[options.openRequestId]) { - onError('INVALID_OPERATION'); - } else { - delete openedFiles[options.openRequestId]; - onSuccess(); - } -} - -function onReadFileRequested(options, onSuccess, onError) { - if (!openedFiles[options.openRequestId]) { - onError('INVALID_OPERATION'); - return; - } - - var contents = - METADATA[openedFiles[options.openRequestId]].contents; - - var remaining = Math.max(0, contents.length - options.offset); - var length = Math.min(remaining, options.length); - - // Write the contents as ASCII text. - var buffer = new ArrayBuffer(length); - var bufferView = new Uint8Array(buffer); - for (var i = 0; i < length; i++) { - bufferView[i] = contents.charCodeAt(i + options.offset); - } - - onSuccess(buffer, false /* Last call. */); -} - -function onMountRequested(onSuccess, onError) { - chrome.fileSystemProvider.mount( - {fileSystemId: 'sample-file-system', displayName: 'Sample File System'}, - function() { - if (chrome.runtime.lastError) { - onError(chrome.runtime.lastError.message); - console.error('Failed to mount because of: ' + - chrome.runtime.lastError.message); - return; - } - onSuccess(); - }); -} - -function onUnmountRequested(options, onSuccess, onError) { - chrome.fileSystemProvider.unmount( - {fileSystemId: options.fileSystemId}, - function() { - if (chrome.runtime.lastError) { - onError(chrome.runtime.lastError.message); - console.error('Failed to unmount because of: ' + - chrome.runtime.lastError.message); - return; - } - onSuccess(); - }); -} - -chrome.fileSystemProvider.onGetMetadataRequested.addListener( - onGetMetadataRequested); -chrome.fileSystemProvider.onReadDirectoryRequested.addListener( - onReadDirectoryRequested); -chrome.fileSystemProvider.onOpenFileRequested.addListener(onOpenFileRequested); -chrome.fileSystemProvider.onCloseFileRequested.addListener( - onCloseFileRequested); -chrome.fileSystemProvider.onReadFileRequested.addListener(onReadFileRequested); -chrome.fileSystemProvider.onMountRequested.addListener(onMountRequested); -chrome.fileSystemProvider.onUnmountRequested.addListener(onUnmountRequested);
diff --git a/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/manifest.json b/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/manifest.json deleted file mode 100644 index fcb281c..0000000 --- a/chrome/common/extensions/docs/examples/api/fileSystemProvider/basic/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "name": "File System Provider API Extension Example", - "version": "0.1", - "manifest_version": 2, - "description": - "Demonstrate features of the API like mounting, listing directories, etc for extensions.", - "permissions": [ - "fileSystemProvider" - ], - "file_system_provider_capabilities": { - "source": "network" - }, - "background": { - "scripts": [ - "background.js" - ] - } -}
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/css/chrome_shared.css b/chrome/common/extensions/docs/examples/api/fontSettings/css/chrome_shared.css deleted file mode 100644 index 007d6f440..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/css/chrome_shared.css +++ /dev/null
@@ -1,100 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -/* Copy of /resources/shared/css/chrome_shared.css for sample extension. */ - -/* Prevent CSS from overriding the hidden property. */ -[hidden] { - display: none !important; -} - -html.loading * { - transition-delay: 0ms !important; - transition-duration: 0ms !important; -} - -body { - cursor: default; - margin: 0; -} - -p { - line-height: 1.8em; -} - -h1, -h2, -h3 { - -webkit-user-select: none; - font-weight: normal; - /* Makes the vertical size of the text the same for all fonts. */ - line-height: 1; -} - -h1 { - font-size: 1.5em; -} - -h2 { - font-size: 1.3em; - margin-bottom: 0.4em; -} - -h3 { - color: black; - font-size: 1.2em; - margin-bottom: 0.8em; -} - -a { - color: rgb(17, 85, 204); - text-decoration: underline; -} - -a:active { - color: rgb(5, 37, 119); -} - -/* Elements that need to be LTR even in an RTL context, but should align - * right. (Namely, URLs, search engine names, etc.) - */ -html[dir='rtl'] .weakrtl { - direction: ltr; - text-align: right; -} - -/* Input fields in search engine table need to be weak-rtl. Since those input - * fields are generated for all cr.ListItem elements (and we only want weakrtl - * on some), the class needs to be on the enclosing div. - */ -html[dir='rtl'] div.weakrtl input { - direction: ltr; - text-align: right; -} - -html[dir='rtl'] .favicon-cell.weakrtl { - padding-inline-end: 22px; - padding-inline-start: 0; -} - -/* weakrtl for selection drop downs needs to account for the fact that - * Webkit does not honor the text-align attribute for the select element. - * (See Webkit bug #40216) - */ -html[dir='rtl'] select.weakrtl { - direction: rtl; -} - -html[dir='rtl'] select.weakrtl option { - direction: ltr; -} - -/* WebKit does not honor alignment for text specified via placeholder attribute. - * This CSS is a workaround. Please remove once WebKit bug is fixed. - * https://bugs.webkit.org/show_bug.cgi?id=63367 - */ -html[dir='rtl'] input.weakrtl::-webkit-input-placeholder, -html[dir='rtl'] .weakrtl input::-webkit-input-placeholder { - direction: rtl; -}
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/css/overlay.css b/chrome/common/extensions/docs/examples/api/fontSettings/css/overlay.css deleted file mode 100644 index 432ca62..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/css/overlay.css +++ /dev/null
@@ -1,162 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -/* The shield that overlays the background. */ -.overlay { - -webkit-box-align: center; - -webkit-box-orient: vertical; - -webkit-box-pack: center; - background-color: rgba(255, 255, 255, 0.75); - bottom: 0; - display: -webkit-box; - left: 0; - overflow: auto; - padding: 20px; - position: fixed; - right: 0; - top: 0; - transition: 200ms opacity; -} - -/* Used to slide in the overlay. */ -.overlay.transparent .page { - /* TODO(flackr): Add perspective(500px) rotateX(5deg) when accelerated - * compositing is enabled on chrome:// pages. See http://crbug.com/116800. */ - transform: scale(0.99) translateY(-20px); -} - -/* The foreground dialog. */ -.overlay .page { - -webkit-border-radius: 3px; - -webkit-box-orient: vertical; - background: white; - box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15); - color: #333; - display: -webkit-box; - min-width: 400px; - padding: 0; - position: relative; - transition: 200ms transform; -} - -/* If the options page is loading don't do the transition. */ -.loading .overlay, -.loading .overlay .page { - transition-duration: 0ms !important; -} - -/* keyframes used to pulse the overlay */ -@keyframes pulse { - 0% { - transform: scale(1); - } - 40% { - transform: scale(1.02); - } - 60% { - transform: scale(1.02); - } - 100% { - transform: scale(1); - } -} - -.overlay .page.pulse { - animation-duration: 180ms; - animation-iteration-count: 1; - animation-name: pulse; - animation-timing-function: ease-in-out; -} - -.overlay .page > .close-button { - background-image: url('../images/x.png'); - background-position: center; - background-repeat: no-repeat; - height: 14px; - position: absolute; - right: 7px; - top: 7px; - width: 14px; -} - -html[dir='rtl'] .overlay .page > .close-button { - left: 10px; - right: auto; -} - -.overlay .page > .close-button:hover { - background-image: url('../images/x-hover.png'); -} - -.overlay .page > .close-button:active { - background-image: url('../images/x-pressed.png'); -} - -.overlay .page h1 { - -webkit-user-select: none; - color: #333; - /* 120% of the body's font-size of 84% is 16px. This will keep the relative - * size between the body and these titles consistent. */ - font-size: 120%; - /* TODO(flackr): Pages like sync-setup and delete user collapse the margin - * above the top of the page. Use padding instead to make sure that the - * headers of these pages have the correct spacing, but this should not be - * necessary. See http://crbug.com/119029. */ - margin: 0; - padding: 14px 17px 14px; - text-shadow: white 0 1px 2px; -} - -.overlay .page .content-area { - -webkit-box-flex: 1; - overflow: auto; - padding: 6px 17px 6px; - position: relative; -} - -.overlay .page .action-area { - -webkit-box-align: center; - -webkit-box-orient: horizontal; - -webkit-box-pack: end; - display: -webkit-box; - padding: 14px 17px; -} - -html[dir='rtl'] .overlay .page .action-area { - left: 0; -} - -.overlay .page .action-area-right { - display: -webkit-box; -} - -.overlay .page .button-strip { - -webkit-box-orient: horizontal; - display: -webkit-box; -} - -.overlay .page .button-strip > button { - display: block; - margin-inline-start: 10px; -} - -/* On OSX 10.7, hidden scrollbars may prevent the user from realizing that the - * overlay contains scrollable content. To resolve this, style the scrollbars on - * OSX so they are always visible. See http://crbug.com/123010. */ -<if expr="is_macosx"> -.overlay .page .content-area::-webkit-scrollbar { - -webkit-appearance: none; - width: 11px; -} - -.overlay .page .content-area::-webkit-scrollbar-thumb { - background-color: rgba(0, 0, 0, 0.2); - border: 2px solid white; - border-radius: 8px; -} - -.overlay .page .content-area::-webkit-scrollbar-thumb:hover { - background-color: rgba(0, 0, 0, 0.5); -} -</if>
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/css/uber_shared.css b/chrome/common/extensions/docs/examples/api/fontSettings/css/uber_shared.css deleted file mode 100644 index 482451b5..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/css/uber_shared.css +++ /dev/null
@@ -1,118 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -body.uber-frame { - color: rgb(48, 57, 66); - margin-inline-start: 155px; -} - -html[dir='rtl'] body.uber-frame { - /* Enable vertical scrollbar at all times in RTL to avoid visual glitches when - * showing sub-pages that vertically overflow. */ - overflow-y: scroll; -} - -/* TODO(dbeam): Remove .page class from overlays in settings so the junk below - * isn't necessary. */ -body.uber-frame #extension-settings.page, -body.uber-frame #mainview-content .page, -body.uber-frame .subpage-sheet-container .page, -body.uber-frame > .page { - margin-inline-end: 24px; - min-width: 576px; - padding-bottom: 20px; - padding-top: 55px; -} - -body.uber-frame header { - background-image: -webkit-linear-gradient(white, - white 40%, - rgba(255, 255, 255, 0.92)); - left: 155px; - /* <section>s in options currently amount to 638px total, broken up into - * 600px max-width + 18px padding-inline-start + 20px margin-inline-end - * so we mirror this value here so the headers match width and horizontal - * alignment when scrolling sideways. */ - max-width: 738px; - min-width: 600px; - position: fixed; - right: 0; - top: 0; - /* list.css sets a z-index of up to 2, this is set to 3 to ensure that the - * header is in front of the selected list item. */ - z-index: 3; -} - -html[dir='rtl'] body.uber-frame header { - left: 0; - right: 155px; -} - -body.uber-frame header > .search-field-container, -body.uber-frame header > .header-extras, -body.uber-frame header > button { - position: absolute; - right: 20px; - top: 21px; -} - -html[dir='rtl'] body.uber-frame header > .search-field-container, -html[dir='rtl'] body.uber-frame header > .header-extras, -html[dir='rtl'] body.uber-frame header > button { - left: 20px; - right: auto; -} - -body.uber-frame header input[type='search'], -body.uber-frame header input[type='text'], -body.uber-frame header button { - margin: 0; -} - -body.uber-frame header > h1 { - margin: 0; - padding: 21px 0 13px; -} - -/* Create a border under the h1 (but before anything that gets appended - * to the end of the header). */ -body.uber-frame header > h1::after { - background-color: #eee; - content: ' '; - display: block; - height: 1px; - margin-inline-end: 20px; - position: relative; - top: 13px; -} - -body.uber-frame footer { - border-top: 1px solid #eee; - margin-top: 16px; - /* min-width and max-width should match the header */ - max-width: 638px; - min-width: 600px; - padding: 8px 0; -} - -/* Sections are used in options pages, help page and history page. This defines - * the section metrics to match the header metrics above. */ -body.uber-frame section { - margin-bottom: 24px; - margin-top: 8px; - max-width: 600px; - padding-inline-start: 18px; -} - -body.uber-frame section:last-of-type { - margin-bottom: 0; -} - -body.uber-frame section > h3 { - margin-inline-start: -18px; -} - -body.uber-frame section > div:only-of-type { - -webkit-box-flex: 1; -}
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/css/widgets.css b/chrome/common/extensions/docs/examples/api/fontSettings/css/widgets.css deleted file mode 100644 index dee76357..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/css/widgets.css +++ /dev/null
@@ -1,306 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* This file defines styles for form controls. The order of rule blocks is - * important as there are some rules with equal specificity that rely on order - * as a tiebreaker. These are marked with OVERRIDE. - */ - -/* Default state **************************************************************/ - -:-webkit-any(button, - input[type='button'], - input[type='submit']):not(.custom-appearance):not(.link-button), -select, -input[type='checkbox'], -input[type='radio'] { - -webkit-appearance: none; - -webkit-user-select: none; - background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); - border: 1px solid rgba(0, 0, 0, 0.25); - border-radius: 2px; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), - inset 0 1px 2px rgba(255, 255, 255, 0.75); - color: #444; - font: inherit; - margin: 0 1px 0 0; - text-shadow: 0 1px 0 rgb(240, 240, 240); -} - -:-webkit-any(button, - input[type='button'], - input[type='submit']):not(.custom-appearance):not(.link-button), -select { - min-height: 2em; - min-width: 4em; -<if expr="is_win"> - /* The following platform-specific rule is necessary to get adjacent - * buttons, text inputs, and so forth to align on their borders while also - * aligning on the text's baselines. */ - padding-bottom: 1px; -</if> -} - -:-webkit-any(button, - input[type='button'], - input[type='submit']):not(.custom-appearance):not(.link-button) { - padding-inline-end: 10px; - padding-inline-start: 10px; -} - -select { - -webkit-appearance: none; - /* OVERRIDE */ - background-image: url('../images/select.png'), - -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); - background-position: right center; - background-repeat: no-repeat; - padding-inline-end: 20px; - padding-inline-start: 6px; -} - -html[dir='rtl'] select { - background-position: center left; -} - -input[type='checkbox'] { - bottom: 2px; - height: 13px; - position: relative; - vertical-align: middle; - width: 13px; -} - -input[type='radio'] { - /* OVERRIDE */ - border-radius: 100%; - bottom: 3px; - height: 15px; - position: relative; - vertical-align: middle; - width: 15px; -} - -/* TODO(estade): add more types here? */ -input[type='password'], -input[type='search'], -input[type='text'], -input[type='url'], -input[type='number'], -input:not([type]), -textarea { - border: 1px solid #bfbfbf; - border-radius: 2px; - box-sizing: border-box; - color: #444; - font: inherit; - margin: 0; - /* Use min-height to accommodate addditional padding for touch as needed. */ - min-height: 2em; - padding: 3px; -<if expr="is_win or is_macosx"> - /* For better alignment between adjacent buttons and inputs. */ - padding-bottom: 4px; -</if> -} - -input[type='search'] { - -webkit-appearance: textfield; - /* NOTE: Keep a relatively high min-width for this so we don't obscure the end - * of the default text in relatively spacious languages (i.e. German). */ - min-width: 160px; -} - -/* Checked ********************************************************************/ - -input[type='checkbox']:checked::before { - -webkit-user-select: none; - background-image: url('../images/check.png'); - background-size: 100% 100%; - content: ''; - display: block; - height: 100%; - width: 100%; -} - -html[dir='rtl'] input[type='checkbox']:checked::before { - transform: scaleX(-1); -} - -input[type='radio']:checked::before { - background-color: #666; - border-radius: 100%; - bottom: 3px; - content: ''; - display: block; - left: 3px; - position: absolute; - right: 3px; - top: 3px; -} - -/* Hover **********************************************************************/ - -:enabled:hover:-webkit-any( - select, - input[type='checkbox'], - input[type='radio'], - :-webkit-any( - button, - input[type='button'], - input[type='submit']):not(.custom-appearance):not(.link-button)) { - background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); - border-color: rgba(0, 0, 0, 0.3); - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), - inset 0 1px 2px rgba(255, 255, 255, 0.95); - color: black; -} - -:enabled:hover:-webkit-any(select) { - /* OVERRIDE */ - background-image: url('../images/select.png'), - -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); -} - -/* Active *********************************************************************/ - -:enabled:active:-webkit-any( - select, - input[type='checkbox'], - input[type='radio'], - :-webkit-any( - button, - input[type='button'], - input[type='submit']):not(.custom-appearance):not(.link-button)) { - background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); - box-shadow: none; - text-shadow: none; -} - -:enabled:active:-webkit-any(select) { - /* OVERRIDE */ - background-image: url('../images/select.png'), - -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); -} - -/* Disabled *******************************************************************/ - -:disabled:-webkit-any( - button, - input[type='button'], - input[type='submit']):not(.custom-appearance):not(.link-button), -select:disabled { - background-image: -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6); - border-color: rgba(80, 80, 80, 0.2); - box-shadow: 0 1px 0 rgba(80, 80, 80, 0.08), - inset 0 1px 2px rgba(255, 255, 255, 0.75); - color: #aaa; -} - -select:disabled { - /* OVERRIDE */ - background-image: url('../images/disabled_select.png'), - -webkit-linear-gradient(#f1f1f1, #f1f1f1 38%, #e6e6e6); -} - -input:disabled:-webkit-any([type='checkbox'], - [type='radio']) { - opacity: .75; -} - -input:disabled:-webkit-any([type='password'], - [type='search'], - [type='text'], - [type='url'], - :not([type])) { - color: #999; -} - -/* Focus **********************************************************************/ - -:enabled:focus:-webkit-any( - select, - input[type='checkbox'], - input[type='password'], - input[type='radio'], - input[type='search'], - input[type='text'], - input[type='url'], - input:not([type]), - :-webkit-any( - button, - input[type='button'], - input[type='submit']):not(.custom-appearance):not(.link-button)) { - /* OVERRIDE */ - transition: border-color 200ms; - /* We use border color because it follows the border radius (unlike outline). - * This is particularly noticeable on mac. */ - border-color: rgb(77, 144, 254); - outline: none; -} - -/* Link buttons ***************************************************************/ - -.link-button { - -webkit-box-shadow: none; - background: transparent none; - border: none; - color: rgb(17, 85, 204); - cursor: pointer; - /* Input elements have -webkit-small-control which can override the body font. - * Resolve this by using 'inherit'. */ - font: inherit; - margin: 0; - padding: 0 4px; -} - -.link-button:hover { - text-decoration: underline; -} - -.link-button:active { - color: rgb(5, 37, 119); - text-decoration: underline; -} - -.link-button[disabled] { - color: #999; - cursor: default; - text-decoration: none; -} - -/* Checkbox/radio helpers ****************************************************** - * - * .checkbox and .radio classes wrap labels. Checkboxes and radios should use - * these classes with the markup structure: - * - * <div class="checkbox"> - * <label> - * <input type="checkbox"></input> - * <span> - * </label> - * </div> - */ - -:-webkit-any(.checkbox, .radio) label { - /* Don't expand horizontally: <http://crbug.com/112091>. */ - display: -webkit-inline-box; - padding-bottom: 7px; - padding-top: 7px; -} - -:-webkit-any(.checkbox, .radio) label input ~ span { - /* Make sure long spans wrap at the same horizontal position they start. */ - display: block; - margin-inline-start: 0.6em; -} - -:-webkit-any(.checkbox, .radio) label:hover { - color: black; -} - -label > input:disabled:-webkit-any([type='checkbox'], [type='radio']) ~ span { - color: #999; -}
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/fonts128.png b/chrome/common/extensions/docs/examples/api/fontSettings/fonts128.png deleted file mode 100644 index 0127cde..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/fonts128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/fonts16.png b/chrome/common/extensions/docs/examples/api/fontSettings/fonts16.png deleted file mode 100644 index 47e5aa6c..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/fonts16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/disabled_select.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/disabled_select.png deleted file mode 100644 index 9bce7a3..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/disabled_select.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/select.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/select.png deleted file mode 100644 index 3cb71fb..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/select.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_center.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_center.png deleted file mode 100644 index e916da0c..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_center.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_center.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_center.png deleted file mode 100644 index 9003650e..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_center.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_left.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_left.png deleted file mode 100644 index 76915f1..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_left.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_right.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_right.png deleted file mode 100644 index fda2c53..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_disabled_right.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_fill_center.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_fill_center.png deleted file mode 100644 index e427ede5..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_fill_center.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_fill_left.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_fill_left.png deleted file mode 100644 index 345a7fe..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slide_bar_fill_left.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_bar_right.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_bar_right.png deleted file mode 100644 index 01566d18..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_bar_right.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb.png deleted file mode 100644 index f6fb421..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_disabled.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_disabled.png deleted file mode 100644 index 5eec71f39..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_disabled.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_down.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_down.png deleted file mode 100644 index b20d82b5..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_down.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_hover.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_hover.png deleted file mode 100644 index 13612251..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/slider/slider_thumb_hover.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/x-hover.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/x-hover.png deleted file mode 100644 index 089df18..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/x-hover.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/x-pressed.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/x-pressed.png deleted file mode 100644 index 48d12c9..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/x-pressed.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/images/x.png b/chrome/common/extensions/docs/examples/api/fontSettings/images/x.png deleted file mode 100644 index 9e2956d9..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/images/x.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/js/cr.js b/chrome/common/extensions/docs/examples/api/fontSettings/js/cr.js deleted file mode 100644 index 69141a6..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/js/cr.js +++ /dev/null
@@ -1,348 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * The global object. - * @type {!Object} - * @const - */ -var global = this; - -/** Platform, package, object property, and Event support. **/ -this.cr = (function() { - 'use strict'; - - /** - * Builds an object structure for the provided namespace path, - * ensuring that names that already exist are not overwritten. For - * example: - * "a.b.c" -> a = {};a.b={};a.b.c={}; - * @param {string} name Name of the object that this file defines. - * @param {*=} opt_object The object to expose at the end of the path. - * @param {Object=} opt_objectToExportTo The object to add the path to; - * default is {@code global}. - * @private - */ - function exportPath(name, opt_object, opt_objectToExportTo) { - var parts = name.split('.'); - var cur = opt_objectToExportTo || global; - - for (var part; parts.length && (part = parts.shift());) { - if (!parts.length && opt_object !== undefined) { - // last part and we have an object; use it - cur[part] = opt_object; - } else if (part in cur) { - cur = cur[part]; - } else { - cur = cur[part] = {}; - } - } - return cur; - }; - - /** - * Fires a property change event on the target. - * @param {EventTarget} target The target to dispatch the event on. - * @param {string} propertyName The name of the property that changed. - * @param {*} newValue The new value for the property. - * @param {*} oldValue The old value for the property. - */ - function dispatchPropertyChange(target, propertyName, newValue, oldValue) { - var e = new Event(propertyName + 'Change'); - e.propertyName = propertyName; - e.newValue = newValue; - e.oldValue = oldValue; - target.dispatchEvent(e); - } - - /** - * Converts a camelCase javascript property name to a hyphenated-lower-case - * attribute name. - * @param {string} jsName The javascript camelCase property name. - * @return {string} The equivalent hyphenated-lower-case attribute name. - */ - function getAttributeName(jsName) { - return jsName.replace(/([A-Z])/g, '-$1').toLowerCase(); - } - - /** - * The kind of property to define in {@code defineProperty}. - * @enum {number} - * @const - */ - var PropertyKind = { - /** - * Plain old JS property where the backing data is stored as a "private" - * field on the object. - */ - JS: 'js', - - /** - * The property backing data is stored as an attribute on an element. - */ - ATTR: 'attr', - - /** - * The property backing data is stored as an attribute on an element. If the - * element has the attribute then the value is true. - */ - BOOL_ATTR: 'boolAttr' - }; - - /** - * Helper function for defineProperty that returns the getter to use for the - * property. - * @param {string} name The name of the property. - * @param {cr.PropertyKind} kind The kind of the property. - * @return {function():*} The getter for the property. - */ - function getGetter(name, kind) { - switch (kind) { - case PropertyKind.JS: - var privateName = name + '_'; - return function() { - return this[privateName]; - }; - case PropertyKind.ATTR: - var attributeName = getAttributeName(name); - return function() { - return this.getAttribute(attributeName); - }; - case PropertyKind.BOOL_ATTR: - var attributeName = getAttributeName(name); - return function() { - return this.hasAttribute(attributeName); - }; - } - } - - /** - * Helper function for defineProperty that returns the setter of the right - * kind. - * @param {string} name The name of the property we are defining the setter - * for. - * @param {cr.PropertyKind} kind The kind of property we are getting the - * setter for. - * @param {function(*):void} opt_setHook A function to run after the property - * is set, but before the propertyChange event is fired. - * @return {function(*):void} The function to use as a setter. - */ - function getSetter(name, kind, opt_setHook) { - switch (kind) { - case PropertyKind.JS: - var privateName = name + '_'; - return function(value) { - var oldValue = this[name]; - if (value !== oldValue) { - this[privateName] = value; - if (opt_setHook) - opt_setHook.call(this, value, oldValue); - dispatchPropertyChange(this, name, value, oldValue); - } - }; - - case PropertyKind.ATTR: - var attributeName = getAttributeName(name); - return function(value) { - var oldValue = this[name]; - if (value !== oldValue) { - if (value == undefined) - this.removeAttribute(attributeName); - else - this.setAttribute(attributeName, value); - if (opt_setHook) - opt_setHook.call(this, value, oldValue); - dispatchPropertyChange(this, name, value, oldValue); - } - }; - - case PropertyKind.BOOL_ATTR: - var attributeName = getAttributeName(name); - return function(value) { - var oldValue = this[name]; - if (value !== oldValue) { - if (value) - this.setAttribute(attributeName, name); - else - this.removeAttribute(attributeName); - if (opt_setHook) - opt_setHook.call(this, value, oldValue); - dispatchPropertyChange(this, name, value, oldValue); - } - }; - } - } - - /** - * Defines a property on an object. When the setter changes the value a - * property change event with the type {@code name + 'Change'} is fired. - * @param {!Object} obj The object to define the property for. - * @param {string} name The name of the property. - * @param {cr.PropertyKind=} opt_kind What kind of underlying storage to use. - * @param {function(*):void} opt_setHook A function to run after the - * property is set, but before the propertyChange event is fired. - */ - function defineProperty(obj, name, opt_kind, opt_setHook) { - if (typeof obj == 'function') - obj = obj.prototype; - - var kind = opt_kind || PropertyKind.JS; - - if (!obj.__lookupGetter__(name)) - obj.__defineGetter__(name, getGetter(name, kind)); - - if (!obj.__lookupSetter__(name)) - obj.__defineSetter__(name, getSetter(name, kind, opt_setHook)); - } - - /** - * Counter for use with createUid - */ - var uidCounter = 1; - - /** - * @return {number} A new unique ID. - */ - function createUid() { - return uidCounter++; - } - - /** - * Returns a unique ID for the item. This mutates the item so it needs to be - * an object - * @param {!Object} item The item to get the unique ID for. - * @return {number} The unique ID for the item. - */ - function getUid(item) { - if (item.hasOwnProperty('uid')) - return item.uid; - return item.uid = createUid(); - } - - /** - * Dispatches a simple event on an event target. - * @param {!EventTarget} target The event target to dispatch the event on. - * @param {string} type The type of the event. - * @param {boolean=} opt_bubbles Whether the event bubbles or not. - * @param {boolean=} opt_cancelable Whether the default action of the event - * can be prevented. Default is true. - * @return {boolean} If any of the listeners called {@code preventDefault} - * during the dispatch this will return false. - */ - function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) { - var e = new Event(type, { - bubbles: opt_bubbles, - cancelable: opt_cancelable === undefined || opt_cancelable - }); - return target.dispatchEvent(e); - } - - /** - * Calls |fun| and adds all the fields of the returned object to the object - * named by |name|. For example, cr.define('cr.ui', function() { - * function List() { - * ... - * } - * function ListItem() { - * ... - * } - * return { - * List: List, - * ListItem: ListItem, - * }; - * }); - * defines the functions cr.ui.List and cr.ui.ListItem. - * @param {string} name The name of the object that we are adding fields to. - * @param {!Function} fun The function that will return an object containing - * the names and values of the new fields. - */ - function define(name, fun) { - var obj = exportPath(name); - var exports = fun(); - for (var propertyName in exports) { - // Maybe we should check the prototype chain here? The current usage - // pattern is always using an object literal so we only care about own - // properties. - var propertyDescriptor = Object.getOwnPropertyDescriptor(exports, - propertyName); - if (propertyDescriptor) - Object.defineProperty(obj, propertyName, propertyDescriptor); - } - } - - /** - * Adds a {@code getInstance} static method that always return the same - * instance object. - * @param {!Function} ctor The constructor for the class to add the static - * method to. - */ - function addSingletonGetter(ctor) { - ctor.getInstance = function() { - return ctor.instance_ || (ctor.instance_ = new ctor()); - }; - } - - /** - * Initialization which must be deferred until run-time. - */ - function initialize() { - // If 'document' isn't defined, then we must be being pre-compiled, - // so set a trap so that we're initialized on first access at run-time. - if (!global.document) { - var originalCr = cr; - - Object.defineProperty(global, 'cr', { - get: function() { - Object.defineProperty(global, 'cr', {value: originalCr}); - originalCr.initialize(); - return originalCr; - }, - configurable: true - }); - - return; - } - - cr.doc = document; - - /** - * Whether we are using a Mac or not. - */ - cr.isMac = /Mac/.test(navigator.platform); - - /** - * Whether this is on the Windows platform or not. - */ - cr.isWindows = /Win/.test(navigator.platform); - - /** - * Whether this is on chromeOS or not. - */ - cr.isChromeOS = /CrOS/.test(navigator.userAgent); - - /** - * Whether this is on vanilla Linux (not chromeOS). - */ - cr.isLinux = /Linux/.test(navigator.userAgent); - } - - return { - addSingletonGetter: addSingletonGetter, - createUid: createUid, - define: define, - defineProperty: defineProperty, - dispatchPropertyChange: dispatchPropertyChange, - dispatchSimpleEvent: dispatchSimpleEvent, - getUid: getUid, - initialize: initialize, - PropertyKind: PropertyKind - }; -})(); - - -/** - * TODO(kgr): Move this to another file which is to be loaded last. - * This will be done as part of future work to make this code pre-compilable. - */ -cr.initialize();
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/js/cr/ui.js b/chrome/common/extensions/docs/examples/api/fontSettings/js/cr/ui.js deleted file mode 100644 index d48d3a8..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/js/cr/ui.js +++ /dev/null
@@ -1,177 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -cr.define('cr.ui', function() { - - /** - * Decorates elements as an instance of a class. - * @param {string|!Element} source The way to find the element(s) to decorate. - * If this is a string then {@code querySeletorAll} is used to find the - * elements to decorate. - * @param {!Function} constr The constructor to decorate with. The constr - * needs to have a {@code decorate} function. - */ - function decorate(source, constr) { - var elements; - if (typeof source == 'string') - elements = cr.doc.querySelectorAll(source); - else - elements = [source]; - - for (var i = 0, el; el = elements[i]; i++) { - if (!(el instanceof constr)) - constr.decorate(el); - } - } - - /** - * Helper function for creating new element for define. - */ - function createElementHelper(tagName, opt_bag) { - // Allow passing in ownerDocument to create in a different document. - var doc; - if (opt_bag && opt_bag.ownerDocument) - doc = opt_bag.ownerDocument; - else - doc = cr.doc; - return doc.createElement(tagName); - } - - /** - * Creates the constructor for a UI element class. - * - * Usage: - * <pre> - * var List = cr.ui.define('list'); - * List.prototype = { - * __proto__: HTMLUListElement.prototype, - * decorate: function() { - * ... - * }, - * ... - * }; - * </pre> - * - * @param {string|Function} tagNameOrFunction The tagName or - * function to use for newly created elements. If this is a function it - * needs to return a new element when called. - * @return {function(Object=):Element} The constructor function which takes - * an optional property bag. The function also has a static - * {@code decorate} method added to it. - */ - function define(tagNameOrFunction) { - var createFunction, tagName; - if (typeof tagNameOrFunction == 'function') { - createFunction = tagNameOrFunction; - tagName = ''; - } else { - createFunction = createElementHelper; - tagName = tagNameOrFunction; - } - - /** - * Creates a new UI element constructor. - * @param {Object=} opt_propertyBag Optional bag of properties to set on the - * object after created. The property {@code ownerDocument} is special - * cased and it allows you to create the element in a different - * document than the default. - * @constructor - */ - function f(opt_propertyBag) { - var el = createFunction(tagName, opt_propertyBag); - f.decorate(el); - for (var propertyName in opt_propertyBag) { - el[propertyName] = opt_propertyBag[propertyName]; - } - return el; - } - - /** - * Decorates an element as a UI element class. - * @param {!Element} el The element to decorate. - */ - f.decorate = function(el) { - el.__proto__ = f.prototype; - el.decorate(); - }; - - return f; - } - - /** - * Input elements do not grow and shrink with their content. This is a simple - * (and not very efficient) way of handling shrinking to content with support - * for min width and limited by the width of the parent element. - * @param {HTMLElement} el The element to limit the width for. - * @param {number} parentEl The parent element that should limit the size. - * @param {number} min The minimum width. - * @param {number} opt_scale Optional scale factor to apply to the width. - */ - function limitInputWidth(el, parentEl, min, opt_scale) { - // Needs a size larger than borders - el.style.width = '10px'; - var doc = el.ownerDocument; - var win = doc.defaultView; - var computedStyle = win.getComputedStyle(el); - var parentComputedStyle = win.getComputedStyle(parentEl); - var rtl = computedStyle.direction == 'rtl'; - - // To get the max width we get the width of the treeItem minus the position - // of the input. - var inputRect = el.getBoundingClientRect(); // box-sizing - var parentRect = parentEl.getBoundingClientRect(); - var startPos = rtl ? parentRect.right - inputRect.right : - inputRect.left - parentRect.left; - - // Add up border and padding of the input. - var inner = parseInt(computedStyle.borderLeftWidth, 10) + - parseInt(computedStyle.paddingLeft, 10) + - parseInt(computedStyle.paddingRight, 10) + - parseInt(computedStyle.borderRightWidth, 10); - - // We also need to subtract the padding of parent to prevent it to overflow. - var parentPadding = rtl ? parseInt(parentComputedStyle.paddingLeft, 10) : - parseInt(parentComputedStyle.paddingRight, 10); - - var max = parentEl.clientWidth - startPos - inner - parentPadding; - if (opt_scale) - max *= opt_scale; - - function limit() { - if (el.scrollWidth > max) { - el.style.width = max + 'px'; - } else { - el.style.width = 0; - var sw = el.scrollWidth; - if (sw < min) { - el.style.width = min + 'px'; - } else { - el.style.width = sw + 'px'; - } - } - } - - el.addEventListener('input', limit); - limit(); - } - - /** - * Takes a number and spits out a value CSS will be happy with. To avoid - * subpixel layout issues, the value is rounded to the nearest integral value. - * @param {number} pixels The number of pixels. - * @return {string} e.g. '16px'. - */ - function toCssPx(pixels) { - if (!window.isFinite(pixels)) - console.error('Pixel value is not a number: ' + pixels); - return Math.round(pixels) + 'px'; - } - - return { - decorate: decorate, - define: define, - limitInputWidth: limitInputWidth, - toCssPx: toCssPx, - }; -});
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/js/cr/ui/overlay.js b/chrome/common/extensions/docs/examples/api/fontSettings/js/cr/ui/overlay.js deleted file mode 100644 index c5fde49..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/js/cr/ui/overlay.js +++ /dev/null
@@ -1,101 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Provides dialog-like behaviors for the tracing UI. - */ -cr.define('cr.ui.overlay', function() { - - /** - * Gets the top, visible overlay. It makes the assumption that if multiple - * overlays are visible, the last in the byte order is topmost. - * TODO(estade): rely on aria-visibility instead? - * @return {HTMLElement} The overlay. - */ - function getTopOverlay() { - var overlays = document.querySelectorAll('.overlay:not([hidden])'); - return overlays[overlays.length - 1]; - } - - /** - * Makes initializations which must hook at the document level. - */ - function globalInitialization() { - // Close the overlay on escape. - document.addEventListener('keydown', function(e) { - if (e.keyCode == 27) { // Escape - var overlay = getTopOverlay(); - if (!overlay) - return; - - cr.dispatchSimpleEvent(overlay, 'cancelOverlay'); - } - }); - - window.addEventListener('resize', setMaxHeightAllPages); - - setMaxHeightAllPages(); - } - - /** - * Sets the max-height of all pages in all overlays, based on the window - * height. - */ - function setMaxHeightAllPages() { - var pages = document.querySelectorAll('.overlay .page'); - - var maxHeight = Math.min(0.9 * window.innerHeight, 640) + 'px'; - for (var i = 0; i < pages.length; i++) - pages[i].style.maxHeight = maxHeight; - } - - /** - * Adds behavioral hooks for the given overlay. - * @param {HTMLElement} overlay The .overlay. - */ - function setupOverlay(overlay) { - // Close the overlay on clicking any of the pages' close buttons. - var closeButtons = overlay.querySelectorAll('.page > .close-button'); - for (var i = 0; i < closeButtons.length; i++) { - closeButtons[i].addEventListener('click', function(e) { - cr.dispatchSimpleEvent(overlay, 'cancelOverlay'); - }); - } - - // Remove the 'pulse' animation any time the overlay is hidden or shown. - overlay.__defineSetter__('hidden', function(value) { - this.classList.remove('pulse'); - if (value) - this.setAttribute('hidden', true); - else - this.removeAttribute('hidden'); - }); - overlay.__defineGetter__('hidden', function() { - return this.hasAttribute('hidden'); - }); - - // Shake when the user clicks away. - overlay.addEventListener('click', function(e) { - // Only pulse if the overlay was the target of the click. - if (this != e.target) - return; - - // This may be null while the overlay is closing. - var overlayPage = this.querySelector('.page:not([hidden])'); - if (overlayPage) - overlayPage.classList.add('pulse'); - }); - overlay.addEventListener('animationend', function(e) { - e.target.classList.remove('pulse'); - }); - } - - return { - globalInitialization: globalInitialization, - setupOverlay: setupOverlay, - }; -}); - -document.addEventListener('DOMContentLoaded', - cr.ui.overlay.globalInitialization);
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/manifest.json b/chrome/common/extensions/docs/examples/api/fontSettings/manifest.json deleted file mode 100644 index 2829fecb..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "Advanced Font Settings", - "version": "0.67", - "manifest_version": 2, - "description": "Customize per-script font settings.", - "options_page": "options.html", - "icons": { - "16": "fonts16.png", - "128": "fonts128.png" - }, - "permissions": ["fontSettings"] -}
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/options.html b/chrome/common/extensions/docs/examples/api/fontSettings/options.html deleted file mode 100644 index 3e40b67..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/options.html +++ /dev/null
@@ -1,302 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"> -<title>Advanced Font Settings</title> -<script src="js/cr.js"></script> -<script src="js/cr/ui.js"></script> -<script src="js/cr/ui/overlay.js"></script> -<script src="slider.js"></script> -<script src="pending_changes.js"></script> -<script src="options.js"></script> -<link rel="stylesheet" href="css/chrome_shared.css"> -<link rel="stylesheet" href="css/overlay.css"> -<link rel="stylesheet" href="css/widgets.css"> -<link rel="stylesheet" href="css/uber_shared.css"> -<link rel="stylesheet" href="slider.css"> -<style> -body.uber-frame { - margin-inline-start: 18px; - margin-inline-end: 30px; -} - -body.uber-frame section { - max-width: 650px; -} - -body.uber-frame section:last-of-type { - margin-top: 28px; -} - -body.uber-frame header { - left: 0; - padding-inline-start: 18px; - right: 0; -} - -body.uber-frame header > h1 { - padding-bottom: 16px; -} - -h1 { - font-size: 16px; -} - -.script-header { - margin-top: 12px; -} - -h3 { - margin-bottom: 11px; - font-size: 14px; -} - -section { - font-size: 12px; -} - -.bordered { - border: 1px solid #D9D9D9; - border-radius: 2px; -} - -.smaller { - font-size: smaller; -} - -.font-settings-div { - margin-inline-end: 5px; - width: 180px; -} - -.font-settings-div:first-of-type { - width: 138px; -} - -.font-settings-div > :first-child { - margin-bottom: 10px; -} - -.font-settings-div > * { - margin-bottom: 14px; -} - -.font-settings-row { - display: -webkit-flex; - width: 800px; -} - -.sample-text-div { - display: -webkit-flex; - white-space: nowrap; - width: 100%; - overflow: hidden; -} - -.sample-text-span { - margin-top: auto; - margin-bottom: auto; - margin-left: 20px; -} - -#overlay-container { - z-index: 100; -} - -#standardFontSample { - font-family: standard; -} - -#serifFontSample { - font-family: serif; -} - -#sansSerifFontSample { - font-family: sans-serif; -} - -#fixedFontSample { - font-family: monospace; -} - -#minFontSample { - font-family: standard; -} - -select { - width: 100%; -} - -#footer > button { - padding-inline-start: 9px; - padding-inline-end: 9px; -} - -#footer > #apply-settings { - padding-inline-start: 17px; - padding-inline-end: 17px; -} - -#apply-settings:enabled { - background-color: #4f7dd6; - background-image: none; - border-color: #2a4aac; - box-shadow: none; - color: #fbfafb; - text-shadow: none; -} - -.slider-legend { - position: relative; - /* This offset is needed to get the legend to align with the slider. */ - top: -7px; -} - -.slider-container { - display: inline-block; - position: relative; - top: 1px; - height: 24px; - width: 88px; -} -</style> -</head> -<body class="uber-frame"> -<div id="overlay-container" class="overlay" hidden> - <div id="reset-overlay" class="page"> - <div class="close-button"></div> - <div id="reset-this-script-overlay-dialog" hidden> - <h1>Reset</h1> - <div id="reset-this-script-overlay-dialog-content" class="content-area"> - </div> - <div class="action-area"> - <div class="button-strip"> - <button id="reset-this-script-cancel">Cancel</button> - <button id="reset-this-script-ok">Reset</button> - </div> - </div> - </div> - <div id="reset-all-scripts-overlay-dialog" hidden> - <h1>Reset</h1> - <div class="content-area"> - Are you sure you want to reset all settings? - </div> - <div class="action-area"> - <div class="button-strip"> - <button id="reset-all-cancel">Cancel</button> - <button id="reset-all-ok">Reset</button> - </div> - </div> - </div> - </div> -</div> -<div class="page"> - <header style="transform: translateX(0px);"> - <h1>Advanced Font Settings</h1> - </header> - <section> - <h3 class="script-header">Script</h3> - <div class="font-settings-row"> - <select style="width: 200px" id="scriptList"></select> - </div> - </section> - <section> - <h3>Proportional fonts</h3> - <div class="font-settings-row"> - <div class="font-settings-div"> - <div id="defaultFontSizeLabel"></div> - <div style="width: 100%; margin-bottom: 0"> - <span class="slider-legend smaller">Aa</span> - <div id="defaultFontSizeSliderContainer" class="slider-container"></div> - <span class="slider-legend">Aa</span> - </div> - </div> - <div class="font-settings-div"> - <div>Standard</div> - <div><select id="standardFontList"></select></div> - </div> - <div class="font-settings-div"> - <div>Serif</div> - <div><select id="serifFontList"></select></div> - </div> - <div class="font-settings-div"> - <div>Sans-Serif</div> - <div><select id="sansSerifFontList"></select></div> - </div> - </div> - <div class="bordered" style="position: relative; left: 0; right: 0; height: 160px; width: 702px;"> - <div class="sample-text-div" style="height: 33%"> - <span id='standardFontSample' class="sample-text-span"> - The quick brown fox jumps over the lazy dog. - </span> - </div> - <div class="sample-text-div" style="height: 33%"> - <span id="serifFontSample" class="sample-text-span"> - The quick brown fox jumps over the lazy dog. - </span> - </div> - <div class="sample-text-div" style="height: 33%"> - <span id="sansSerifFontSample" class="sample-text-span"> - The quick brown fox jumps over the lazy dog. - </span> - </div> - </div> - </section> - <section> - <h3>Fixed-width fonts</h3> - <div class="font-settings-row"> - <div class="font-settings-div"> - <div id="fixedFontSizeLabel"></div> - <div style="width: 100%; margin-bottom: 0"> - <span class="slider-legend smaller">Aa</span> - <div id="defaultFixedFontSizeSliderContainer" class="slider-container"></div> - <span class="slider-legend">Aa</span> - </div> - </div> - <div class="font-settings-div"> - <div>Fixed</div> - <div><select id="fixedFontList"></select></div> - </div> - </div> - <div class="bordered" style="position: relative; overflow: hidden; left: 0; right: 0; height: 58px; width: 702px;"> - <div class="sample-text-div" style="height: 100%"> - <span id="fixedFontSample" class="sample-text-span"> - The quick brown fox jumps over the lazy dog. - </span> - </div> - </div> - </section> - <section> - <h3>Minimum font size</h3> - <div class="font-settings-row"> - <div class="font-settings-div"> - <div id="minFontSizeLabel" style="margin-bottom: 8px"></div> - <div style="width: 100%; margin-bottom: 12px"> - <span class="slider-legend smaller">Aa</span> - <div id="minFontSizeSliderContainer" class="slider-container"></div> - <span class="slider-legend">Aa</span> - </div> - </div> - </div> - <div class="bordered" style="position: relative; overflow: hidden; left: 0; right: 0; height: 58px; width: 702px;"> - <div class="sample-text-div" style="height: 100%"> - <span id="minFontSample" class="sample-text-span"> - The quick brown fox jumps over the lazy dog. - </span> - </div> - </div> - </section> - <section id="footer"> - <button id="apply-settings"> - Apply settings - </button> - <button id="reset-this-script-button"> - Reset settings for this script - </button> - <button id="reset-all-button"> - Reset all settings - </button> - </section> -</div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/options.js b/chrome/common/extensions/docs/examples/api/fontSettings/options.js deleted file mode 100644 index 6c57f168..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/options.js +++ /dev/null
@@ -1,768 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -/** - * @fileoverview The Advanced Font Settings Extension implementation. - */ - -function $(id) { - return document.getElementById(id); -} - -/** - * @namespace - */ -var advancedFonts = {}; - -/** - * The ICU script code for the Common, or global, script, which is used as the - * fallback when the script is undeclared. - * @const - */ -advancedFonts.COMMON_SCRIPT = 'Zyyy'; - -/** - * The scripts supported by the Font Settings Extension API. - * @const - */ -advancedFonts.scripts = [ - { scriptCode: advancedFonts.COMMON_SCRIPT, scriptName: 'Default'}, - { scriptCode: 'Afak', scriptName: 'Afaka'}, - { scriptCode: 'Arab', scriptName: 'Arabic'}, - { scriptCode: 'Armi', scriptName: 'Imperial Aramaic'}, - { scriptCode: 'Armn', scriptName: 'Armenian'}, - { scriptCode: 'Avst', scriptName: 'Avestan'}, - { scriptCode: 'Bali', scriptName: 'Balinese'}, - { scriptCode: 'Bamu', scriptName: 'Bamum'}, - { scriptCode: 'Bass', scriptName: 'Bassa Vah'}, - { scriptCode: 'Batk', scriptName: 'Batak'}, - { scriptCode: 'Beng', scriptName: 'Bengali'}, - { scriptCode: 'Blis', scriptName: 'Blissymbols'}, - { scriptCode: 'Bopo', scriptName: 'Bopomofo'}, - { scriptCode: 'Brah', scriptName: 'Brahmi'}, - { scriptCode: 'Brai', scriptName: 'Braille'}, - { scriptCode: 'Bugi', scriptName: 'Buginese'}, - { scriptCode: 'Buhd', scriptName: 'Buhid'}, - { scriptCode: 'Cakm', scriptName: 'Chakma'}, - { scriptCode: 'Cans', scriptName: 'Unified Canadian Aboriginal Syllabics'}, - { scriptCode: 'Cari', scriptName: 'Carian'}, - { scriptCode: 'Cham', scriptName: 'Cham'}, - { scriptCode: 'Cher', scriptName: 'Cherokee'}, - { scriptCode: 'Cirt', scriptName: 'Cirth'}, - { scriptCode: 'Copt', scriptName: 'Coptic'}, - { scriptCode: 'Cprt', scriptName: 'Cypriot'}, - { scriptCode: 'Cyrl', scriptName: 'Cyrillic'}, - { scriptCode: 'Cyrs', scriptName: 'Old Church Slavonic Cyrillic'}, - { scriptCode: 'Deva', scriptName: 'Devanagari'}, - { scriptCode: 'Dsrt', scriptName: 'Deseret'}, - { scriptCode: 'Dupl', scriptName: 'Duployan shorthand'}, - { scriptCode: 'Egyd', scriptName: 'Egyptian demotic'}, - { scriptCode: 'Egyh', scriptName: 'Egyptian hieratic'}, - { scriptCode: 'Egyp', scriptName: 'Egyptian hieroglyphs'}, - { scriptCode: 'Elba', scriptName: 'Elbasan'}, - { scriptCode: 'Ethi', scriptName: 'Ethiopic'}, - { scriptCode: 'Geok', scriptName: 'Georgian Khutsuri'}, - { scriptCode: 'Geor', scriptName: 'Georgian'}, - { scriptCode: 'Glag', scriptName: 'Glagolitic'}, - { scriptCode: 'Goth', scriptName: 'Gothic'}, - { scriptCode: 'Gran', scriptName: 'Grantha'}, - { scriptCode: 'Grek', scriptName: 'Greek'}, - { scriptCode: 'Gujr', scriptName: 'Gujarati'}, - { scriptCode: 'Guru', scriptName: 'Gurmukhi'}, - { scriptCode: 'Hang', scriptName: 'Hangul'}, - { scriptCode: 'Hani', scriptName: 'Han'}, - { scriptCode: 'Hano', scriptName: 'Hanunoo'}, - { scriptCode: 'Hans', scriptName: 'Simplified Han'}, - { scriptCode: 'Hant', scriptName: 'Traditional Han'}, - { scriptCode: 'Hebr', scriptName: 'Hebrew'}, - { scriptCode: 'Hluw', scriptName: 'Anatolian Hieroglyphs'}, - { scriptCode: 'Hmng', scriptName: 'Pahawh Hmong'}, - { scriptCode: 'Hung', scriptName: 'Old Hungarian'}, - { scriptCode: 'Inds', scriptName: 'Indus'}, - { scriptCode: 'Ital', scriptName: 'Old Italic'}, - { scriptCode: 'Java', scriptName: 'Javanese'}, - { scriptCode: 'Jpan', scriptName: 'Japanese'}, - { scriptCode: 'Jurc', scriptName: 'Jurchen'}, - { scriptCode: 'Kali', scriptName: 'Kayah Li'}, - { scriptCode: 'Khar', scriptName: 'Kharoshthi'}, - { scriptCode: 'Khmr', scriptName: 'Khmer'}, - { scriptCode: 'Khoj', scriptName: 'Khojki'}, - { scriptCode: 'Knda', scriptName: 'Kannada'}, - { scriptCode: 'Kpel', scriptName: 'Kpelle'}, - { scriptCode: 'Kthi', scriptName: 'Kaithi'}, - { scriptCode: 'Lana', scriptName: 'Lanna'}, - { scriptCode: 'Laoo', scriptName: 'Lao'}, - { scriptCode: 'Latf', scriptName: 'Fraktur Latin'}, - { scriptCode: 'Latg', scriptName: 'Gaelic Latin'}, - { scriptCode: 'Latn', scriptName: 'Latin'}, - { scriptCode: 'Lepc', scriptName: 'Lepcha'}, - { scriptCode: 'Limb', scriptName: 'Limbu'}, - { scriptCode: 'Lina', scriptName: 'Linear A'}, - { scriptCode: 'Linb', scriptName: 'Linear B'}, - { scriptCode: 'Lisu', scriptName: 'Fraser'}, - { scriptCode: 'Loma', scriptName: 'Loma'}, - { scriptCode: 'Lyci', scriptName: 'Lycian'}, - { scriptCode: 'Lydi', scriptName: 'Lydian'}, - { scriptCode: 'Mand', scriptName: 'Mandaean'}, - { scriptCode: 'Mani', scriptName: 'Manichaean'}, - { scriptCode: 'Maya', scriptName: 'Mayan hieroglyphs'}, - { scriptCode: 'Mend', scriptName: 'Mende'}, - { scriptCode: 'Merc', scriptName: 'Meroitic Cursive'}, - { scriptCode: 'Mero', scriptName: 'Meroitic'}, - { scriptCode: 'Mlym', scriptName: 'Malayalam'}, - { scriptCode: 'Mong', scriptName: 'Mongolian'}, - { scriptCode: 'Moon', scriptName: 'Moon'}, - { scriptCode: 'Mroo', scriptName: 'Mro'}, - { scriptCode: 'Mtei', scriptName: 'Meitei Mayek'}, - { scriptCode: 'Mymr', scriptName: 'Myanmar'}, - { scriptCode: 'Narb', scriptName: 'Old North Arabian'}, - { scriptCode: 'Nbat', scriptName: 'Nabataean'}, - { scriptCode: 'Nkgb', scriptName: 'Naxi Geba'}, - { scriptCode: 'Nkoo', scriptName: 'N’Ko'}, - { scriptCode: 'Nshu', scriptName: 'Nüshu'}, - { scriptCode: 'Ogam', scriptName: 'Ogham'}, - { scriptCode: 'Olck', scriptName: 'Ol Chiki'}, - { scriptCode: 'Orkh', scriptName: 'Orkhon'}, - { scriptCode: 'Orya', scriptName: 'Oriya'}, - { scriptCode: 'Osma', scriptName: 'Osmanya'}, - { scriptCode: 'Palm', scriptName: 'Palmyrene'}, - { scriptCode: 'Perm', scriptName: 'Old Permic'}, - { scriptCode: 'Phag', scriptName: 'Phags-pa'}, - { scriptCode: 'Phli', scriptName: 'Inscriptional Pahlavi'}, - { scriptCode: 'Phlp', scriptName: 'Psalter Pahlavi'}, - { scriptCode: 'Phlv', scriptName: 'Book Pahlavi'}, - { scriptCode: 'Phnx', scriptName: 'Phoenician'}, - { scriptCode: 'Plrd', scriptName: 'Pollard Phonetic'}, - { scriptCode: 'Prti', scriptName: 'Inscriptional Parthian'}, - { scriptCode: 'Rjng', scriptName: 'Rejang'}, - { scriptCode: 'Roro', scriptName: 'Rongorongo'}, - { scriptCode: 'Runr', scriptName: 'Runic'}, - { scriptCode: 'Samr', scriptName: 'Samaritan'}, - { scriptCode: 'Sara', scriptName: 'Sarati'}, - { scriptCode: 'Sarb', scriptName: 'Old South Arabian'}, - { scriptCode: 'Saur', scriptName: 'Saurashtra'}, - { scriptCode: 'Sgnw', scriptName: 'SignWriting'}, - { scriptCode: 'Shaw', scriptName: 'Shavian'}, - { scriptCode: 'Shrd', scriptName: 'Sharada'}, - { scriptCode: 'Sind', scriptName: 'Khudawadi'}, - { scriptCode: 'Sinh', scriptName: 'Sinhala'}, - { scriptCode: 'Sora', scriptName: 'Sora Sompeng'}, - { scriptCode: 'Sund', scriptName: 'Sundanese'}, - { scriptCode: 'Sylo', scriptName: 'Syloti Nagri'}, - { scriptCode: 'Syrc', scriptName: 'Syriac'}, - { scriptCode: 'Syre', scriptName: 'Estrangelo Syriac'}, - { scriptCode: 'Syrj', scriptName: 'Western Syriac'}, - { scriptCode: 'Syrn', scriptName: 'Eastern Syriac'}, - { scriptCode: 'Tagb', scriptName: 'Tagbanwa'}, - { scriptCode: 'Takr', scriptName: 'Takri'}, - { scriptCode: 'Tale', scriptName: 'Tai Le'}, - { scriptCode: 'Talu', scriptName: 'New Tai Lue'}, - { scriptCode: 'Taml', scriptName: 'Tamil'}, - { scriptCode: 'Tang', scriptName: 'Tangut'}, - { scriptCode: 'Tavt', scriptName: 'Tai Viet'}, - { scriptCode: 'Telu', scriptName: 'Telugu'}, - { scriptCode: 'Teng', scriptName: 'Tengwar'}, - { scriptCode: 'Tfng', scriptName: 'Tifinagh'}, - { scriptCode: 'Tglg', scriptName: 'Tagalog'}, - { scriptCode: 'Thaa', scriptName: 'Thaana'}, - { scriptCode: 'Thai', scriptName: 'Thai'}, - { scriptCode: 'Tibt', scriptName: 'Tibetan'}, - { scriptCode: 'Tirh', scriptName: 'Tirhuta'}, - { scriptCode: 'Ugar', scriptName: 'Ugaritic'}, - { scriptCode: 'Vaii', scriptName: 'Vai'}, - { scriptCode: 'Visp', scriptName: 'Visible Speech'}, - { scriptCode: 'Wara', scriptName: 'Varang Kshiti'}, - { scriptCode: 'Wole', scriptName: 'Woleai'}, - { scriptCode: 'Xpeo', scriptName: 'Old Persian'}, - { scriptCode: 'Xsux', scriptName: 'Sumero-Akkadian Cuneiform'}, - { scriptCode: 'Yiii', scriptName: 'Yi'}, - { scriptCode: 'Zmth', scriptName: 'Mathematical Notation'}, - { scriptCode: 'Zsym', scriptName: 'Symbols'} -]; - -/** - * The generic font families supported by the Font Settings Extension API. - * @const - */ -advancedFonts.FAMILIES = - ['standard', 'sansserif', 'serif', 'fixed', 'cursive', 'fantasy']; - -/** - * Sample texts. - * @const - */ -advancedFonts.SAMPLE_TEXTS = { - // "Cyrllic script". - Cyrl: 'Кириллица', - Hang: '정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날.', - Hans: '床前明月光,疑是地上霜。举头望明月,低头思故乡。', - Hant: '床前明月光,疑是地上霜。舉頭望明月,低頭思故鄉。', - Jpan: '吾輩は猫である。名前はまだ無い。', - // "Khmer language". - Khmr: '\u1797\u17B6\u179F\u17B6\u1781\u17D2\u1798\u17C2\u179A', - Zyyy: 'The quick brown fox jumps over the lazy dog.' -}; - -/** - * Controller of pending changes. - * @const - */ -advancedFonts.pendingChanges = new PendingChanges(); - -/** - * Map from |genericFamily| to UI controls and data for its font setting. - */ -advancedFonts.fontSettings = null; - -/** - * Map from |fontSizeKey| to UI controls and data for its font size setting. - */ -advancedFonts.fontSizeSettings = null; - -/** - * Gets the font size used for |fontSizeKey|, including pending changes. Calls - * |callback| with the result. - * - * @param {string} fontSizeKey The font size setting key. See - * PendingChanges.getFontSize(). - * @param {function(number, boolean)} callback The callback of form - * function(size, controllable). |size| is the effective setting, - * |controllable| is whether the setting can be set. - */ -advancedFonts.getEffectiveFontSize = function(fontSizeKey, callback) { - advancedFonts.fontSizeSettings[fontSizeKey].getter({}, function(details) { - var controllable = advancedFonts.isControllableLevel( - details.levelOfControl); - var size = details.pixelSize; - var pendingFontSize = advancedFonts.pendingChanges.getFontSize(fontSizeKey); - // If the setting is not controllable, we can have no pending change. - if (!controllable) { - if (pendingFontSize != null) { - advancedFonts.pendingChanges.setFontSize(fontSizeKey, null); - $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty(); - pendingFontSize = null; - } - } - - // If we have a pending change, it overrides the current setting. - if (pendingFontSize != null) - size = pendingFontSize; - callback(size, controllable); - }); -}; - -/** - * Gets the font used for |script| and |genericFamily|, including pending - * changes. Calls |callback| with the result. - * - * @param {string} script The script code. - * @param {string} genericFamily The generic family. - * @param {function(string, boolean, string)} callback The callback of form - * function(font, controllable, effectiveFont). |font| is the setting - * (pending or not), |controllable| is whether the setting can be set, - * |effectiveFont| is the font used taking fallback into consideration. - */ -advancedFonts.getEffectiveFont = function(script, genericFamily, callback) { - var pendingChanges = advancedFonts.pendingChanges; - var details = { script: script, genericFamily: genericFamily }; - chrome.fontSettings.getFont(details, function(result) { - var setting = {}; - setting.font = result.fontId; - setting.controllable = - advancedFonts.isControllableLevel(result.levelOfControl); - var pendingFont = - pendingChanges.getFont(details.script, details.genericFamily); - // If the setting is not controllable, we can have no pending change. - if (!setting.controllable) { - if (pendingFont != null) { - pendingChanges.setFont(script, genericFamily, null); - $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty(); - pendingFont = null; - } - } - - // If we have a pending change, it overrides the current setting. - if (pendingFont != null) - setting.font = pendingFont; - - // If we have a font, we're done. - if (setting.font) { - callback(setting.font, setting.controllable, setting.font); - return; - } - - // If we're still here, we have to fallback to common script, unless this - // already is common script. - if (script == advancedFonts.COMMON_SCRIPT) { - callback('', setting.controllable, ''); - return; - } - advancedFonts.getEffectiveFont( - advancedFonts.COMMON_SCRIPT, - genericFamily, - callback.bind(null, setting.font, setting.controllable)); - }); -}; - -/** - * Refreshes the UI controls related to a font setting. - * - * @param {{fontList: HTMLSelectElement, samples: Array<HTMLElement>}} - * fontSetting The setting object (see advancedFonts.fontSettings). - * @param {string} font The value of the font setting. - * @param {boolean} controllable Whether the font setting can be controlled - * by this extension. - * @param {string} effectiveFont The font used, including fallback to Common - * script. - */ -advancedFonts.refreshFont = function( - fontSetting, font, controllable, effectiveFont) { - for (var i = 0; i < fontSetting.samples.length; ++i) - fontSetting.samples[i].style.fontFamily = effectiveFont; - advancedFonts.setSelectedFont(fontSetting.fontList, font); - fontSetting.fontList.disabled = !controllable; -}; - -/** - * Refreshes the UI controls related to a font size setting. - * - * @param {{label: HTMLElement, slider: Slider, samples: Array<HTMLElement>}} - * fontSizeSetting The setting object (see advancedFonts.fontSizeSettings). - * @param size The value of the font size setting. - * @param controllable Whether the setting can be controlled by this extension. - */ -advancedFonts.refreshFontSize = function(fontSizeSetting, size, controllable) { - fontSizeSetting.label.textContent = 'Size: ' + size + 'px'; - advancedFonts.setFontSizeSlider(fontSizeSetting.slider, size, controllable); - for (var i = 0; i < fontSizeSetting.samples.length; ++i) - fontSizeSetting.samples[i].style.fontSize = size + 'px'; -}; - -/** - * Refreshes all UI controls to reflect the current settings, including pending - * changes. - */ -advancedFonts.refresh = function() { - var script = advancedFonts.getSelectedScript(); - var sample; - if (advancedFonts.SAMPLE_TEXTS[script]) - sample = advancedFonts.SAMPLE_TEXTS[script]; - else - sample = advancedFonts.SAMPLE_TEXTS[advancedFonts.COMMON_SCRIPT]; - var sampleTexts = document.querySelectorAll('.sample-text-span'); - for (var i = 0; i < sampleTexts.length; i++) - sampleTexts[i].textContent = sample; - - var setting; - var callback; - for (var genericFamily in advancedFonts.fontSettings) { - setting = advancedFonts.fontSettings[genericFamily]; - callback = advancedFonts.refreshFont.bind(null, setting); - advancedFonts.getEffectiveFont(script, genericFamily, callback); - } - - for (var fontSizeKey in advancedFonts.fontSizeSettings) { - setting = advancedFonts.fontSizeSettings[fontSizeKey]; - callback = advancedFonts.refreshFontSize.bind(null, setting); - advancedFonts.getEffectiveFontSize(fontSizeKey, callback); - } - - $('apply-settings').disabled = advancedFonts.pendingChanges.isEmpty(); -}; - -/** - * @return {string} The currently selected script code. - */ -advancedFonts.getSelectedScript = function() { - var scriptList = $('scriptList'); - return scriptList.options[scriptList.selectedIndex].value; -}; - -/** - * @param {HTMLSelectElement} fontList The <select> containing a list of fonts. - * @return {string} The currently selected value of |fontList|. - */ -advancedFonts.getSelectedFont = function(fontList) { - return fontList.options[fontList.selectedIndex].value; -}; - -/** - * Populates the font lists. - * @param {Array<{fontId: string, displayName: string>} fonts The list of - * fonts on the system. - */ -advancedFonts.populateFontLists = function(fonts) { - for (var genericFamily in advancedFonts.fontSettings) { - var list = advancedFonts.fontSettings[genericFamily].fontList; - - // Add a special item to indicate fallback to the non-per-script - // font setting. The Font Settings API uses the empty string to indicate - // fallback. - var defaultItem = document.createElement('option'); - defaultItem.value = ''; - defaultItem.text = '(Use default)'; - list.add(defaultItem); - - for (var i = 0; i < fonts.length; ++i) { - var item = document.createElement('option'); - item.value = fonts[i].fontId; - item.text = fonts[i].displayName; - list.add(item); - } - } - advancedFonts.refresh(); -}; - -/** - * Handles change events on a <select> element for a font setting. - * @param {string} genericFamily The generic family for the font setting. - * @param {Event} event The change event. - */ -advancedFonts.handleFontListChange = function(genericFamily, event) { - var script = advancedFonts.getSelectedScript(); - var font = advancedFonts.getSelectedFont(event.target); - - advancedFonts.pendingChanges.setFont(script, genericFamily, font); - advancedFonts.refresh(); -}; - -/** - * Sets the selected value of |fontList| to |fontId|. - * @param {HTMLSelectElement} fontList The <select> containing a list of fonts. - * @param {string} fontId The font to set |fontList|'s selection to. - */ -advancedFonts.setSelectedFont = function(fontList, fontId) { - var script = advancedFonts.getSelectedScript(); - var i; - for (i = 0; i < fontList.length; i++) { - if (fontId == fontList.options[i].value) { - fontList.selectedIndex = i; - break; - } - } - if (i == fontList.length) { - console.warn("font '" + fontId + "' for " + fontList.id + ' for ' + - script + ' is not on the system'); - } -}; - -/** - * Handles change events on a font size slider. - * @param {string} fontSizeKey The key for the font size setting whose slider - * changed. See PendingChanges.getFont. - * @param {string} value The new value of the slider. - */ -advancedFonts.handleFontSizeSliderChange = function(fontSizeKey, value) { - var pixelSize = parseInt(value); - if (!isNaN(pixelSize)) { - advancedFonts.pendingChanges.setFontSize(fontSizeKey, pixelSize); - advancedFonts.refresh(); - } -}; - -/** - * @param {string} levelOfControl The level of control string for a setting, - * as returned by the Font Settings Extension API. - * @return {boolean} True if |levelOfControl| signifies that the extension can - * control the setting; otherwise, returns false. - */ -advancedFonts.isControllableLevel = function(levelOfControl) { - return levelOfControl == 'controllable_by_this_extension' || - levelOfControl == 'controlled_by_this_extension'; -}; - -/* - * Updates the specified font size slider's value and enabled property. - * @param {Slider} slider The slider for a font size setting. - * @param {number} size The value to set the slider to. - * @param {boolean} enabled Whether to enable or disable the slider. - */ -advancedFonts.setFontSizeSlider = function(slider, size, enabled) { - if (slider.getValue() != size) - slider.setValue(size); - var inputElement = slider.getInput(); - if (enabled) { - inputElement.parentNode.classList.remove('disabled'); - inputElement.disabled = false; - } else { - inputElement.parentNode.classList.add('disabled'); - inputElement.disabled = true; - } -}; - -/** - * Initializes the UI control elements related to the font size setting - * |fontSizeKey| and registers listeners for the user adjusting its slider and - * the setting changing on the browser-side. - * @param {string} fontSizeKey The key for font size setting. See - * PendingChanges.getFont(). - */ -advancedFonts.initFontSizeSetting = function(fontSizeKey) { - var fontSizeSettings = advancedFonts.fontSizeSettings; - var setting = fontSizeSettings[fontSizeKey]; - var label = setting.label; - var samples = setting.samples; - - setting.slider = new Slider( - setting.sliderContainer, - 0, - setting.minValue, - setting.maxValue, - advancedFonts.handleFontSizeSliderChange.bind(null, fontSizeKey) - ); - - var slider = setting.slider; - setting.getter({}, function(details) { - var size = details.pixelSize.toString(); - var controllable = advancedFonts.isControllableLevel( - details.levelOfControl); - advancedFonts.setFontSizeSlider(slider, size, controllable); - for (var i = 0; i < samples.length; i++) - samples[i].style.fontSize = size + 'px'; - }); - fontSizeSettings[fontSizeKey].onChanged.addListener(advancedFonts.refresh); -}; - -/** - * Clears the font settings for the specified script. - * @param {string} script The script code. - */ -advancedFonts.clearSettingsForScript = function(script) { - advancedFonts.pendingChanges.clearOneScript(script); - for (var i = 0; i < advancedFonts.FAMILIES.length; i++) { - chrome.fontSettings.clearFont({ - script: script, - genericFamily: advancedFonts.FAMILIES[i] - }); - } -}; - -/** - * Clears all font and font size settings. - */ -advancedFonts.clearAllSettings = function() { - advancedFonts.pendingChanges.clear(); - for (var i = 0; i < advancedFonts.scripts.length; i++) - advancedFonts.clearSettingsForScript(advancedFonts.scripts[i].scriptCode); - chrome.fontSettings.clearDefaultFixedFontSize(); - chrome.fontSettings.clearDefaultFontSize(); - chrome.fontSettings.clearMinimumFontSize(); -}; - -/** - * Closes the overlay. - */ -advancedFonts.closeOverlay = function() { - $('overlay-container').hidden = true; -}; - -/** - * Initializes apply and reset buttons. - */ -advancedFonts.initApplyAndResetButtons = function() { - var applyButton = $('apply-settings'); - applyButton.addEventListener('click', function() { - advancedFonts.pendingChanges.apply(); - advancedFonts.refresh(); - }); - - var overlay = $('overlay-container'); - cr.ui.overlay.globalInitialization(); - cr.ui.overlay.setupOverlay(overlay); - overlay.addEventListener('cancelOverlay', advancedFonts.closeOverlay); - - $('reset-this-script-button').onclick = function(event) { - var scriptList = $('scriptList'); - var scriptName = scriptList.options[scriptList.selectedIndex].text; - $('reset-this-script-overlay-dialog-content').innerText = - 'Are you sure you want to reset settings for ' + scriptName + - ' script?'; - - $('overlay-container').hidden = false; - $('reset-this-script-overlay-dialog').hidden = false; - $('reset-all-scripts-overlay-dialog').hidden = true; - }; - $('reset-this-script-ok').onclick = function(event) { - advancedFonts.clearSettingsForScript(advancedFonts.getSelectedScript()); - advancedFonts.closeOverlay(); - advancedFonts.refresh(); - }; - $('reset-this-script-cancel').onclick = advancedFonts.closeOverlay; - - $('reset-all-button').onclick = function(event) { - $('overlay-container').hidden = false; - $('reset-all-scripts-overlay-dialog').hidden = false; - $('reset-this-script-overlay-dialog').hidden = true; - }; - $('reset-all-ok').onclick = function(event) { - advancedFonts.clearAllSettings(); - advancedFonts.closeOverlay(); - advancedFonts.refresh(); - }; - $('reset-all-cancel').onclick = advancedFonts.closeOverlay; -}; - -/** - * Best guess for system fonts, taken from the IDS_WEB_FONT_FAMILY strings in - * Chrome. - * TODO: The font should be localized like Chrome does. - * @const - */ -advancedFonts.systemFonts = { - cros: 'Noto Sans UI, sans-serif', - linux: 'Ubuntu, sans-serif', - mac: 'Lucida Grande, sans-serif', - win: 'Segoe UI, Tahoma, sans-serif', - unknown: 'sans-serif' -}; - -/** - * @return {string} The platform this extension is running on. - */ -advancedFonts.getPlatform = function() { - var ua = window.navigator.appVersion; - if (ua.indexOf('Win') != -1) return 'win'; - if (ua.indexOf('Mac') != -1) return 'mac'; - if (ua.indexOf('Linux') != -1) return 'linux'; - if (ua.indexOf('CrOS') != -1) return 'cros'; - return 'unknown'; -}; - -/** - * Chrome settings tries to use the system font. So does this extension. - */ -advancedFonts.useSystemFont = function() { - document.body.style.fontFamily = - advancedFonts.systemFonts[advancedFonts.getPlatform()]; -}; - -/** - * Sorts the list of script codes by scriptName. Someday this extension will - * have localized script names, so the order will depend on locale. - */ -advancedFonts.sortScripts = function() { - var i; - var scripts = advancedFonts.scripts; - for (i = 0; i < scripts; ++i) { - if (scripts[i].scriptCode == advancedFonts.COMMON_SCRIPT) - break; - } - var defaultScript = scripts.splice(i, 1)[0]; - - scripts.sort(function(a, b) { - if (a.scriptName > b.scriptName) - return 1; - if (a.scriptName < b.scriptName) - return -1; - return 0; - }); - - scripts.unshift(defaultScript); -}; - -/** - * Initializes UI controls for font settings. - */ -advancedFonts.initFontControls = function() { - advancedFonts.fontSettings = { - standard: { - fontList: $('standardFontList'), - samples: [$('standardFontSample'), $('minFontSample')] - }, - serif: { - fontList: $('serifFontList'), - samples: [$('serifFontSample')] - }, - sansserif: { - fontList: $('sansSerifFontList'), - samples: [$('sansSerifFontSample')] - }, - fixed: { - fontList: $('fixedFontList'), - samples: [$('fixedFontSample')] - } - }; - - for (var genericFamily in advancedFonts.fontSettings) { - var list = advancedFonts.fontSettings[genericFamily].fontList; - list.addEventListener( - 'change', advancedFonts.handleFontListChange.bind(list, genericFamily)); - } - chrome.fontSettings.onFontChanged.addListener(advancedFonts.refresh); - chrome.fontSettings.getFontList(advancedFonts.populateFontLists); -}; - -/** - * Initializes UI controls for font size settings. - */ -advancedFonts.initFontSizeControls = function() { - advancedFonts.fontSizeSettings = { - defaultFontSize: { - sliderContainer: $('defaultFontSizeSliderContainer'), - minValue: 6, - maxValue: 50, - samples: [ - $('standardFontSample'), $('serifFontSample'), $('sansSerifFontSample') - ], - label: $('defaultFontSizeLabel'), - getter: chrome.fontSettings.getDefaultFontSize, - onChanged: chrome.fontSettings.onDefaultFontSizeChanged - }, - defaultFixedFontSize: { - sliderContainer: $('defaultFixedFontSizeSliderContainer'), - minValue: 6, - maxValue: 50, - samples: [$('fixedFontSample')], - label: $('fixedFontSizeLabel'), - getter: chrome.fontSettings.getDefaultFixedFontSize, - onChanged: chrome.fontSettings.onDefaultFixedFontSizeChanged - }, - minFontSize: { - sliderContainer: $('minFontSizeSliderContainer'), - minValue: 6, - maxValue: 24, - samples: [$('minFontSample')], - label: $('minFontSizeLabel'), - getter: chrome.fontSettings.getMinimumFontSize, - onChanged: chrome.fontSettings.onMinimumFontSizeChanged - } - }; - - for (var fontSizeKey in advancedFonts.fontSizeSettings) - advancedFonts.initFontSizeSetting(fontSizeKey); -}; - -/** - * Initializes the list of scripts. - */ -advancedFonts.initScriptList = function() { - var scriptList = $('scriptList'); - advancedFonts.sortScripts(); - var scripts = advancedFonts.scripts; - for (var i = 0; i < scripts.length; i++) { - var script = document.createElement('option'); - script.value = scripts[i].scriptCode; - script.text = scripts[i].scriptName; - scriptList.add(script); - } - scriptList.selectedIndex = 0; - scriptList.addEventListener('change', advancedFonts.refresh); -}; - -/** - * Initializes the extension. - */ -advancedFonts.init = function() { - advancedFonts.useSystemFont(); - - advancedFonts.initFontControls(); - advancedFonts.initFontSizeControls(); - advancedFonts.initScriptList(); - - advancedFonts.initApplyAndResetButtons(); -}; - -document.addEventListener('DOMContentLoaded', advancedFonts.init);
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/pending_changes.js b/chrome/common/extensions/docs/examples/api/fontSettings/pending_changes.js deleted file mode 100644 index be43bb9..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/pending_changes.js +++ /dev/null
@@ -1,145 +0,0 @@ -// Copyright 2013 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. - -'use strict'; - -/** - * @fileoverview PendingChanges class tracks changes to be applied when an - * "Apply Changes" button is clicked. - */ - -/** - * Creates a PendingChanges object with no pending changes. - * - * @constructor - */ -var PendingChanges = function() { - // Format: pendingFontChanges_.Cyrl.sansserif = "My SansSerif Cyrillic Font" - this.pendingFontChanges_ = {}; - - // Format: pendingFontSizeChanges_.defaultFontSize = 12 - this.pendingFontSizeChanges_ = {}; -}; - -/** - * Returns the pending font setting change for the specified script and family, - * or null if it doesn't exist. - * - * @param {string} script The script code, like "Cyrl". - * @param {string} genericFamily The generic family, like "sansserif". - * @return {?string} The pending font setting, like "My Cyrillic SansSerif Font" - * or null if it doesn't exist. - */ -PendingChanges.prototype.getFont = function(script, genericFamily) { - if (this.pendingFontChanges_[script]) - return this.pendingFontChanges_[script][genericFamily]; - return null; -}; - -/** - * Returns the pending font size setting change, or null if it doesn't exist. - * - * @param {string} fontSizeKey The font size setting key. One of - * 'defaultFontSize', 'defaultFixedFontSize', or 'minFontSize'. - * @return {?number} The pending font size setting in pixels, or null if it - * doesn't exist. - */ -PendingChanges.prototype.getFontSize = function(fontSizeKey) { - return this.pendingFontSizeChanges_[fontSizeKey]; -}; - -/** - * Sets the pending font change for the specified script and family. - * - * @param {string} script The script code, like "Cyrl". - * @param {string} genericFamily The generic family, like "sansserif". - * @param {?string} font The font to set the setting to, or null to clear it. - */ -PendingChanges.prototype.setFont = function(script, genericFamily, font) { - if (!this.pendingFontChanges_[script]) - this.pendingFontChanges_[script] = {}; - if (this.pendingFontChanges_[script][genericFamily] == font) - return; - this.pendingFontChanges_[script][genericFamily] = font; -}; - -/** - * Sets the pending font size change. - * - * @param {string} fontSizeKey The font size setting key. See - * getFontSize(). - * @param {number} size The font size to set the setting to. - */ -PendingChanges.prototype.setFontSize = function(fontSizeKey, size) { - if (this.pendingFontSizeChanges_[fontSizeKey] == size) - return; - this.pendingFontSizeChanges_[fontSizeKey] = size; -}; - -/** - * Commits the pending changes to Chrome. After this function is called, there - * are no pending changes. - */ -PendingChanges.prototype.apply = function() { - for (var script in this.pendingFontChanges_) { - for (var genericFamily in this.pendingFontChanges_[script]) { - var fontId = this.pendingFontChanges_[script][genericFamily]; - if (fontId == null) - continue; - var details = {}; - details.script = script; - details.genericFamily = genericFamily; - details.fontId = fontId; - chrome.fontSettings.setFont(details); - } - } - - var size = this.pendingFontSizeChanges_['defaultFontSize']; - if (size != null) - chrome.fontSettings.setDefaultFontSize({pixelSize: size}); - - size = this.pendingFontSizeChanges_['defaultFixedFontSize']; - if (size != null) - chrome.fontSettings.setDefaultFixedFontSize({pixelSize: size}); - - size = this.pendingFontSizeChanges_['minFontSize']; - if (size != null) - chrome.fontSettings.setMinimumFontSize({pixelSize: size}); - - this.clear(); -}; - -/** - * Clears the pending font changes for a single script. - * - * @param {string} script The script code, like "Cyrl". - */ -PendingChanges.prototype.clearOneScript = function(script) { - this.pendingFontChanges_[script] = {}; -}; - -/** - * Clears all pending font changes. - */ -PendingChanges.prototype.clear = function() { - this.pendingFontChanges_ = {}; - this.pendingFontSizeChanges_ = {}; -}; - -/** - * @return {boolean} True if there are no pending changes, otherwise false. - */ -PendingChanges.prototype.isEmpty = function() { - for (var script in this.pendingFontChanges_) { - for (var genericFamily in this.pendingFontChanges_[script]) { - if (this.pendingFontChanges_[script][genericFamily] != null) - return false; - } - } - for (var name in this.pendingFontSizeChanges_) { - if (this.pendingFontSizeChanges_[name] != null) - return false; - } - return true; -};
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/slider.css b/chrome/common/extensions/docs/examples/api/fontSettings/slider.css deleted file mode 100644 index 236054f1..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/slider.css +++ /dev/null
@@ -1,113 +0,0 @@ -/* Copyright 2013 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. - */ - -/* Customize the standard input[type='range']. */ -.slider > input[type='range'] { - -webkit-appearance: none !important; /* Hide the default thumb icon. */ - background: transparent; /* Hide the standard slider bar */ - height: 100%; - left: -2px; /* Required to align the input element with the parent. */ - position: absolute; - top: -2px; - width: 100%; -} - -/* Custom thumb icon. */ -.slider > input[type='range']::-webkit-slider-thumb { - -webkit-appearance: none; - background-position: center center; - background-repeat: no-repeat; - height: 24px; - position: relative; - z-index: 2; -} - -/* Custom slider bar (we hide the standard one). */ -.slider > .bar { - /* In order to match the horizontal position of the standard slider bar - left and right must be equal to 1/2 of the thumb icon width. */ - left: 8px; - right: 8px; - bottom: 10px; - pointer-events: none; /* Mouse events pass through to the standard input. */ - position: absolute; - top: 10px; - background-image: url(../images/slider/slide_bar_center.png); - height: 4px; -} - -.slider > .bar > .filled, -.slider > .bar > .cap { - position: absolute; -} - -/* The filled portion of the slider bar to the left of the thumb. */ -.slider > .bar > .filled { - border-left-style: none; - border-right-style: none; - left: 0; - width: 0; /* The element style.width is manipulated from the code. */ -} - -.slider > .bar > .cap.right { - background-image: url(../images/slider/slider_bar_right.png); - height: 4px; - width: 4px; - left: 100%; -} - -.slider > .bar > .filled { - background-image: url(../images/slider/slide_bar_fill_center.png); - height: 4px; -} - -.slider > .bar > .cap.left { - background-image: url(../images/slider/slide_bar_fill_left.png); - height: 4px; - width: 4px; - right: 100%; -} - -.slider.disabled > .bar { - background-image: url(../images/slider/slide_bar_disabled_center.png); -} - -.slider.disabled > .bar > .filled { - background-image: url(../images/slider/slide_bar_disabled_center.png); -} - -.slider.disabled > .bar > .cap.left { - background-image: url(../images/slider/slide_bar_disabled_left.png); -} - -.slider.disabled > .bar > .cap.right { - background-image: url(../images/slider/slide_bar_disabled_right.png); -} - -.slider.disabled, -.slider.readonly { - pointer-events: none; -} - -.slider { - -webkit-box-flex: 1; -} - -.slider > input[type='range']::-webkit-slider-thumb { - background-image: url(../images/slider/slider_thumb.png); - width: 16px; -} - -.slider > input[type='range']::-webkit-slider-thumb:hover { - background-image: url(../images/slider/slider_thumb_hover.png); -} - -.slider > input[type='range']::-webkit-slider-thumb:active { - background-image: url(../images/slider/slider_thumb_down.png); -} - -.slider.disabled > input[type='range']::-webkit-slider-thumb { - background-image: url(../images/slider/slider_thumb_disabled.png); -}
diff --git a/chrome/common/extensions/docs/examples/api/fontSettings/slider.js b/chrome/common/extensions/docs/examples/api/fontSettings/slider.js deleted file mode 100644 index ff139dc..0000000 --- a/chrome/common/extensions/docs/examples/api/fontSettings/slider.js +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2013 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. - -'use strict'; - -/** - * @fileoverview A Slider control. Based on Chromium's MediaControls.Slider. - */ - -/** - * Creates a slider control. - * - * @param {HTMLElement} container The containing div element. - * @param {number} value Initial value - * @param {number} min Minimum value - * @param {number} max Maximum value - * @param {?function(number)=} opt_onChange Value change handler - * @constructor - */ -function Slider(container, value, min, max, opt_onChange) { - this.container_ = container; - this.onChange_ = opt_onChange; - - var containerDocument = this.container_.ownerDocument; - - this.container_.classList.add('slider'); - - this.input_ = containerDocument.createElement('input'); - this.input_.type = 'range'; - this.input_.min = min; - this.input_.max = max; - this.input_.value = value; - this.container_.appendChild(this.input_); - - this.input_.addEventListener( - 'change', this.onInputChange_.bind(this)); - this.input_.addEventListener( - 'input', this.onInputChange_.bind(this)); - - this.bar_ = containerDocument.createElement('div'); - this.bar_.className = 'bar'; - this.container_.appendChild(this.bar_); - - this.filled_ = containerDocument.createElement('div'); - this.filled_.className = 'filled'; - this.bar_.appendChild(this.filled_); - - var leftCap = containerDocument.createElement('div'); - leftCap.className = 'cap left'; - this.bar_.appendChild(leftCap); - - var rightCap = containerDocument.createElement('div'); - rightCap.className = 'cap right'; - this.bar_.appendChild(rightCap); - - this.updateFilledWidth_(); -}; - -/** - * @return {number} The value of the input control. - */ -Slider.prototype.getValue = function() { - return this.input_.value; -}; - -/** - * @param{number} value The value to set the input control to. - */ -Slider.prototype.setValue = function(value) { - this.input_.value = value; - this.updateFilledWidth_(); -}; - -/** - * @return {HTMLInputElement} The underlying input control. - */ -Slider.prototype.getInput = function() { - return this.input_; -} - -/** - * Updates the filled portion of the slider to reflect the slider's current - * value. - * @private - */ -Slider.prototype.updateFilledWidth_ = function() { - var proportion = (this.input_.value - this.input_.min) / - (this.input_.max - this.input_.min); - this.filled_.style.width = proportion * 100 + '%'; -}; - -/** - * Called when the slider's value changes. - * @private - */ -Slider.prototype.onInputChange_ = function() { - this.updateFilledWidth_(); - if (this.onChange_) - this.onChange_(this.input_.value); -}; -
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/history.html b/chrome/common/extensions/docs/examples/api/history/historyOverride/history.html deleted file mode 100644 index 689b5ef2..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/history.html +++ /dev/null
@@ -1,42 +0,0 @@ -<html> - <head> - <title>History</title> - <link rel="stylesheet" type="text/css" href="style.css"/> - </head> - <body> - <div id="searchBar"> - <h1>History<sup>2</sup></h1> - <input id="searchInput" type="text" name="search" - placeholder="Search History"> - <input type="submit" id="searchSubmit" value="Submit"> - <br> - <br> - <input type="submit" id="deleteSelected" value="Delete Selected"> - <br> - <br> - <input type="submit" id="removeAll" value="Remove All"> - <br> - <br> - <input type="submit" id="seeAll" value="See All"> - </div> - <div id="historyDiv"> - </div> - <template id="historyTemplate"> - <div class="history"> - <div class="imageDiv"> - <a class="titleLink"></a> - </div> - <div class="urlDiv"> - <p class="pageName"></p> - </div> - <div class="removeDiv"> - <a> - <button class="removeButton">Delete</button> - <input type="checkbox" class="removeCheck"/> - </a> - </div> - </div> - </template> - <script src="logic.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/history128.png b/chrome/common/extensions/docs/examples/api/history/historyOverride/history128.png deleted file mode 100644 index e53641a..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/history128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/history16.png b/chrome/common/extensions/docs/examples/api/history/historyOverride/history16.png deleted file mode 100644 index cdb6e8ae..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/history16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/history32.png b/chrome/common/extensions/docs/examples/api/history/historyOverride/history32.png deleted file mode 100644 index 004630a..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/history32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/history48.png b/chrome/common/extensions/docs/examples/api/history/historyOverride/history48.png deleted file mode 100644 index c16dfe8..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/history48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/logic.js b/chrome/common/extensions/docs/examples/api/history/historyOverride/logic.js deleted file mode 100644 index fc07ddb..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/logic.js +++ /dev/null
@@ -1,76 +0,0 @@ -// 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. - -const kMillisecondsPerWeek = 1000 * 60 * 60 * 24 * 7; -const kOneWeekAgo = (new Date).getTime() - kMillisecondsPerWeek; -let historyDiv = document.getElementById('historyDiv'); -const kColors = ['#4688F1', '#E8453C', '#F9BB2D', '#3AA757']; -let $ = document.getElementById.bind(document); - -function constructHistory(historyItems) { - let template = $('historyTemplate'); - for (let item of historyItems) { - let displayDiv = template.content.querySelector("#history, div"); - let randomColor = kColors[Math.floor(Math.random() * kColors.length)]; - displayDiv.style.backgroundColor = randomColor; - let titleLink = template.content.querySelector('.titleLink, a'); - let pageName = template.content.querySelector('.pageName, p'); - let removeButton = template.content.querySelector('.removeButton, button'); - let checkbox = template.content.querySelector('.removeCheck, input'); - checkbox.setAttribute('value', item.url); - let favicon = document.createElement('img'); - let host = new URL(item.url).host; - titleLink.href = item.url; - favicon.src = 'chrome://favicon/' + item.url; - titleLink.textContent = host; - titleLink.appendChild(favicon); - pageName.innerText = item.title; - if (item.title === '') { - pageName.innerText = host; - } - var clone = document.importNode(template.content, true); - clone.querySelector('.removeButton, button') - .addEventListener('click', function() { - chrome.history.deleteUrl({url: item.url}, function() { - location.reload(); - }); - }); - historyDiv.appendChild(clone); - } -} - -chrome.history.search({ - text: '', - startTime: kOneWeekAgo, - maxResults: 99 - }, constructHistory); - -$('searchSubmit').onclick = function() { - historyDiv.innerHTML = " " - let searchQuery = document.getElementById('searchInput').value - chrome.history.search({ - text: searchQuery, - startTime: kOneWeekAgo - }, constructHistory) -} - -$('deleteSelected').onclick = function() { - let checkboxes = document.getElementsByTagName('input'); - for (var i =0; i<checkboxes.length; i++) { - if (checkboxes[i].checked == true) { - chrome.history.deleteUrl({url: checkboxes[i].value}) - } - } - location.reload(); -} - -$('removeAll').onclick = function() { - chrome.history.deleteAll(function() { - location.reload(); - }); -} - -$('seeAll').onclick = function() { - location.reload(); -}
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/manifest.json b/chrome/common/extensions/docs/examples/api/history/historyOverride/manifest.json deleted file mode 100644 index bb44e22..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/manifest.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "manifest_version": 2, - "name": "History Override", - "description": "Overrides the History Page", - "version": "1.0", - "chrome_url_overrides" : { - "history": "history.html" - }, - "browser_action": { - "default_title": "History" - }, - "permissions": [ - "history", - "chrome://favicon/" - ], - "icons": { - "16": "history16.png", - "32": "history32.png", - "48": "history48.png", - "128": "history128.png" - } -}
diff --git a/chrome/common/extensions/docs/examples/api/history/historyOverride/style.css b/chrome/common/extensions/docs/examples/api/history/historyOverride/style.css deleted file mode 100644 index bc4db0a..0000000 --- a/chrome/common/extensions/docs/examples/api/history/historyOverride/style.css +++ /dev/null
@@ -1,130 +0,0 @@ -/* 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.*/ -::-webkit-scrollbar { - width: 0px; /* remove scrollbar space */ - background: transparent; /* make scrollbar invisible */ -} - -#searchBar { - float: left; - width: 250px; - height: auto; - position: absolute; - top: 10; - left: 10; -} - -#historyDiv { - color: white; - font-size: 16px; - max-width: 1020px; - min-width: 320px; - max-height: 98vh; - min-height: 500px; - position: absolute; - top: 10; - left: 260; - overflow: scroll; - overflow-x: hidden; -} - -.history { - float: left; - margin-right: 10px; - margin-bottom: 10px; - width: 300px; - height: 150px; - word-wrap: break-word; - padding: 10px; - display:inline-block; -} - -.title { - color: black; - float: left; - position: relative; - left: 15; - bottom: 15; -} - -img { - float: left; - position: relative; - left: 5; - top: 2; - margin-right: 8px; -} - - -.imageDiv { - background-color: white; - width: 310px; - height: 20px; - position: relative; - right: 0; - overflow-y: hidden; -} - -.removeButton { - position: relative; - right: 0; - bottom: 0; - height: 30px; - width: 50px; - border: none; - background-color: white; -} - -.urlDiv { - position: relative; - right: 0; - top: -10; - height: 90px; - width: 300px; - overflow-y: hidden; -} - -.removeCheck { - position: relative; - left: 230; - bottom: -15; - height: 30px; -} - -#searchSubmit { - height: 30px; - width: 50px; - border: none; - background-color: #3AA757; -} - -#deleteSelected { - height: 30px; - width: 185px; - border: none; - background-color: #F9BB2D; -} - -#removeAll { - height: 30px; - width: 185px; - border: none; - background-color: #E8453C; -} - -#seeAll { - height: 30px; - width: 185px; - border: none; - background-color: #4688F1; -} - -#searchInput { - height: 30px; -} - -h1 { - font-size: 50px; - font-family: Impact, Charcoal, sans-serif; -}
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png b/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png deleted file mode 100644 index 8fd573f5..0000000 --- a/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json b/chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json deleted file mode 100644 index b4aa6ffe..0000000 --- a/chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "Typed URL History", - "version": "1.2", - "description": "Reads your history, and shows the top ten pages you go to by typing the URL.", - "permissions": [ - "history" - ], - "browser_action": { - "default_popup": "typedUrls.html", - "default_icon": "clock.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html b/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html deleted file mode 100644 index 9b8bc71..0000000 --- a/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html +++ /dev/null
@@ -1,15 +0,0 @@ -<!DOCTYPE HTML> -<html> - <head> - <title>Recently Typed URLs</title> - <style> - body {min-width: 250px;} - </style> - <script src='typedUrls.js'></script> - </head> - - <body> - <h2>Recently Typed URLs:</h2> - <div id="typedUrl_div"></div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js b/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js deleted file mode 100644 index 204d1ac..0000000 --- a/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Event listner for clicks on links in a browser action popup. -// Open the link in a new tab of the current window. -function onAnchorClick(event) { - chrome.tabs.create({ - selected: true, - url: event.srcElement.href - }); - return false; -} - -// Given an array of URLs, build a DOM list of those URLs in the -// browser action popup. -function buildPopupDom(divName, data) { - var popupDiv = document.getElementById(divName); - - var ul = document.createElement('ul'); - popupDiv.appendChild(ul); - - for (var i = 0, ie = data.length; i < ie; ++i) { - var a = document.createElement('a'); - a.href = data[i]; - a.appendChild(document.createTextNode(data[i])); - a.addEventListener('click', onAnchorClick); - - var li = document.createElement('li'); - li.appendChild(a); - - ul.appendChild(li); - } -} - -// Search history to find up to ten links that a user has typed in, -// and show those links in a popup. -function buildTypedUrlList(divName) { - // To look for history items visited in the last week, - // subtract a week of microseconds from the current time. - var microsecondsPerWeek = 1000 * 60 * 60 * 24 * 7; - var oneWeekAgo = (new Date).getTime() - microsecondsPerWeek; - - // Track the number of callbacks from chrome.history.getVisits() - // that we expect to get. When it reaches zero, we have all results. - var numRequestsOutstanding = 0; - - chrome.history.search({ - 'text': '', // Return every history item.... - 'startTime': oneWeekAgo // that was accessed less than one week ago. - }, - function(historyItems) { - // For each history item, get details on all visits. - for (var i = 0; i < historyItems.length; ++i) { - var url = historyItems[i].url; - var processVisitsWithUrl = function(url) { - // We need the url of the visited item to process the visit. - // Use a closure to bind the url into the callback's args. - return function(visitItems) { - processVisits(url, visitItems); - }; - }; - chrome.history.getVisits({url: url}, processVisitsWithUrl(url)); - numRequestsOutstanding++; - } - if (!numRequestsOutstanding) { - onAllVisitsProcessed(); - } - }); - - - // Maps URLs to a count of the number of times the user typed that URL into - // the omnibox. - var urlToCount = {}; - - // Callback for chrome.history.getVisits(). Counts the number of - // times a user visited a URL by typing the address. - var processVisits = function(url, visitItems) { - for (var i = 0, ie = visitItems.length; i < ie; ++i) { - // Ignore items unless the user typed the URL. - if (visitItems[i].transition != 'typed') { - continue; - } - - if (!urlToCount[url]) { - urlToCount[url] = 0; - } - - urlToCount[url]++; - } - - // If this is the final outstanding call to processVisits(), - // then we have the final results. Use them to build the list - // of URLs to show in the popup. - if (!--numRequestsOutstanding) { - onAllVisitsProcessed(); - } - }; - - // This function is called when we have the final list of URls to display. - var onAllVisitsProcessed = function() { - // Get the top scorring urls. - urlArray = []; - for (var url in urlToCount) { - urlArray.push(url); - } - - // Sort the URLs by the number of times the user typed them. - urlArray.sort(function(a, b) { - return urlToCount[b] - urlToCount[a]; - }); - - buildPopupDom(divName, urlArray.slice(0, 10)); - }; -} - -document.addEventListener('DOMContentLoaded', function () { - buildTypedUrlList("typedUrl_div"); -}); \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/i18n/cld/background.js b/chrome/common/extensions/docs/examples/api/i18n/cld/background.js deleted file mode 100644 index 0c948493..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/cld/background.js +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright (c) 2009 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. - -var selectedId = -1; -function refreshLanguage() { - chrome.tabs.detectLanguage(null, function(language) { - console.log(language); - if (language == " invalid_language_code") - language = "???"; - chrome.browserAction.setBadgeText({"text": language, tabId: selectedId}); - }); -} - -chrome.tabs.onUpdated.addListener(function(tabId, props) { - if (props.status == "complete" && tabId == selectedId) - refreshLanguage(); -}); - -chrome.tabs.onSelectionChanged.addListener(function(tabId, props) { - selectedId = tabId; - refreshLanguage(); -}); - -chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - selectedId = tabs[0].id; - refreshLanguage(); -});
diff --git a/chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json b/chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json deleted file mode 100644 index 4b242cf..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "CLD", - "description": "Displays the language of a tab", - "version": "0.3", - "background": { - "scripts": ["background.js"] - }, - "browser_action": { - "default_name": "Page Language" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/icon.png b/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/icon.png deleted file mode 100644 index d86677db..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/manifest.json b/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/manifest.json deleted file mode 100644 index beceb33..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "Detect Language", - "description": "Detects up to 3 languages and their percentages of the provided string", - "version": "1.0", - - "browser_action": { - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - - "manifest_version": 2 -} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/popup.html b/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/popup.html deleted file mode 100644 index f017bae..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/popup.html +++ /dev/null
@@ -1,17 +0,0 @@ -<html> - <head> - <style> - body { - font-family: "Segoe UI", "Lucida Grande", Tahoma, sans-serif; - font-size: 100%; - } - </style> - <script src="popup.js"></script> - </head> - <body> - <div id="detect_lang"> - <textarea id="text" placeholder="Text to translate" style="padding: 10px; width: 300px;"></textarea> - <button id="btn-detect">Translate</button> - </div> - </body> -</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/popup.js b/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/popup.js deleted file mode 100644 index 1ce8544..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/detectLanguage/popup.js +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -document.addEventListener('DOMContentLoaded', function() { - document.getElementById("btn-detect").addEventListener("click", function() { - var inputText = document.getElementById("text").value; - chrome.i18n.detectLanguage(inputText, function(result) { - var languages = "Languages: \n"; - for (var i = 0; i < result.languages.length; i++) { - languages += result.languages[i].language + " "; - languages += result.languages[i].percentage + "\n"; - } - - var is_reliable = "\nReliable? \n" + result.isReliable + "\n"; - alert(languages + is_reliable); - }); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json deleted file mode 100644 index b33d2f0..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json +++ /dev/null
@@ -1,27 +0,0 @@ -{ - "chrome_extension_name": { - "message": "AcceptLanguage" - }, - "chrome_extension_description": { - "message": "Returns accept languages of the browser" - }, - "click_here": { - "message": "Left click to list acceptLanguages." - }, - "browser_action_title": { - "message": "Click Me" - }, - "chrome_accept_languages": { - "message": "$CHROME$ accepts $languages$ languages", - "placeholders": { - "chrome": { - "content": "Chrome", - "example": "Chrome" - }, - "languages": { - "content": "$1", - "example": "en-US,sr,de" - } - } - } -}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json deleted file mode 100644 index 0e1a7ef..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json +++ /dev/null
@@ -1,27 +0,0 @@ -{ - "chrome_extension_name": { - "message": "AcceptLanguage" - }, - "chrome_extension_description": { - "message": "Devuelve los idiomas aceptados por el navegador" - }, - "click_here": { - "message": "Click con botón izquierdo para mostrar la lista de acceptLanguages." - }, - "browser_action_title": { - "message": "Haz click aquí" - }, - "chrome_accept_languages": { - "message": "$CHROME$ acepta los idiomas $languages$", - "placeholders": { - "chrome": { - "content": "Chrome", - "example": "Chrome" - }, - "languages": { - "content": "$1", - "example": "en-US,sr,de" - } - } - } -}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json deleted file mode 100644 index 30bd958..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "chrome_extension_name": { - "message": "Прихватљиви језици" - }, - "chrome_extension_description": { - "message": "Језици које прегледач прихвата" - }, - "click_here": { - "message": "Кликните да излистате дозвољене језике." - }, - "chrome_accept_languages": { - "message": "$CHROME$ прихвата $languages$ језике.", - "placeholders": { - "chrome": { - "content": "Chrome", - "example": "Chrome" - }, - "languages": { - "content": "$1", - "example": "en-US,sr,de" - } - } - } -}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.png b/chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json deleted file mode 100644 index 52997f2..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "__MSG_chrome_extension_name__", - "description": "__MSG_chrome_extension_description__", - "version": "0.2", - "default_locale": "en_US", - "browser_action": { - "default_title": "__MSG_browser_action_title__", - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html b/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html deleted file mode 100644 index d765b9d..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!-- -Copyright (c) 2012 The Chromium Authors. All rights reserved. Use of this -source code is governed by a BSD-style license that can be found in the -LICENSE file. ---> - -<html> - <head> - <style> - body { - color: black; - width: 300px; - } - </style> - <script src="popup.js"></script> - </head> - <body> - <div id="accept_lang"> - <span id="languageSpan"></span> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.js b/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.js deleted file mode 100644 index fd70b6164..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.js +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function setChildTextNode(elementId, text) { - document.getElementById(elementId).innerText = text; -} - -function init() { - setChildTextNode('languageSpan', chrome.i18n.getMessage("click_here")); -} - -function getAcceptLanguages() { - chrome.i18n.getAcceptLanguages(function(languageList) { - var languages = languageList.join(","); - setChildTextNode('languageSpan', - chrome.i18n.getMessage("chrome_accept_languages", languages)); - }) -} - -document.addEventListener('DOMContentLoaded', function() { - document.querySelector('#accept_lang').addEventListener( - 'click', getAcceptLanguages); - init(); -});
diff --git a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/_locales/de/messages.json b/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/_locales/de/messages.json deleted file mode 100644 index 0d8e2f7..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/_locales/de/messages.json +++ /dev/null
@@ -1,8 +0,0 @@ -{ - "application_title": { - "message": "Eine lokalisierte gehostete Beispielanwendung" - }, - "application_description": { - "message": "Hier steht eine Beschreibung der Applikation, die im Web Store auftauchen wird." - } -}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/_locales/en/messages.json b/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/_locales/en/messages.json deleted file mode 100644 index ed87abf..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/_locales/en/messages.json +++ /dev/null
@@ -1,10 +0,0 @@ -{ - "application_title": { - "message": "Minimal Localized Hosted App", - "description": "The title of the application, displayed in the web store." - }, - "application_description": { - "message": "This is the minimal set of data required to upload a localized hosted application to the web store.", - "description": "The description of the application, displayed in the web store." - } -}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/icon128.png b/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/icon128.png deleted file mode 100644 index 0b36c4c..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/icon128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/manifest.json b/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/manifest.json deleted file mode 100644 index 9cb94fd..0000000 --- a/chrome/common/extensions/docs/examples/api/i18n/localizedHostedApp/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "__MSG_application_title__", - "description": "__MSG_application_description__", - "version": "0.2", - "default_locale": "en", - "app": { - "launch": { - "web_url": "http://example.com/" - } - }, - "icons": { - "128": "icon128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/background.js b/chrome/common/extensions/docs/examples/api/idle/idle_simple/background.js deleted file mode 100644 index c25e0ab3..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/background.js +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright (c) 2010 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. - -var history_log = []; - -/** -* Stores a state every time an "active" event is sent, up to 20 items. -*/ -chrome.idle.onStateChanged.addListener(function(newstate) { - var time = new Date(); - if (history_log.length >= 20) { - history_log.pop(); - } - history_log.unshift({'state':newstate, 'time':time}); -}); - -/** -* Opens history.html when the browser action is clicked. -* Used window.open because I didn't want the tabs permission. -*/ -chrome.browserAction.onClicked.addListener(function() { - window.open('history.html', 'testwindow', 'width=700,height=600'); -});
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html b/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html deleted file mode 100644 index c8061c560..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html +++ /dev/null
@@ -1,38 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. ---> -<html> - <head> - <style> - body { - width: 100%; - font: 13px Arial; - } - </style> - <script src="history.js"></script> - </head> - <body> - <h1>Idle API Demonstration</h1> - <h2>Current state</h2> - <p> - Idle threshold: - <select id="idle-threshold"> - <option selected value="15">15</option> - <option value="30">30</option> - <option value="60">60</option> - </select> - <p> - <code>chrome.idle.queryState(<strong id="idle-set-threshold"></strong>, ...);</code> - - <span id="idle-state"></span> - </p> - <p> - Last state change: <span id="idle-laststate"></span> - </p> - - <h2>Idle changes:</h2> - <ul id='idle-history'></ul> - </body> -</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.js b/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.js deleted file mode 100644 index 814c7cb..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.js +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Convert a state and time into a nice styled chunk of HTML. - */ -function renderState(state, time) { - var now = new Date().getTime(); - var diff = Math.round((time.getTime() - now) / 1000); - var str = (diff == 0) ? - "now" : - Math.abs(diff) + " seconds " + (diff > 0 ? "from now" : "ago"); - var col = (state == "active") ? - "#009900" : - "#990000"; - return "<b style='color: " + col + "'>" + state + "</b> " + str; -}; - -/** - * Creates DOM and injects a rendered state into the page. - */ -function renderItem(state, time, parent) { - var dom_item = document.createElement('li'); - dom_item.innerHTML = renderState(state, time); - parent.appendChild(dom_item); -}; - -// Store previous state so we can show deltas. This is important -// because the API currently doesn't fire idle messages, and we'd -// like to keep track of last time we went idle. -var laststate = null; -var laststatetime = null; - -/** - * Checks the current state of the browser. - */ -function checkState() { - threshold = parseInt(document.querySelector('#idle-threshold').value); - var dom_threshold = document.querySelector('#idle-set-threshold'); - dom_threshold.innerText = threshold; - - // Request the state based off of the user-supplied threshold. - chrome.idle.queryState(threshold, function(state) { - var time = new Date(); - if (laststate != state) { - laststate = state; - laststatetime = time; - } - - // Keep rendering results so we get a nice "seconds elapsed" view. - var dom_result = document.querySelector('#idle-state'); - dom_result.innerHTML = renderState(state, time); - var dom_laststate = document.querySelector('#idle-laststate'); - dom_laststate.innerHTML = renderState(laststate, laststatetime); - }); -}; - -var dom_history = document.querySelector('#idle-history'); - -/** - * Render the data gathered by the background page - should show a log - * of "active" states. No events are fired upon idle. - */ -function renderHistory() { - dom_history.innerHTML = ""; - var history_log = chrome.extension.getBackgroundPage().history_log; - for (var i = 0; i < history_log.length; i++) { - var data = history_log[i]; - renderItem(data['state'], data['time'], dom_history); - } -}; - - -document.addEventListener('DOMContentLoaded', function() { - // Check every second (even though this is overkill - minimum idle - // threshold is 15 seconds) so that the numbers appear to be counting up. - checkState(); - window.setInterval(checkState, 1000); - - // Check every second (see above). - renderHistory(); - window.setInterval(renderHistory, 1000); -});
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json b/chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json deleted file mode 100644 index b6fba2a..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "name" : "Idle - Simple Example", - "version" : "1.0.1", - "description" : "Demonstrates the Idle API", - "background" : { - "scripts": ["background.js"] - }, - "permissions" : [ "idle" ], - "browser_action" : { - "default_icon" : "sample-19.png" - }, - "icons" : { - "16" : "sample-16.png", - "48" : "sample-48.png", - "128" : "sample-128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.png deleted file mode 100644 index 96be429..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.png deleted file mode 100644 index 5308fc9..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.png deleted file mode 100644 index 108b2a7..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.png deleted file mode 100644 index a732e383..0000000 --- a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/input.ime/basic/icon.png b/chrome/common/extensions/docs/examples/api/input.ime/basic/icon.png deleted file mode 100644 index d86677db..0000000 --- a/chrome/common/extensions/docs/examples/api/input.ime/basic/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/input.ime/basic/main.js b/chrome/common/extensions/docs/examples/api/input.ime/basic/main.js deleted file mode 100644 index fdff7cef..0000000 --- a/chrome/common/extensions/docs/examples/api/input.ime/basic/main.js +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2013 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. - -var ime_api = chrome.input.ime; - -var context_id = -1; - -console.log("Initializing IME"); - -ime_api.onFocus.addListener(function(context) { - console.log('onFocus:' + context.contextID); - context_id = context.contextID; -}); -ime_api.onBlur.addListener(function(contextID) { - console.log('onBlur:' + contextID); - context_id = -1; -}); - -ime_api.onActivate.addListener(function(engineID) { - console.log('onActivate:' + engineID); -}); -ime_api.onDeactivated.addListener(function(engineID) { - console.log('onDeactivated:' + engineID); -}); - -ime_api.onKeyEvent.addListener( -function(engineID, keyData) { - console.log('onKeyEvent:' + keyData.key + " context: " + context_id); - if (keyData.type == "keydown" && keyData.key.match(/^[a-z]$/)) { - chrome.input.ime.commitText({"contextID": context_id, - "text": keyData.key.toUpperCase()}); - return true; - } - - return false -});
diff --git a/chrome/common/extensions/docs/examples/api/input.ime/basic/manifest.json b/chrome/common/extensions/docs/examples/api/input.ime/basic/manifest.json deleted file mode 100644 index b0a06d7e..0000000 --- a/chrome/common/extensions/docs/examples/api/input.ime/basic/manifest.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name": "Test IME", - "version": "1.0", - "manifest_version": 2, - "description": "A simple IME that converts all keystrokes to upper case.", - "background": { - "scripts": ["main.js"] - }, - "permissions": [ - "input" - ], - "input_components": [ - { - "name": "Test IME", - "id": "test", - "language": "en-US", // The primary language this IME is used for - "layouts": ["us::eng"] // The supported keyboard layouts for this IME - } - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png b/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png deleted file mode 100644 index 35324c5..0000000 --- a/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json b/chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json deleted file mode 100644 index 76d6907..0000000 --- a/chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "Message Timer", - "version": "1.3", - "description": "Times how long it takes to send a message to a content script and back.", - "content_scripts": [ - { - "matches": ["http://*/*", "https://*/*"], - "js": ["page.js"] - } - ], - "browser_action": { - "default_title": "Time to current page", - "default_icon": "clock.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/page.js b/chrome/common/extensions/docs/examples/api/messaging/timer/page.js deleted file mode 100644 index 29f518e1..0000000 --- a/chrome/common/extensions/docs/examples/api/messaging/timer/page.js +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright (c) 2013 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. - -chrome.runtime.onConnect.addListener(function(port) { - port.onMessage.addListener(function(msg) { - port.postMessage({counter: msg.counter+1}); - }); -}); - -chrome.runtime.onMessage.addListener( - function(request, sender, sendResponse) { - sendResponse({counter: request.counter+1}); - });
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/popup.html b/chrome/common/extensions/docs/examples/api/messaging/timer/popup.html deleted file mode 100644 index 2931321..0000000 --- a/chrome/common/extensions/docs/examples/api/messaging/timer/popup.html +++ /dev/null
@@ -1,25 +0,0 @@ -<head> -<style> -tr { - white-space: nowrap; -} -.results { - text-align: right; - min-width: 6em; - color: black; -} -</style> -<script src="popup.js"></script> -</head> -<body> -<table> - <tr> - <td><button id="testMessage">Measure sendMessage</button></td> - <td id="resultsRequest" class="results">(results)</td> - </tr> - <tr> - <td><button id="testConnect">Measure postMessage</button></td> - <td id="resultsConnect" class="results">(results)</td> - </tr> -</table> -</body>
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/popup.js b/chrome/common/extensions/docs/examples/api/messaging/timer/popup.js deleted file mode 100644 index 8f50354..0000000 --- a/chrome/common/extensions/docs/examples/api/messaging/timer/popup.js +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function setChildTextNode(elementId, text) { - document.getElementById(elementId).innerText = text; -} - -// Tests the roundtrip time of sendMessage(). -function testMessage() { - setChildTextNode("resultsRequest", "running..."); - - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - var timer = new chrome.Interval(); - timer.start(); - var tab = tabs[0]; - chrome.tabs.sendMessage(tab.id, {counter: 1}, function handler(response) { - if (response.counter < 1000) { - chrome.tabs.sendMessage(tab.id, {counter: response.counter}, handler); - } else { - timer.stop(); - var usec = Math.round(timer.microseconds() / response.counter); - setChildTextNode("resultsRequest", usec + "usec"); - } - }); - }); -} - -// Tests the roundtrip time of Port.postMessage() after opening a channel. -function testConnect() { - setChildTextNode("resultsConnect", "running..."); - - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - var timer = new chrome.Interval(); - timer.start(); - - var port = chrome.tabs.connect(tabs[0].id); - port.postMessage({counter: 1}); - port.onMessage.addListener(function getResp(response) { - if (response.counter < 1000) { - port.postMessage({counter: response.counter}); - } else { - timer.stop(); - var usec = Math.round(timer.microseconds() / response.counter); - setChildTextNode("resultsConnect", usec + "usec"); - } - }); - }); -} - -(function(){ - if (!chrome.benchmarking) { - alert("Warning: Looks like you forgot to run chrome with " + - " --enable-benchmarking set."); - return; - } - document.addEventListener('DOMContentLoaded', function() { - document.querySelector('#testMessage').addEventListener( - 'click', testMessage); - document.querySelector('#testConnect').addEventListener( - 'click', testConnect); - }); -})();
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/README.txt b/chrome/common/extensions/docs/examples/api/nativeMessaging/README.txt deleted file mode 100644 index c0269460..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/README.txt +++ /dev/null
@@ -1,26 +0,0 @@ -This directory contains an example of chrome application that uses native -messaging API that allows to communicate with a native application. - -In order for this example to work you must first install the native messaging -host from the host directory. - -To install the host: - -On Windows: - Run install_host.bat script in the host directory. - This script installs the native messaging host for the current user, by - creating a registry key - HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo - and setting its default value to the full path to - host\com.google.chrome.example.echo-win.json . - If you want to install the native messaging host for all users, change HKCU to - HKLM. - Note that you need to have python installed. - -On Mac and Linux: - Run install_host.sh script in the host directory: - host/install_host.sh - By default the host is installed only for the user who runs the script, but if - you run it with admin privileges (i.e. 'sudo host/install_host.sh'), then the - host will be installed for all users. You can later use host/uninstall_host.sh - to uninstall the host.
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/icon-128.png b/chrome/common/extensions/docs/examples/api/nativeMessaging/app/icon-128.png deleted file mode 100644 index c3bd2fd48..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/icon-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/main.html b/chrome/common/extensions/docs/examples/api/nativeMessaging/app/main.html deleted file mode 100644 index 445b876..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/main.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright 2013 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. ---> - -<html> - <head> - <script src='./main.js'></script> - </head> - <body> - <button id='connect-button'>Connect</button> - <input id='input-text' type='text' /> - <button id='send-message-button'>Send</button> - <div id='response'></div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/main.js b/chrome/common/extensions/docs/examples/api/nativeMessaging/app/main.js deleted file mode 100644 index 618268a..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/main.js +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2013 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. - -var port = null; - -var getKeys = function(obj){ - var keys = []; - for(var key in obj){ - keys.push(key); - } - return keys; -} - - -function appendMessage(text) { - document.getElementById('response').innerHTML += "<p>" + text + "</p>"; -} - -function updateUiState() { - if (port) { - document.getElementById('connect-button').style.display = 'none'; - document.getElementById('input-text').style.display = 'block'; - document.getElementById('send-message-button').style.display = 'block'; - } else { - document.getElementById('connect-button').style.display = 'block'; - document.getElementById('input-text').style.display = 'none'; - document.getElementById('send-message-button').style.display = 'none'; - } -} - -function sendNativeMessage() { - message = {"text": document.getElementById('input-text').value}; - port.postMessage(message); - appendMessage("Sent message: <b>" + JSON.stringify(message) + "</b>"); -} - -function onNativeMessage(message) { - appendMessage("Received message: <b>" + JSON.stringify(message) + "</b>"); -} - -function onDisconnected() { - appendMessage("Failed to connect: " + chrome.runtime.lastError.message); - port = null; - updateUiState(); -} - -function connect() { - var hostName = "com.google.chrome.example.echo"; - appendMessage("Connecting to native messaging host <b>" + hostName + "</b>") - port = chrome.runtime.connectNative(hostName); - port.onMessage.addListener(onNativeMessage); - port.onDisconnect.addListener(onDisconnected); - updateUiState(); -} - -document.addEventListener('DOMContentLoaded', function () { - document.getElementById('connect-button').addEventListener( - 'click', connect); - document.getElementById('send-message-button').addEventListener( - 'click', sendNativeMessage); - updateUiState(); -});
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/manifest.json b/chrome/common/extensions/docs/examples/api/nativeMessaging/app/manifest.json deleted file mode 100644 index a339e11..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/app/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - // Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik - "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB", - "name": "Native Messaging Example", - "version": "1.0", - "manifest_version": 2, - "description": "Send a message to a native application.", - "app": { - "launch": { - "local_path": "main.html" - } - }, - "icons": { - "128": "icon-128.png" - }, - "permissions": [ - "nativeMessaging" - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/com.google.chrome.example.echo-win.json b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/com.google.chrome.example.echo-win.json deleted file mode 100644 index 84e5448..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/com.google.chrome.example.echo-win.json +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2013 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. - -{ - "name": "com.google.chrome.example.echo", - "description": "Chrome Native Messaging API Example Host", - "path": "native-messaging-example-host.bat", - "type": "stdio", - "allowed_origins": [ - "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/" - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/com.google.chrome.example.echo.json b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/com.google.chrome.example.echo.json deleted file mode 100644 index dfeae04..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/com.google.chrome.example.echo.json +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2013 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. - -{ - "name": "com.google.chrome.example.echo", - "description": "Chrome Native Messaging API Example Host", - "path": "HOST_PATH", - "type": "stdio", - "allowed_origins": [ - "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/" - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/install_host.bat b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/install_host.bat deleted file mode 100755 index 8b88ab8..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/install_host.bat +++ /dev/null
@@ -1,7 +0,0 @@ -:: Copyright 2014 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. - -:: Change HKCU to HKLM if you want to install globally. -:: %~dp0 is the directory containing this bat script and ends with a backslash. -REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /ve /t REG_SZ /d "%~dp0com.google.chrome.example.echo-win.json" /f
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/install_host.sh b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/install_host.sh deleted file mode 100755 index f968c37..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/install_host.sh +++ /dev/null
@@ -1,39 +0,0 @@ -#!/bin/sh -# Copyright 2013 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. - -set -e - -DIR="$( cd "$( dirname "$0" )" && pwd )" -if [ "$(uname -s)" = "Darwin" ]; then - if [ "$(whoami)" = "root" ]; then - TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts" - else - TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts" - fi -else - if [ "$(whoami)" = "root" ]; then - TARGET_DIR="/etc/opt/chrome/native-messaging-hosts" - else - TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts" - fi -fi - -HOST_NAME=com.google.chrome.example.echo - -# Create directory to store native messaging host. -mkdir -p "$TARGET_DIR" - -# Copy native messaging host manifest. -cp "$DIR/$HOST_NAME.json" "$TARGET_DIR" - -# Update host path in the manifest. -HOST_PATH=$DIR/native-messaging-example-host -ESCAPED_HOST_PATH=${HOST_PATH////\\/} -sed -i -e "s/HOST_PATH/$ESCAPED_HOST_PATH/" "$TARGET_DIR/$HOST_NAME.json" - -# Set permissions for the manifest so that all users can read it. -chmod o+r "$TARGET_DIR/$HOST_NAME.json" - -echo "Native messaging host $HOST_NAME has been installed."
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host deleted file mode 100755 index 8c94ed8..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host +++ /dev/null
@@ -1,128 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# A simple native messaging host. Shows a Tkinter dialog with incoming messages -# that also allows to send message back to the webapp. - -import struct -import sys -import threading -import Queue - -try: - import Tkinter - import tkMessageBox -except ImportError: - Tkinter = None - -# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY -# to avoid unwanted modifications of the input/output streams. -if sys.platform == "win32": - import os, msvcrt - msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) - msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) - -# Helper function that sends a message to the webapp. -def send_message(message): - # Write message size. - sys.stdout.write(struct.pack('I', len(message))) - # Write the message itself. - sys.stdout.write(message) - sys.stdout.flush() - -# Thread that reads messages from the webapp. -def read_thread_func(queue): - message_number = 0 - while 1: - # Read the message length (first 4 bytes). - text_length_bytes = sys.stdin.read(4) - - if len(text_length_bytes) == 0: - if queue: - queue.put(None) - sys.exit(0) - - # Unpack message length as 4 byte integer. - text_length = struct.unpack('i', text_length_bytes)[0] - - # Read the text (JSON object) of the message. - text = sys.stdin.read(text_length).decode('utf-8') - - if queue: - queue.put(text) - else: - # In headless mode just send an echo message back. - send_message('{"echo": %s}' % text) - -if Tkinter: - class NativeMessagingWindow(Tkinter.Frame): - def __init__(self, queue): - self.queue = queue - - Tkinter.Frame.__init__(self) - self.pack() - - self.text = Tkinter.Text(self) - self.text.grid(row=0, column=0, padx=10, pady=10, columnspan=2) - self.text.config(state=Tkinter.DISABLED, height=10, width=40) - - self.messageContent = Tkinter.StringVar() - self.sendEntry = Tkinter.Entry(self, textvariable=self.messageContent) - self.sendEntry.grid(row=1, column=0, padx=10, pady=10) - - self.sendButton = Tkinter.Button(self, text="Send", command=self.onSend) - self.sendButton.grid(row=1, column=1, padx=10, pady=10) - - self.after(100, self.processMessages) - - def processMessages(self): - while not self.queue.empty(): - message = self.queue.get_nowait() - if message == None: - self.quit() - return - self.log("Received %s" % message) - - self.after(100, self.processMessages) - - def onSend(self): - text = '{"text": "' + self.messageContent.get() + '"}' - self.log('Sending %s' % text) - try: - send_message(text) - except IOError: - tkMessageBox.showinfo('Native Messaging Example', - 'Failed to send message.') - sys.exit(1) - - def log(self, message): - self.text.config(state=Tkinter.NORMAL) - self.text.insert(Tkinter.END, message + "\n") - self.text.config(state=Tkinter.DISABLED) - - -def Main(): - if not Tkinter: - send_message('"Tkinter python module wasn\'t found. Running in headless ' + - 'mode. Please consider installing Tkinter."') - read_thread_func(None) - sys.exit(0) - - queue = Queue.Queue() - - main_window = NativeMessagingWindow(queue) - main_window.master.title('Native Messaging Example') - - thread = threading.Thread(target=read_thread_func, args=(queue,)) - thread.daemon = True - thread.start() - - main_window.mainloop() - - sys.exit(0) - - -if __name__ == '__main__': - Main()
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host.bat b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host.bat deleted file mode 100755 index 430179e..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/native-messaging-example-host.bat +++ /dev/null
@@ -1,6 +0,0 @@ -@echo off -:: Copyright (c) 2013 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. - -python "%~dp0/native-messaging-example-host" %*
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/uninstall_host.bat b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/uninstall_host.bat deleted file mode 100755 index 5c2631f..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/uninstall_host.bat +++ /dev/null
@@ -1,7 +0,0 @@ -:: Copyright 2014 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. - -:: Deletes the entry created by install_host.bat -REG DELETE "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /f -REG DELETE "HKLM\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /f
diff --git a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/uninstall_host.sh b/chrome/common/extensions/docs/examples/api/nativeMessaging/host/uninstall_host.sh deleted file mode 100755 index bed4776..0000000 --- a/chrome/common/extensions/docs/examples/api/nativeMessaging/host/uninstall_host.sh +++ /dev/null
@@ -1,24 +0,0 @@ -#!/bin/sh -# Copyright 2013 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. - -set -e - -if [ "$(uname -s)" = "Darwin" ]; then - if [ "$(whoami)" = "root" ]; then - TARGET_DIR="/Library/Google/Chrome/NativeMessagingHosts" - else - TARGET_DIR="$HOME/Library/Application Support/Google/Chrome/NativeMessagingHosts" - fi -else - if [ "$(whoami)" = "root" ]; then - TARGET_DIR="/etc/opt/chrome/native-messaging-hosts" - else - TARGET_DIR="$HOME/.config/google-chrome/NativeMessagingHosts" - fi -fi - -HOST_NAME=com.google.chrome.example.echo -rm "$TARGET_DIR/com.google.chrome.example.echo.json" -echo "Native messaging host $HOST_NAME has been uninstalled."
diff --git a/chrome/common/extensions/docs/examples/api/notifications/128.png b/chrome/common/extensions/docs/examples/api/notifications/128.png deleted file mode 100644 index 181ee31..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/16.png b/chrome/common/extensions/docs/examples/api/notifications/16.png deleted file mode 100644 index 4f24553..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/48.png b/chrome/common/extensions/docs/examples/api/notifications/48.png deleted file mode 100644 index 2ad14f9..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/64.png b/chrome/common/extensions/docs/examples/api/notifications/64.png deleted file mode 100644 index 61ec9592..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/64.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/background.js b/chrome/common/extensions/docs/examples/api/notifications/background.js deleted file mode 100644 index cbe9d53..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/background.js +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright (c) 2011 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. - -/* - Displays a notification with the current time. Requires "notifications" - permission in the manifest file (or calling - "Notification.requestPermission" beforehand). -*/ -function show() { - var time = /(..)(:..)/.exec(new Date()); // The prettyprinted time. - var hour = time[1] % 12 || 12; // The prettyprinted hour. - var period = time[1] < 12 ? 'a.m.' : 'p.m.'; // The period of the day. - new Notification(hour + time[2] + ' ' + period, { - icon: '48.png', - body: 'Time to make the toast.' - }); -} - -// Conditionally initialize the options. -if (!localStorage.isInitialized) { - localStorage.isActivated = true; // The display activation. - localStorage.frequency = 1; // The display frequency, in minutes. - localStorage.isInitialized = true; // The option initialization. -} - -// Test for notification support. -if (window.Notification) { - // While activated, show notifications at the display frequency. - if (JSON.parse(localStorage.isActivated)) { show(); } - - var interval = 0; // The display interval, in minutes. - - setInterval(function() { - interval++; - - if ( - JSON.parse(localStorage.isActivated) && - localStorage.frequency <= interval - ) { - show(); - interval = 0; - } - }, 60000); -}
diff --git a/chrome/common/extensions/docs/examples/api/notifications/manifest.json b/chrome/common/extensions/docs/examples/api/notifications/manifest.json deleted file mode 100644 index 1f77d635..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "name": "Notification Demo", - "version": "1.1", - "description": - "Shows off desktop notifications, which are \"toast\" windows that pop up on the desktop.", - "icons": {"16": "16.png", "48": "48.png", "128": "128.png"}, - "permissions": [ - "notifications" - ], - "options_page": "options.html", - "background": { "scripts": ["background.js"] }, - "manifest_version": 2, - - // crbug.com/134315 - "web_accessible_resources": [ - "48.png" - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/notifications/options.html b/chrome/common/extensions/docs/examples/api/notifications/options.html deleted file mode 100644 index df61b379..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/options.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!-- - Copyright (c) 2012 The Chromium Authors. All rights reserved. - Use of this source code is governed by a BSD-style license that can be - found in the LICENSE file. - - Brian Kennish <bkennish@chromium.org> - - An option page for configuring notifications. ---> -<!doctype html> -<html> - <head> - <title>Notification Demo</title> - <link href="style.css" rel="stylesheet" type="text/css"> - <script src="options.js"></script> - </head> - <body> - <h1> - <img src="64.png" alt="Toast"> - Notification Demo - </h1> - <h2>Options</h2> - <form id="options"> - <input type="checkbox" name="isActivated" checked> - Display a notification every - <select name="frequency"> - <option>1</option> - <option>2</option> - <option>3</option> - <option>4</option> - <option>5</option> - <option>10</option> - <option>15</option> - <option>20</option> - <option>25</option> - <option>30</option> - </select> - minute(s). - </form> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/notifications/options.js b/chrome/common/extensions/docs/examples/api/notifications/options.js deleted file mode 100644 index 9f5e6a2..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/options.js +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright (c) 2011 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. - -/* - Grays out or [whatever the opposite of graying out is called] the option - field. -*/ -function ghost(isDeactivated) { - options.style.color = isDeactivated ? 'graytext' : 'black'; - // The label color. - options.frequency.disabled = isDeactivated; // The control manipulability. -} - -window.addEventListener('load', function() { - // Initialize the option controls. - options.isActivated.checked = JSON.parse(localStorage.isActivated); - // The display activation. - options.frequency.value = localStorage.frequency; - // The display frequency, in minutes. - - if (!options.isActivated.checked) { ghost(true); } - - // Set the display activation and frequency. - options.isActivated.onchange = function() { - localStorage.isActivated = options.isActivated.checked; - ghost(!options.isActivated.checked); - }; - - options.frequency.onchange = function() { - localStorage.frequency = options.frequency.value; - }; -});
diff --git a/chrome/common/extensions/docs/examples/api/notifications/style.css b/chrome/common/extensions/docs/examples/api/notifications/style.css deleted file mode 100644 index 7a5de73..0000000 --- a/chrome/common/extensions/docs/examples/api/notifications/style.css +++ /dev/null
@@ -1,25 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -/* Clone the look and feel of "chrome://" pages. */ -body { - margin: 10px; - font: 84% Arial, sans-serif -} - -h1 { font-size: 156% } - -h1 img { - margin: 1px 5px 0 1px; - vertical-align: middle -} - -h2 { - border-top: 1px solid #9cc2ef; - background-color: #ebeff9; - padding: 3px 5px; - font-size: 100% -}
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/background.js b/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/background.js deleted file mode 100644 index 83d69f4..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/background.js +++ /dev/null
@@ -1,11 +0,0 @@ -// 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. - -// This event is fired with the user accepts the input in the omnibox. -chrome.omnibox.onInputEntered.addListener( - function(text) { - // Encode user input for special characters , / ? : @ & = + $ # - var newURL = 'https://www.google.com/search?q=' + encodeURIComponent(text); - chrome.tabs.create({ url: newURL }); - });
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/manifest.json b/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/manifest.json deleted file mode 100644 index 5d1c2ff..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/manifest.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "name": "Omnibox New Tab Search", - "description": "Type 'nt' plus a search term into the Omnibox to open search in new tab.", - "version": "1.0", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "omnibox": { "keyword" : "nt" }, - "manifest_version": 2, - "browser_action": { - "default_icon": { - "16": "newtab_search16.png", - "32": "newtab_search32.png" - } - }, - "icons": { - "16": "newtab_search16.png", - "32": "newtab_search32.png", - "48": "newtab_search48.png", - "128": "newtab_search128.png" - } -}
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search128.png b/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search128.png deleted file mode 100644 index d4b8637..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search16.png b/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search16.png deleted file mode 100644 index 09c8ae2..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search32.png b/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search32.png deleted file mode 100644 index 17a435a..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search48.png b/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search48.png deleted file mode 100644 index 5678cec..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/newtab_search/newtab_search48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.js b/chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.js deleted file mode 100644 index 35808c9..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/simple-example/background.js +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -// This event is fired each time the user updates the text in the omnibox, -// as long as the extension's keyword mode is still active. -chrome.omnibox.onInputChanged.addListener( - function(text, suggest) { - console.log('inputChanged: ' + text); - suggest([ - {content: text + " one", description: "the first one"}, - {content: text + " number two", description: "the second entry"} - ]); - }); - -// This event is fired with the user accepts the input in the omnibox. -chrome.omnibox.onInputEntered.addListener( - function(text) { - console.log('inputEntered: ' + text); - alert('You just typed "' + text + '"'); - });
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json b/chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json deleted file mode 100644 index eafc95a..0000000 --- a/chrome/common/extensions/docs/examples/api/omnibox/simple-example/manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name": "Omnibox Example", - "description" : "To use, type 'omnix' plus a search term into the Omnibox.", - "version": "1.1", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "omnibox": { "keyword" : "omnix" }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html b/chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html deleted file mode 100644 index 87cf3ed..0000000 --- a/chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html +++ /dev/null
@@ -1,19 +0,0 @@ -<html> - <head> - <title>Blank New Tab</title> - <style> - div { - color: #cccccc; - vertical-align: 50%; - text-align: center; - font-family: sans-serif; - font-size: 300%; - } - </style> - </head> - <body> - <div style="height:40%"></div> - <div>Blank New Tab™</div> - </body> -</html> -
diff --git a/chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json b/chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json deleted file mode 100644 index 9efcc231..0000000 --- a/chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json +++ /dev/null
@@ -1,10 +0,0 @@ -{ - "name": "Blank new tab page", - "description": "Override the new tab page with a blank one", - "version": "0.2", - "incognito": "split", - "chrome_url_overrides": { - "newtab": "blank.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json b/chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json deleted file mode 100644 index 927faa3..0000000 --- a/chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json +++ /dev/null
@@ -1,9 +0,0 @@ -{ - "name": "iGoogle new tab page", - "description": "Override the new tab page with iGoogle", - "version": "0.2", - "chrome_url_overrides": { - "newtab": "redirect.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html b/chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html deleted file mode 100644 index 35117f48..0000000 --- a/chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html +++ /dev/null
@@ -1,3 +0,0 @@ -<head> -<meta http-equiv="refresh"content="0;URL=http://www.google.com/ig"> -</head>
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.js b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.js deleted file mode 100644 index 30005da..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.js +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Update the declarative rules on install or upgrade. -chrome.runtime.onInstalled.addListener(function() { - chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { - chrome.declarativeContent.onPageChanged.addRules([{ - conditions: [ - // When a page contains a <video> tag... - new chrome.declarativeContent.PageStateMatcher({ - css: ["video"] - }) - ], - // ... show the page action. - actions: [new chrome.declarativeContent.ShowPageAction() ] - }]); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json deleted file mode 100644 index 79134a72..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name" : "Page action by content", - "version" : "1.1", - "description" : "Shows a page action for HTML pages containing a video", - "background" : { - "scripts": ["background.js"], - "persistent": false - }, - "page_action" : - { - "default_icon" : "video-19.png", - "default_title" : "There's a <video> in this page!" - }, - "permissions": [ "declarativeContent" ], - "icons" : { - "48" : "video-48.png", - "128" : "video-128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-128.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-128.png deleted file mode 100644 index c16dea2..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-19.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-19.png deleted file mode 100644 index 2f5caf1..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-48.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-48.png deleted file mode 100644 index 0a06c37..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/video-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.js b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.js deleted file mode 100644 index bdc7433..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.js +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2011 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. - -// When the extension is installed or upgraded ... -chrome.runtime.onInstalled.addListener(function() { - // Replace all rules ... - chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { - // With a new rule ... - chrome.declarativeContent.onPageChanged.addRules([ - { - // That fires when a page's URL contains a 'g' ... - conditions: [ - new chrome.declarativeContent.PageStateMatcher({ - pageUrl: { urlContains: 'g' }, - }) - ], - // And shows the extension's page action. - actions: [ new chrome.declarativeContent.ShowPageAction() ] - } - ]); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.png deleted file mode 100644 index 27b35c4..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.png deleted file mode 100644 index 6dc2d13..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.png deleted file mode 100644 index 9af987c6..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json deleted file mode 100644 index 5c20902f..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "name": "Page action by URL", - "version": "1.0", - "description": "Shows a page action for urls which have the letter 'g' in them.", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "page_action" : - { - "default_icon" : "icon-19.png", - "default_title" : "There's a 'G' in this URL!" - }, - "permissions" : [ - "declarativeContent" - ], - "icons" : { - "48" : "icon-48.png", - "128" : "icon-128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html deleted file mode 100644 index 58ecd28..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html +++ /dev/null
@@ -1,8 +0,0 @@ -<html> -<head> -<script src="background.js"></script> -</head> -<body> -<canvas id="canvas" width="19" height="19"></canvas> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.js b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.js deleted file mode 100644 index f2e59ce..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.js +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var lastTabId = 0; -var tab_clicks = {}; - -chrome.tabs.onSelectionChanged.addListener(function(tabId) { - lastTabId = tabId; - chrome.pageAction.show(lastTabId); -}); - -chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - lastTabId = tabs[0].id; - chrome.pageAction.show(lastTabId); -}); - -// Called when the user clicks on the page action. -chrome.pageAction.onClicked.addListener(function(tab) { - var clicks = tab_clicks[tab.id] || 0; - chrome.pageAction.setIcon({path: "icon" + (clicks + 1) + ".png", - tabId: tab.id}); - if (clicks % 2) { - chrome.pageAction.show(tab.id); - } else { - chrome.pageAction.hide(tab.id); - setTimeout(function() { chrome.pageAction.show(tab.id); }, 200); - } - chrome.pageAction.setTitle({title: "click:" + clicks, tabId: tab.id}); - - // We only have 2 icons, but cycle through 3 icons to test the - // out-of-bounds index bug. - clicks++; - if (clicks > 3) - clicks = 0; - tab_clicks[tab.id] = clicks; -}); - -var i = 0; -window.setInterval(function() { - var clicks = tab_clicks[lastTabId] || 0; - - // Don't animate while in "click" mode. - if (clicks > 0) return; - - // Don't do anything if we don't have a tab yet. - if (lastTabId == 0) return; - - i++; - chrome.pageAction.setIcon({imageData: draw(i*2, i*4), tabId: lastTabId}); -}, 50); - -function draw(starty, startx) { - var canvas = document.getElementById('canvas'); - var context = canvas.getContext('2d'); - context.clearRect(0, 0, canvas.width, canvas.height); - context.fillStyle = "rgba(0,200,0,255)"; - context.fillRect(startx % 19, starty % 19, 8, 8); - context.fillStyle = "rgba(0,0,200,255)"; - context.fillRect((startx + 5) % 19, (starty + 5) % 19, 8, 8); - context.fillStyle = "rgba(200,0,0,255)"; - context.fillRect((startx + 10) % 19, (starty + 10) % 19, 8, 8); - return context.getImageData(0, 0, 19, 19); -}
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.png b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.png b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.png deleted file mode 100644 index da75c5f..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json deleted file mode 100644 index 115b8d0..0000000 --- a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "Animated Page Action", - "description": "This extension adds an animated browser action to the toolbar.", - "version": "1.2", - "background": { - "page": "background.html" - }, - "page_action": { - "default_title": "First icon" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/permissions/extension-questions.crx b/chrome/common/extensions/docs/examples/api/permissions/extension-questions.crx deleted file mode 100644 index 9737b18e..0000000 --- a/chrome/common/extensions/docs/examples/api/permissions/extension-questions.crx +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/images/icon.png b/chrome/common/extensions/docs/examples/api/permissions/extension-questions/images/icon.png deleted file mode 100644 index 66a3be1..0000000 --- a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/images/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/manifest.json b/chrome/common/extensions/docs/examples/api/permissions/extension-questions/manifest.json deleted file mode 100644 index 2d8647ed..0000000 --- a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "Top Chrome Extension Questions", - "version": "0.3", - "description": "Sample demonstration of the optional permissions API.", - "icons": { - "128": "images/icon.png", - "48": "images/icon.png", - "16": "images/icon.png" - }, - "browser_action": { - "default_icon": "images/icon.png", - "default_popup": "popup.html" - }, - "options_page": "options.html", - "optional_permissions": ["http://api.stackoverflow.com/"], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/options.html b/chrome/common/extensions/docs/examples/api/permissions/extension-questions/options.html deleted file mode 100644 index 7fa0aae4..0000000 --- a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/options.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<head> - <style> - #status { font-weight: bold; } - </style> -</head> -<body> - <button id="enable">Grant Permission</button> - <button id="disable">Revoke Permission</button> - <p> - Stack Overflow permission status: <span id="status"></span> - <script src="options.js"></script> - </p> -</body>
diff --git a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/options.js b/chrome/common/extensions/docs/examples/api/permissions/extension-questions/options.js deleted file mode 100644 index 9ff8f7e2..0000000 --- a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/options.js +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright (c) 2011 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. - -var PERMISSIONS = {origins: ['http://api.stackoverflow.com/']}; -var YES = 'ENABLED'; -var NO = 'DISABLED'; - -var $status = document.querySelector('#status'); -chrome.permissions.onAdded.addListener(function(permissions) { - $status.innerText = YES; -}); -chrome.permissions.onRemoved.addListener(function(permissions) { - $status.innerText = NO; -}); -chrome.permissions.contains(PERMISSIONS, function(contains) { - $status.innerText = contains ? YES : NO; -}); - -document.querySelector('button#enable').addEventListener('click', function() { - chrome.permissions.contains(PERMISSIONS, function(allowed) { - if (allowed) { - alert('You already have SO host permission!'); - } else { - chrome.permissions.request(PERMISSIONS, function(result) { - if (result) { - console.log('SO host permission granted!' + - 'Open the browser action again.'); - } - }); - } - }); -}); - -document.querySelector('button#disable').addEventListener('click', function() { - chrome.permissions.contains(PERMISSIONS, function(allowed) { - if (allowed) { - chrome.permissions.remove(PERMISSIONS, function(result) { - console.log('Revoked SO host permission.'); - }); - } else { - alert('No SO host permission found.'); - } - }); -}); -
diff --git a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/popup.html b/chrome/common/extensions/docs/examples/api/permissions/extension-questions/popup.html deleted file mode 100644 index 43fc6b0..0000000 --- a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/popup.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!doctype html> -<head> - <style> - body { width: 300px; } - </style> -</head> -<body> - <h3 id="title"></h3> - <ul id="results"></ul> - <script src="popup.js"></script> -</body>
diff --git a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/popup.js b/chrome/common/extensions/docs/examples/api/permissions/extension-questions/popup.js deleted file mode 100644 index 46c74d9..0000000 --- a/chrome/common/extensions/docs/examples/api/permissions/extension-questions/popup.js +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright (c) 2011 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. - -var PERMISSIONS = {origins: ['http://api.stackoverflow.com/']}; -var URL = 'http://api.stackoverflow.com/1.1/questions?max=10&sort=votes&tagged=google-chrome-extension'; -var ROOT = 'http://stackoverflow.com'; - -chrome.permissions.contains(PERMISSIONS, function(result) { - if (!result) { - // Open options page to request permissions. - document.querySelector('#title').innerText = - 'Requires Stack Overflow permission'; - chrome.tabs.create({url: 'options.html'}); - } else { - // Make the request to SO. - makeRequest(function(data) { - // Render the results. - renderQuestions(JSON.parse(data)); - }); - } -}); - -function makeRequest(callback) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', URL); - xhr.addEventListener('load', function(e) { - var result = xhr.responseText; - callback(result); - }); - xhr.send(); -} - -function renderQuestions(data) { - var $results = document.querySelector('#results'); - var questions = data.questions; - for (var i = 0; i < Math.min(10, questions.length); i++) { - var question = questions[i]; - var $question = document.createElement('li'); - var url = ROOT + question.question_answers_url; - $question.innerHTML = '<a href="' + url + '" target="_blank">' + - question.title + '</a>'; - results.appendChild($question); - } - // Update title too. - document.querySelector('#title').innerText = 'Top Chrome Extension Questions'; -}
diff --git a/chrome/common/extensions/docs/examples/api/power/_locales/en/messages.json b/chrome/common/extensions/docs/examples/api/power/_locales/en/messages.json deleted file mode 100644 index ef50944..0000000 --- a/chrome/common/extensions/docs/examples/api/power/_locales/en/messages.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "extensionName": { - "message": "Keep Awake", - "description": "Extension name." - }, - "extensionDescription": { - "message": "Override system power-saving settings.", - "description": "Extension description." - }, - "disabledTitle": { - "message": "Default power-saving settings", - "description": "Browser action title when disabled." - }, - "displayTitle": { - "message": "Screen will be kept on", - "description": "Browser action title when preventing screen-off." - }, - "systemTitle": { - "message": "System will stay awake", - "description": "Browser action title when preventing system sleep." - } -}
diff --git a/chrome/common/extensions/docs/examples/api/power/background.js b/chrome/common/extensions/docs/examples/api/power/background.js deleted file mode 100644 index 5fd9083..0000000 --- a/chrome/common/extensions/docs/examples/api/power/background.js +++ /dev/null
@@ -1,101 +0,0 @@ -// Copyright (c) 2013 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. - -/** - * States that the extension can be in. - */ -var StateEnum = { - DISABLED: 'disabled', - DISPLAY: 'display', - SYSTEM: 'system' -}; - -/** - * Key used for storing the current state in {localStorage}. - */ -var STATE_KEY = 'state'; - -/** - * Loads the locally-saved state asynchronously. - * @param {function} callback Callback invoked with the loaded {StateEnum}. - */ -function loadSavedState(callback) { - chrome.storage.local.get(STATE_KEY, function(items) { - var savedState = items[STATE_KEY]; - for (var key in StateEnum) { - if (savedState == StateEnum[key]) { - callback(savedState); - return; - } - } - callback(StateEnum.DISABLED); - }); -} - -/** - * Switches to a new state. - * @param {string} newState New {StateEnum} to use. - */ -function setState(newState) { - var imagePrefix = 'night'; - var title = ''; - - switch (newState) { - case StateEnum.DISABLED: - chrome.power.releaseKeepAwake(); - imagePrefix = 'night'; - title = chrome.i18n.getMessage('disabledTitle'); - break; - case StateEnum.DISPLAY: - chrome.power.requestKeepAwake('display'); - imagePrefix = 'day'; - title = chrome.i18n.getMessage('displayTitle'); - break; - case StateEnum.SYSTEM: - chrome.power.requestKeepAwake('system'); - imagePrefix = 'sunset'; - title = chrome.i18n.getMessage('systemTitle'); - break; - default: - throw 'Invalid state "' + newState + '"'; - } - - var items = {}; - items[STATE_KEY] = newState; - chrome.storage.local.set(items); - - chrome.browserAction.setIcon({ - path: { - '19': 'images/' + imagePrefix + '-19.png', - '38': 'images/' + imagePrefix + '-38.png' - } - }); - chrome.browserAction.setTitle({title: title}); -} - -chrome.browserAction.onClicked.addListener(function() { - loadSavedState(function(state) { - switch (state) { - case StateEnum.DISABLED: - setState(StateEnum.DISPLAY); - break; - case StateEnum.DISPLAY: - setState(StateEnum.SYSTEM); - break; - case StateEnum.SYSTEM: - setState(StateEnum.DISABLED); - break; - default: - throw 'Invalid state "' + state + '"'; - } - }); -}); - -chrome.runtime.onStartup.addListener(function() { - loadSavedState(function(state) { setState(state); }); -}); - -chrome.runtime.onInstalled.addListener(function(details) { - loadSavedState(function(state) { setState(state); }); -});
diff --git a/chrome/common/extensions/docs/examples/api/power/images/day-19.png b/chrome/common/extensions/docs/examples/api/power/images/day-19.png deleted file mode 100644 index 09d2305..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/day-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/day-38.png b/chrome/common/extensions/docs/examples/api/power/images/day-38.png deleted file mode 100644 index ec5eec9b..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/day-38.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/icon-128.png b/chrome/common/extensions/docs/examples/api/power/images/icon-128.png deleted file mode 100644 index ec35e41..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/icon-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/icon-16.png b/chrome/common/extensions/docs/examples/api/power/images/icon-16.png deleted file mode 100644 index 0755f7c..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/icon-16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/icon-48.png b/chrome/common/extensions/docs/examples/api/power/images/icon-48.png deleted file mode 100644 index 272390d5..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/icon-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/night-19.png b/chrome/common/extensions/docs/examples/api/power/images/night-19.png deleted file mode 100644 index 949b2d65..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/night-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/night-38.png b/chrome/common/extensions/docs/examples/api/power/images/night-38.png deleted file mode 100644 index b891f77..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/night-38.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/sunset-19.png b/chrome/common/extensions/docs/examples/api/power/images/sunset-19.png deleted file mode 100644 index ce5af806..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/sunset-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/images/sunset-38.png b/chrome/common/extensions/docs/examples/api/power/images/sunset-38.png deleted file mode 100644 index 3510341..0000000 --- a/chrome/common/extensions/docs/examples/api/power/images/sunset-38.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/power/manifest.json b/chrome/common/extensions/docs/examples/api/power/manifest.json deleted file mode 100644 index dd90842..0000000 --- a/chrome/common/extensions/docs/examples/api/power/manifest.json +++ /dev/null
@@ -1,30 +0,0 @@ -{ - "manifest_version": 2, - - "name": "__MSG_extensionName__", - "description": "__MSG_extensionDescription__", - "version": "1.9", - "icons": { - "16": "images/icon-16.png", - "48": "images/icon-48.png", - "128": "images/icon-128.png" - }, - - "permissions": [ - "power", - "storage" - ], - "browser_action": { - "default_title": "__MSG_disabledTitle__", - "default_icon": { - "19": "images/night-19.png", - "38": "images/night-38.png" - } - }, - "background": { - "scripts": ["background.js"], - "persistent": false - }, - - "default_locale": "en" -}
diff --git a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/advicedog.jpg b/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/advicedog.jpg deleted file mode 100644 index 9274fbd..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/advicedog.jpg +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/manifest.json b/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/manifest.json deleted file mode 100644 index 2511406..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name" : "Block/allow third-party cookies API example extension", - "version" : "0.1", - "description" : "Sample extension which demonstrates how to access a preference.", - "permissions": [ "privacy" ], - "browser_action": { - "default_icon": "advicedog.jpg", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.css b/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.css deleted file mode 100644 index 3e715ba..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.css +++ /dev/null
@@ -1,13 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -#container { - width: 300px; -} - -#incognito { - display: none; -}
diff --git a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.html b/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.html deleted file mode 100644 index 37dccec..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <link href="popup.css" rel="stylesheet" type="text/css"> - <script src="popup.js"></script> -</head> -<body> - -<div id="container"> - <input type="checkbox" id="regularValue" /> - Allow third-party sites to set cookies - <div id="incognito"> - <input type="checkbox" id="useSeparateIncognitoSettings" /> - Use separate setting for incognito mode: - <br> - <input type="checkbox" id="incognitoValue" disabled="disabled"/> - Allow third-party sites to set cookies in incognito sessions - </div> - <div id="incognito-forbidden"> - Select "Allow in incognito" to access incognito preferences - </div> -</div> - -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.js b/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.js deleted file mode 100644 index ce25b113..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/allowThirdPartyCookies/popup.js +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -var pref = chrome.privacy.websites.thirdPartyCookiesAllowed; - -function $(id) { - return document.getElementById(id); -} - -/** - * Returns whether the |levelOfControl| means that the extension can change the - * preference value. - * - * @param levelOfControl{string} - */ -function settingIsControllable(levelOfControl) { - return (levelOfControl == 'controllable_by_this_extension' || - levelOfControl == 'controlled_by_this_extension'); -} - -/** - * Updates the UI to reflect the state of the preference. - * - * @param settings{object} A settings object, as returned from |get()| or the - * |onchange| event. - */ -function updateUI(settings) { - var disableUI = !settingIsControllable(settings.levelOfControl); - document.getElementById('regularValue').disabled = disableUI; - document.getElementById('useSeparateIncognitoSettings').disabled = disableUI; - if (settings.hasOwnProperty('incognitoSpecific')) { - var hasIncognitoValue = settings.incognitoSpecific; - document.getElementById('useSeparateIncognitoSettings').checked = - hasIncognitoValue; - document.getElementById('incognitoValue').disabled = - disableUI || !hasIncognitoValue; - document.getElementById('incognitoValue').checked = settings.value; - } else { - document.getElementById('regularValue').checked = settings.value; - } -} - -/** - * Wrapper for |updateUI| which is used as callback for the |get()| method and - * which logs the result. - * If there was an error getting the preference, does nothing. - * - * @param settings{object} A settings object, as returned from |get()|. - */ -function updateUIFromGet(settings) { - if (settings) { - console.log('pref.get result:' + JSON.stringify(settings)); - updateUI(settings); - } -} - -/** - * Wrapper for |updateUI| which is used as handler for the |onchange| event - * and which logs the result. - * - * @param settings{object} A settings object, as returned from the |onchange| - * event. - */ -function updateUIFromOnChange(settings) { - console.log('pref.onChange event:' + JSON.stringify(settings)); - updateUI(settings); -} - -/* - * Initializes the UI. - */ -function init() { - chrome.extension.isAllowedIncognitoAccess(function(allowed) { - if (allowed) { - pref.get({'incognito': true}, updateUIFromGet); - $('incognito').style.display = 'block'; - $('incognito-forbidden').style.display = 'none'; - } - }); - pref.get({}, updateUIFromGet); - pref.onChange.addListener(updateUIFromOnChange); - - $('regularValue').addEventListener('click', function () { - setPrefValue(this.checked, false); - }); - $('useSeparateIncognitoSettings').addEventListener('click', function () { - setUseSeparateIncognitoSettings(this.checked); - }); - $('incognitoValue').addEventListener('click', function () { - setPrefValue(this.checked, true); - }); -} - -/** - * Called from the UI to change the preference value. - * - * @param enabled{boolean} The new preference value. - * @param incognito{boolean} Whether the value is specific to incognito mode. - */ -function setPrefValue(enabled, incognito) { - var scope = incognito ? 'incognito_session_only' : 'regular'; - pref.set({'value': enabled, 'scope': scope}); -} - -/** - * Called from the UI to change whether to use separate settings for - * incognito mode. - * - * @param value{boolean} whether to use separate settings for - * incognito mode. - */ -function setUseSeparateIncognitoSettings(value) { - if (!value) { - pref.clear({'incognito': true}); - } else { - // Explicitly set the value for incognito mode. - pref.get({'incognito': true}, function(settings) { - pref.set({'incognito': true, 'value': settings.value}); - }); - } - document.getElementById('incognitoValue').disabled = !value; -} - -// Call `init` to kick things off. -document.addEventListener('DOMContentLoaded', init);
diff --git a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/advicedog.jpg b/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/advicedog.jpg deleted file mode 100644 index 9274fbd..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/advicedog.jpg +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/manifest.json b/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/manifest.json deleted file mode 100644 index c72e895..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name" : "Block/allow referrer API example extension", - "version" : "0.1", - "description" : "Sample extension which demonstrates how to access a preference.", - "permissions": [ "privacy" ], - "browser_action": { - "default_icon": "advicedog.jpg", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.css b/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.css deleted file mode 100644 index 3e715ba..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.css +++ /dev/null
@@ -1,13 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -#container { - width: 300px; -} - -#incognito { - display: none; -}
diff --git a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.html b/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.html deleted file mode 100644 index 7f94699c..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <link href="popup.css" rel="stylesheet" type="text/css"> - <script src="popup.js"></script> -</head> -<body> - -<div id="container"> - <input type="checkbox" id="regularValue" /> - Enable referrers - <div id="incognito"> - <input type="checkbox" id="useSeparateIncognitoSettings" /> - Use separate setting for incognito mode: - <br> - <input type="checkbox" id="incognitoValue" disabled="disabled"/> - Enable referrers in incognito sessions - </div> - <div id="incognito-forbidden"> - Select "Allow in incognito" to access incognito preferences - </div> -</div> - -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.js b/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.js deleted file mode 100644 index 72bb9e4..0000000 --- a/chrome/common/extensions/docs/examples/api/preferences/enableReferrer/popup.js +++ /dev/null
@@ -1,127 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -var pref = chrome.privacy.websites.referrersEnabled; - -function $(id) { - return document.getElementById(id); -} - -/** - * Returns whether the |levelOfControl| means that the extension can change the - * preference value. - * - * @param levelOfControl{string} - */ -function settingIsControllable(levelOfControl) { - return (levelOfControl == 'controllable_by_this_extension' || - levelOfControl == 'controlled_by_this_extension'); -} - -/** - * Updates the UI to reflect the state of the preference. - * - * @param settings{object} A settings object, as returned from |get()| or the - * |onchange| event. - */ -function updateUI(settings) { - var disableUI = !settingIsControllable(settings.levelOfControl); - document.getElementById('regularValue').disabled = disableUI; - document.getElementById('useSeparateIncognitoSettings').disabled = disableUI; - if (settings.hasOwnProperty('incognitoSpecific')) { - var hasIncognitoValue = settings.incognitoSpecific; - document.getElementById('useSeparateIncognitoSettings').checked = - hasIncognitoValue; - document.getElementById('incognitoValue').disabled = - disableUI || !hasIncognitoValue; - document.getElementById('incognitoValue').checked = settings.value; - } else { - document.getElementById('regularValue').checked = settings.value; - } -} - -/** - * Wrapper for |updateUI| which is used as callback for the |get()| method and - * which logs the result. - * If there was an error getting the preference, does nothing. - * - * @param settings{object} A settings object, as returned from |get()|. - */ -function updateUIFromGet(settings) { - if (settings) { - console.log('pref.get result:' + JSON.stringify(settings)); - updateUI(settings); - } -} - -/** - * Wrapper for |updateUI| which is used as handler for the |onchange| event - * and which logs the result. - * - * @param settings{object} A settings object, as returned from the |onchange| - * event. - */ -function updateUIFromOnChange(settings) { - console.log('pref.onChange event:' + JSON.stringify(settings)); - updateUI(settings); -} - -/* - * Initializes the UI. - */ -function init() { - chrome.extension.isAllowedIncognitoAccess(function(allowed) { - if (allowed) { - pref.get({'incognito': true}, updateUIFromGet); - $('incognito').style.display = 'block'; - $('incognito-forbidden').style.display = 'none'; - } - }); - pref.get({}, updateUIFromGet); - pref.onChange.addListener(updateUIFromOnChange); - - $('regularValue').addEventListener('click', function () { - setPrefValue(this.checked, false); - }); - $('useSeparateIncognitoSettings').addEventListener('click', function () { - setUseSeparateIncognitoSettings(this.checked); - }); - $('incognitoValue').addEventListener('click', function () { - setPrefValue(this.checked, true); - }); -} - -/** - * Called from the UI to change the preference value. - * - * @param enabled{boolean} The new preference value. - * @param incognito{boolean} Whether the value is specific to incognito mode. - */ -function setPrefValue(enabled, incognito) { - var scope = incognito ? 'incognito_session_only' : 'regular'; - pref.set({'value': enabled, 'scope': scope}); -} - -/** - * Called from the UI to change whether to use separate settings for - * incognito mode. - * - * @param value{boolean} whether to use separate settings for - * incognito mode. - */ -function setUseSeparateIncognitoSettings(value) { - if (!value) { - pref.clear({'incognito': true}); - } else { - // Explicitly set the value for incognito mode. - pref.get({'incognito': true}, function(settings) { - pref.set({'incognito': true, 'value': settings.value}); - }); - } - document.getElementById('incognitoValue').disabled = !value; -} - -// Call `init` to kick things off. -document.addEventListener('DOMContentLoaded', init);
diff --git a/chrome/common/extensions/docs/examples/api/printing/icons/icon.png b/chrome/common/extensions/docs/examples/api/printing/icons/icon.png deleted file mode 100644 index 19057a5f..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/icons/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/printing/icons/icon128.png b/chrome/common/extensions/docs/examples/api/printing/icons/icon128.png deleted file mode 100644 index 13a19d6d..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/icons/icon128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/printing/icons/icon16.png b/chrome/common/extensions/docs/examples/api/printing/icons/icon16.png deleted file mode 100644 index 7591630c..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/icons/icon16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/printing/icons/icon48.png b/chrome/common/extensions/docs/examples/api/printing/icons/icon48.png deleted file mode 100644 index f51b2ff24..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/icons/icon48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/printing/manifest.json b/chrome/common/extensions/docs/examples/api/printing/manifest.json deleted file mode 100644 index e47664fe..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "name": "Print Extension", - "version": "1.0", - "description": "Sends print job directly to the printers installed on the Chromebook", - "permissions": [ - "printing" - ], - "browser_action": { - "default_popup": "printers.html", - "default_icon": "icons/icon.png" - }, - "icons": { - "16": "icons/icon16.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/printing/printers.css b/chrome/common/extensions/docs/examples/api/printing/printers.css deleted file mode 100644 index e97ffda6..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/printers.css +++ /dev/null
@@ -1,18 +0,0 @@ -/** - * Copyright 2020 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. - */ - -table, th, td, tr { - border: 1px solid black; -} - -table { - width: 100%; - border-collapse: collapse; -} - -div { - overflow: auto; -}
diff --git a/chrome/common/extensions/docs/examples/api/printing/printers.html b/chrome/common/extensions/docs/examples/api/printing/printers.html deleted file mode 100644 index 3654aff2..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/printers.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!-- - * Copyright 2020 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. ---> -<!DOCTYPE HTML> -<html> - <head> - <title>Printers</title> - <link href="printers.css" rel="stylesheet" type="text/css"> - <script src="printers.js"></script> - </head> - - <body> - <h2>Printers:</h2> - <div id="printers"> - <table id="printersTable"> - <thead> - <tr> - <th>Id</th> - <th>Name</th> - <th>Description</th> - <th>URI</th> - <th>Source</th> - <th>Default</th> - <th>Recently used</th> - <th>Capabilities</th> - <th>Status</th> - <th>Print</th> - </tr> - </thead> - </table> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/printing/printers.js b/chrome/common/extensions/docs/examples/api/printing/printers.js deleted file mode 100644 index 2462665..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/printers.js +++ /dev/null
@@ -1,99 +0,0 @@ -// Copyright 2020 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. - -function onPrintButtonClicked(printerId, dpi) { - var ticket = { - version: '1.0', - print: { - color: {type: 'STANDARD_MONOCHROME'}, - duplex: {type: 'NO_DUPLEX'}, - page_orientation: {type: 'LANDSCAPE'}, - copies: {copies: 1}, - dpi: {horizontal_dpi: dpi.horizontal_dpi, vertical_dpi: dpi.vertical_dpi}, - media_size: { - width_microns: 210000, - height_microns: 297000, - vendor_id: 'iso_a4_210x297mm' - }, - collate: {collate: false} - } - }; - - fetch('test.pdf') - .then(response => response.arrayBuffer()) - .then(arrayBuffer => { - const request = { - job: { - printerId: printerId, - title: 'test job', - ticket: ticket, - contentType: 'application/pdf', - document: new Blob( - [new Uint8Array(arrayBuffer)], {type: 'application/pdf'}) - } - }; - chrome.printing.submitJob(request, (response) => { - if (response !== undefined) { - console.log(response.status); - } - if (chrome.runtime.lastError !== undefined) { - console.log(chrome.runtime.lastError.message); - } - }); - }); -} - -function createPrintButton(onClicked) { - const button = document.createElement('button'); - button.innerHTML = 'Print'; - button.onclick = onClicked; - return button; -} - -function createPrintersTable() { - chrome.printing.getPrinters(function(printers) { - const tbody = document.createElement('tbody'); - - for (let i = 0; i < printers.length; ++i) { - const printer = printers[i]; - chrome.printing.getPrinterInfo(printer.id, function(response) { - const columnValues = [ - printer.id, - printer.name, - printer.description, - printer.uri, - printer.source, - printer.isDefault, - printer.recentlyUsedRank, - JSON.stringify(response.capabilities), - response.status, - ]; - - let tr = document.createElement('tr'); - for (const columnValue of columnValues) { - const td = document.createElement('td'); - td.appendChild(document.createTextNode(columnValue)); - td.setAttribute('align', 'center'); - tr.appendChild(td); - } - - const printTd = document.createElement('td'); - printTd.appendChild(createPrintButton(function() { - onPrintButtonClicked( - printer.id, response.capabilities.printer.dpi.option[0]); - })); - tr.appendChild(printTd); - - tbody.appendChild(tr); - }); - } - - const table = document.getElementById('printersTable'); - table.appendChild(tbody); - }); -} - -document.addEventListener('DOMContentLoaded', function() { - createPrintersTable(); -});
diff --git a/chrome/common/extensions/docs/examples/api/printing/test.pdf b/chrome/common/extensions/docs/examples/api/printing/test.pdf deleted file mode 100644 index 7bad251b..0000000 --- a/chrome/common/extensions/docs/examples/api/printing/test.pdf +++ /dev/null
@@ -1,50 +0,0 @@ -%PDF-1.7 -% ò¤ô -1 0 obj << - /Type /Catalog - /Pages 2 0 R ->> -endobj -2 0 obj << - /Type /Pages - /MediaBox [ 0 0 200 300 ] - /Count 1 - /Kids [ 3 0 R ] ->> -endobj -3 0 obj << - /Type /Page - /Parent 2 0 R - /Contents 4 0 R ->> -endobj -4 0 obj << ->> -stream -q -0 0 0 rg -0 290 10 10 re B* -10 150 50 30 re B* -0 0 1 rg -190 290 10 10 re B* -70 232 50 30 re B* -0 1 0 rg -190 0 10 10 re B* -130 150 50 30 re B* -1 0 0 rg -0 0 10 10 re B* -70 67 50 30 re B* -Q -endstream -endobj -xref -0 5 -0000000000 65535 f -0000000015 00000 n -0000000068 00000 n -0000000161 00000 n -0000000230 00000 n -trailer<< /Root 1 0 R /Size 5 >> -startxref -456 -%%EOF
diff --git a/chrome/common/extensions/docs/examples/api/printingMetrics/background.js b/chrome/common/extensions/docs/examples/api/printingMetrics/background.js deleted file mode 100644 index 283a841..0000000 --- a/chrome/common/extensions/docs/examples/api/printingMetrics/background.js +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2019 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. - -chrome.printingMetrics.onPrintJobFinished.addListener(function(printJob) { - chrome.storage.local.get('printJobs', function(result) { - let printJobs = result.printJobs || 0; - printJobs++; - chrome.browserAction.setBadgeText({text: printJobs.toString()}); - chrome.storage.local.set({printJobs: printJobs}); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/printingMetrics/manifest.json b/chrome/common/extensions/docs/examples/api/printingMetrics/manifest.json deleted file mode 100644 index 8890532..0000000 --- a/chrome/common/extensions/docs/examples/api/printingMetrics/manifest.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name": "Print Job History", - "version": "1.0", - "description": "Reads your print history and displays the recent print jobs.", - "permissions": [ - "printingMetrics", - "storage" - ], - "browser_action": { - "default_popup": "print_jobs.html", - "default_icon": "print.png" - }, - "background": { - "scripts": [ - "background.js" - ], - "persistent": false - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/printingMetrics/print.png b/chrome/common/extensions/docs/examples/api/printingMetrics/print.png deleted file mode 100644 index 19057a5f..0000000 --- a/chrome/common/extensions/docs/examples/api/printingMetrics/print.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.css b/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.css deleted file mode 100644 index fb9e350..0000000 --- a/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.css +++ /dev/null
@@ -1,18 +0,0 @@ -/** - * Copyright 2019 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. - */ - -table, th, td, tr { - border: 1px solid black; -} - -table { - width: 100%; - border-collapse: collapse; -} - -div { - overflow: auto; -}
diff --git a/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.html b/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.html deleted file mode 100644 index 6341d68..0000000 --- a/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!-- - * Copyright 2019 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. ---> -<!DOCTYPE HTML> -<html> - <head> - <title>Recent print jobs</title> - <link href="print_jobs.css" rel="stylesheet" type="text/css"> - <script src="print_jobs.js"></script> - </head> - - <body> - <h2>Recent print jobs:</h2> - <div id="printJobs"> - <table id="printJobsTable"> - <thead> - <tr> - <th rowspan="2">Title</th> - <th rowspan="2">Status</th> - <th rowspan="2">Time</th> - <th rowspan="2">Number of pages</th> - <th colspan="3">Printer</th> - <th colspan="5">Settings</th> - </tr> - <tr> - <th>Name</th> - <th>URI</th> - <th>Source</th> - <th>Color</th> - <th>Duplex</th> - <th>Paper width</th> - <th>Paper height</th> - <th>Copies</th> - </tr> - </thead> - </table> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.js b/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.js deleted file mode 100644 index dee293a..0000000 --- a/chrome/common/extensions/docs/examples/api/printingMetrics/print_jobs.js +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2019 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. - -function showPrintJobTable() { - chrome.printingMetrics.getPrintJobs(function(printJobs) { - const tbody = document.createElement('tbody'); - - for (let i = 0; i < printJobs.length; ++i) { - const columnValues = [ - printJobs[i].title, printJobs[i].status, - new Date(printJobs[i].completionTime), printJobs[i].numberOfPages, - printJobs[i].printer.name, printJobs[i].printer.uri, - printJobs[i].printer.source, printJobs[i].settings.color, - printJobs[i].settings.duplex, printJobs[i].settings.mediaSize.width, - printJobs[i].settings.mediaSize.height, printJobs[i].settings.copies - ]; - - let tr = document.createElement('tr'); - for (columnValue of columnValues) { - const td = document.createElement('td'); - td.appendChild(document.createTextNode(columnValue)); - td.setAttribute('align', 'center'); - tr.appendChild(td); - } - tbody.appendChild(tr); - } - - const table = document.getElementById('printJobsTable'); - table.appendChild(tbody); - }); -} - -document.addEventListener('DOMContentLoaded', function() { - showPrintJobTable(); -});
diff --git a/chrome/common/extensions/docs/examples/api/processes/process_monitor/icon.png b/chrome/common/extensions/docs/examples/api/processes/process_monitor/icon.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/process_monitor/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/processes/process_monitor/manifest.json b/chrome/common/extensions/docs/examples/api/processes/process_monitor/manifest.json deleted file mode 100644 index 2c1836a..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/process_monitor/manifest.json +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "name": "Process Monitor", - "version": "1.2", - "description": "Adds a browser action that monitors resource usage of all browser processes.", - "permissions": [ - "processes" - ], - "browser_action": { - "default_title": "Process Monitor", - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/processes/process_monitor/popup.html b/chrome/common/extensions/docs/examples/api/processes/process_monitor/popup.html deleted file mode 100644 index 27caa29..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/process_monitor/popup.html +++ /dev/null
@@ -1,33 +0,0 @@ -<html> -<head> -<script src="popup.js"></script> -<style> -body { - overflow: hidden; - margin: 0px; - padding: 0px; - background: white; -} - -div:first-child { - margin-top: 0px; -} - -div, td { - padding: 1px 3px; - font-family: sans-serif; - font-size: 10pt; - margin-top: 1px; - white-space: nowrap; -} -</style> -</head> -<body> -<div id="title"><b>Process Monitor</b></div> -<div id="process-list"><i>Loading...</i></div> -<div id="buttons"> - <input type="button" value="End Process" id="killProcess" /> -</div> -</div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/processes/process_monitor/popup.js b/chrome/common/extensions/docs/examples/api/processes/process_monitor/popup.js deleted file mode 100644 index 8e4d46b2..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/process_monitor/popup.js +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Shows an updating list of process statistics. -function init() { - chrome.processes.onUpdatedWithMemory.addListener( - function(processes) { - var table = "<table>\n" + - "<tr><td><b>Process</b></td>" + - "<td>OS ID</td>" + - "<td>Title</td>" + - "<td>Type</td>" + - "<td>Tabs</td>" + - "<td>CPU</td>" + - "<td>Network</td>" + - "<td>Private Memory</td>" + - "<td>JS Memory</td>" + - "<td></td>" + - "</tr>\n"; - for (pid in processes) { - table = displayProcessInfo(processes[pid], table); - } - table += "</table>\n"; - var div = document.getElementById("process-list"); - div.innerHTML = table; - }); - - document.getElementById("killProcess").onclick = function () { - var procId = parseInt(prompt("Enter process ID")); - chrome.processes.terminate(procId); - } -} - -function displayProcessInfo(process, table) { - // Format network string like task manager - var network = process.network; - if (network > 1024) { - network = (network / 1024).toFixed(1) + " kB/s"; - } else if (network > 0) { - network += " B/s"; - } else if (network == -1) { - network = "N/A"; - } - - table += - "<tr><td>" + process.id + "</td>" + - "<td>" + process.osProcessId + "</td>" + - "<td>" + process.title + "</td>" + - "<td>" + process.type + "</td>" + - "<td>" + process.tabs + "</td>" + - "<td>" + process.cpu + "</td>" + - "<td>" + network + "</td>"; - - if ("privateMemory" in process) { - table += "<td>" + (process.privateMemory / 1024) + "K</td>"; - } else { - table += "<td>N/A</td>"; - } - if ("jsMemoryAllocated" in process) { - var allocated = process.jsMemoryAllocated / 1024; - var used = process.jsMemoryUsed / 1024; - table += "<td>" + allocated.toFixed(2) + "K (" + used.toFixed(2) + - "K live)</td>"; - } else { - table += "<td>N/A</td>"; - } - - table += - "<td></td>" + - "</tr>\n"; - return table; -} - -document.addEventListener('DOMContentLoaded', init);
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.png b/chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json b/chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json deleted file mode 100644 index bdbdb1e..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "name": "Show Tabs in Process", - "version": "1.0", - "description": "Adds a browser action showing which tabs share the current tab's process.", - "permissions": [ - "processes", "tabs", "chrome://favicon/*" - ], - "browser_action": { - "default_title": "Show Tabs in this Process", - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.css b/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.css deleted file mode 100644 index 31e15e18..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.css +++ /dev/null
@@ -1,25 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -body { - overflow: hidden; - margin: 0px; - padding: 0px; - background: white; - width: 400px; -} - -div:first-child { - margin-top: 0px; -} - -div { - padding: 1px 3px; - font-family: sans-serif; - font-size: 10pt; - width: 400px; - margin-top: 1px; -}
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html b/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html deleted file mode 100644 index d8133454..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Popup</title> - <link href="popup.css" rel="stylesheet" type="text/css"> - <script src="popup.js"></script> - </head> - <body> - <div id="title"></div> - <div id="tab-list"></div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.js b/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.js deleted file mode 100644 index 429d226..0000000 --- a/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.js +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright (c) 2011 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. - -// Show a list of all tabs in the same process as this one. -function init() { - chrome.windows.getCurrent({populate: true}, function(currentWindow) { - chrome.tabs.query({currentWindow: true, active: true}, function(tabs) { - var current = currentWindow.tabs.filter(function(tab) { - return tab.active; - })[0]; - chrome.processes.getProcessIdForTab(current.id, - function(pid) { - var outputDiv = document.getElementById("tab-list"); - var titleDiv = document.getElementById("title"); - titleDiv.innerHTML = "<b>Tabs in Process " + pid + ":</b>"; - displayTabInfo(currentWindow.id, current, outputDiv); - displaySameProcessTabs(current, pid, outputDiv); - } - ); - - }); - }); -} - -function displaySameProcessTabs(selectedTab, processId, outputDiv) { - // Loop over all windows and their tabs - var tabs = []; - chrome.windows.getAll({ populate: true }, function(windowList) { - for (var i = 0; i < windowList.length; i++) { - for (var j = 0; j < windowList[i].tabs.length; j++) { - var tab = windowList[i].tabs[j]; - if (tab.id != selectedTab.id) { - tabs.push(tab); - } - } - } - - // Display tab in list if it is in the same process - tabs.forEach(function(tab) { - chrome.processes.getProcessIdForTab(tab.id, - function(pid) { - if (pid == processId) { - displayTabInfo(tab.windowId, tab, outputDiv); - } - } - ); - }); - }); -} - -// Print a link to a given tab -function displayTabInfo(windowId, tab, outputDiv) { - if (tab.favIconUrl != undefined) { - outputDiv.innerHTML += "<img src='chrome://favicon/" + tab.url + "'>\n"; - } - outputDiv.innerHTML += - "<b><a href='#' onclick='showTab(window, " + windowId + ", " + tab.id + - ")'>" + tab.title + "</a></b><br>\n" + - "<i>" + tab.url + "</i><br>\n"; -} - -// Bring the selected tab to the front -function showTab(origWindow, windowId, tabId) { - // TODO: Bring the window to the front. (See http://crbug.com/31434) - //chrome.windows.update(windowId, {focused: true}); - chrome.tabs.update(tabId, { selected: true }); - origWindow.close(); -} - -// Kick things off. -document.addEventListener('DOMContentLoaded', init);
diff --git a/chrome/common/extensions/docs/examples/api/storage/stylizr/icon.png b/chrome/common/extensions/docs/examples/api/storage/stylizr/icon.png deleted file mode 100644 index 30098be0e..0000000 --- a/chrome/common/extensions/docs/examples/api/storage/stylizr/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/storage/stylizr/manifest.json b/chrome/common/extensions/docs/examples/api/storage/stylizr/manifest.json deleted file mode 100644 index 1c0b9ce..0000000 --- a/chrome/common/extensions/docs/examples/api/storage/stylizr/manifest.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name": "Stylizr", - "description": "Spruce up your pages with custom CSS.", - "version": "1.0", - - "permissions": [ - "activeTab", - "storage" - ], - - "options_page": "options.html", - - "browser_action": { - "default_icon": "icon.png", - "default_title": "Stylize!", - "default_popup": "popup.html" - }, - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/storage/stylizr/options.html b/chrome/common/extensions/docs/examples/api/storage/stylizr/options.html deleted file mode 100644 index 108e6617..0000000 --- a/chrome/common/extensions/docs/examples/api/storage/stylizr/options.html +++ /dev/null
@@ -1,42 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Stylizr</title> - <style> - body { - font-family: sans-serif; - } - label { - display: block; - } - textarea { - font-family: monospace; - } - .message { - height: 20px; - background: #eee; - padding: 5px; - } - </style> - </head> - <body> - <div class="message"></div> - <h3>Stylizr Instructions</h3> - - <ol> - <li>Write CSS in this textarea and save</li> - <li>Navigate to some page</li> - <li>Click the browser action icon <img src="icon.png" /></li> - <li>Hey presto! CSS is injected!</li> - </ol> - - <textarea name="style_url" id="style_url" cols=80 rows=24 - placeholder="eg: * { font-size: 110%; }"></textarea> - - <br/> - <button class="submit">Save</button> - <button class="reset">Reset</button> - - <script src="options.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/storage/stylizr/options.js b/chrome/common/extensions/docs/examples/api/storage/stylizr/options.js deleted file mode 100644 index a687c5f..0000000 --- a/chrome/common/extensions/docs/examples/api/storage/stylizr/options.js +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Store CSS data in the "local" storage area. -// -// Usually we try to store settings in the "sync" area since a lot of the time -// it will be a better user experience for settings to automatically sync -// between browsers. -// -// However, "sync" is expensive with a strict quota (both in storage space and -// bandwidth) so data that may be as large and updated as frequently as the CSS -// may not be suitable. -var storage = chrome.storage.local; - -// Get at the DOM controls used in the sample. -var resetButton = document.querySelector('button.reset'); -var submitButton = document.querySelector('button.submit'); -var textarea = document.querySelector('textarea'); - -// Load any CSS that may have previously been saved. -loadChanges(); - -submitButton.addEventListener('click', saveChanges); -resetButton.addEventListener('click', reset); - -function saveChanges() { - // Get the current CSS snippet from the form. - var cssCode = textarea.value; - // Check that there's some code there. - if (!cssCode) { - message('Error: No CSS specified'); - return; - } - // Save it using the Chrome extension storage API. - storage.set({'css': cssCode}, function() { - // Notify that we saved. - message('Settings saved'); - }); -} - -function loadChanges() { - storage.get('css', function(items) { - // To avoid checking items.css we could specify storage.get({css: ''}) to - // return a default value of '' if there is no css value yet. - if (items.css) { - textarea.value = items.css; - message('Loaded saved CSS.'); - } - }); -} - -function reset() { - // Remove the saved value from storage. storage.clear would achieve the same - // thing. - storage.remove('css', function(items) { - message('Reset stored CSS'); - }); - // Refresh the text area. - textarea.value = ''; -} - -function message(msg) { - var message = document.querySelector('.message'); - message.innerText = msg; - setTimeout(function() { - message.innerText = ''; - }, 3000); -}
diff --git a/chrome/common/extensions/docs/examples/api/storage/stylizr/popup.html b/chrome/common/extensions/docs/examples/api/storage/stylizr/popup.html deleted file mode 100644 index 02b597d..0000000 --- a/chrome/common/extensions/docs/examples/api/storage/stylizr/popup.html +++ /dev/null
@@ -1,16 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Stylizr</title> - <style> - body { - font-family: sans-serif; - width: 200px; - } - </style> - </head> - <body> - <div id="message"></div> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/storage/stylizr/popup.js b/chrome/common/extensions/docs/examples/api/storage/stylizr/popup.js deleted file mode 100644 index 4b44751..0000000 --- a/chrome/common/extensions/docs/examples/api/storage/stylizr/popup.js +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Store CSS data in the "local" storage area. -// -// See note in options.js for rationale on why not to use "sync". -var storage = chrome.storage.local; - -var message = document.querySelector('#message'); - -// Check if there is CSS specified. -storage.get('css', function(items) { - console.log(items); - // If there is CSS specified, inject it into the page. - if (items.css) { - chrome.tabs.insertCSS({code: items.css}, function() { - if (chrome.runtime.lastError) { - message.innerText = 'Not allowed to inject CSS into special page.'; - } else { - message.innerText = 'Injected style!'; - } - }); - } else { - var optionsUrl = chrome.extension.getURL('options.html'); - message.innerHTML = 'Set a style in the <a target="_blank" href="' + - optionsUrl + '">options page</a> first.'; - } -}); -
diff --git a/chrome/common/extensions/docs/examples/api/tabCapture/eventPage.js b/chrome/common/extensions/docs/examples/api/tabCapture/eventPage.js deleted file mode 100644 index fcde1bc..0000000 --- a/chrome/common/extensions/docs/examples/api/tabCapture/eventPage.js +++ /dev/null
@@ -1,82 +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. - -// The window (tab) opened and navigated to receiver.html. -var receiver = null; - -// Open a new window of receiver.html when browser action icon is clicked. -function playCapturedStream(stream) { - if (!stream) { - console.error('Error starting tab capture: ' + - (chrome.runtime.lastError.message || 'UNKNOWN')); - return; - } - if (receiver != null) { - receiver.close(); - } - receiver = window.open('receiver.html'); - receiver.currentStream = stream; -} - -function testCapture() { - console.log('Test with method capture().'); - chrome.tabCapture.capture({ - video: true, audio: true, - videoConstraints: { - mandatory: { - // If minWidth/Height have the same aspect ratio (e.g., 16:9) as - // maxWidth/Height, the implementation will letterbox/pillarbox as - // needed. Otherwise, set minWidth/Height to 0 to allow output video - // to be of any arbitrary size. - minWidth: 16, - minHeight: 9, - maxWidth: 854, - maxHeight: 480, - maxFrameRate: 60, // Note: Frame rate is variable (0 <= x <= 60). - }, - }, - }, - function(stream) { - playCapturedStream(stream); - }); -} - -function testGetMediaStreamId() { - console.log('Test with method getMediaStreamId().'); - chrome.tabCapture.getMediaStreamId(function(streamId) { - if (typeof streamId !== 'string') { - console.error('Failed to get media stream id: ' + - (chrome.runtime.lastError.message || 'UNKNOWN')); - return; - } - - navigator.webkitGetUserMedia({ - audio:false, - video: { - mandatory:{ - chromeMediaSource:'tab', // The media source must be 'tab' here. - chromeMediaSourceId:streamId - } - } - }, - function(stream){ - playCapturedStream(stream); - }, - function(error){ - console.error(error); - }) - }); -} - -chrome.browserAction.onClicked.addListener(function(tab) { - // Retrieve the test option to test each method respectively. - // The captured stream will have different resolution for each test. - chrome.storage.local.get(['tabCaptureMethod'], function(result) { - if (result.tabCaptureMethod == 'streamId') { - testGetMediaStreamId(); - } else { - testCapture(); - } - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/tabCapture/icon.png b/chrome/common/extensions/docs/examples/api/tabCapture/icon.png deleted file mode 100644 index a49189cf..0000000 --- a/chrome/common/extensions/docs/examples/api/tabCapture/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabCapture/manifest.json b/chrome/common/extensions/docs/examples/api/tabCapture/manifest.json deleted file mode 100644 index 777e1e2..0000000 --- a/chrome/common/extensions/docs/examples/api/tabCapture/manifest.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "name": "Tab Capture Example", - "description": "Capture a tab and play in a <video> element in a separate tab.", - "version": "1", - "manifest_version": 2, - "background": { - "scripts": ["eventPage.js"], - "persistent": false - }, - "browser_action": { - "default_icon": "icon.png" - }, - "options_ui": { - "page": "options.html", - "open_in_tab": false - }, - "permissions": [ - "storage", - "tabs", - "tabCapture" - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/tabCapture/options.html b/chrome/common/extensions/docs/examples/api/tabCapture/options.html deleted file mode 100644 index f385c6d..0000000 --- a/chrome/common/extensions/docs/examples/api/tabCapture/options.html +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<html> -<head><title>tabCapture Sample Options</title></head> -<body> - -Test tabCapture method: -<form name="methodForm"> - <input type="radio" name="method" id="capture" - value="capture" style="margin-top: 5px"> capture()<br> - <input type="radio" name="method" id="streamId" - value="streamId" style="margin-top: 5px"> getMediaSteamId()<br> -</form> - -<button id="save" style="margin-top: 10px">Save</button> -<div id="status" style="margin-top: 5px"></div> - -<script src="options.js"></script> -</body> -</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/tabCapture/options.js b/chrome/common/extensions/docs/examples/api/tabCapture/options.js deleted file mode 100644 index 575cbbac..0000000 --- a/chrome/common/extensions/docs/examples/api/tabCapture/options.js +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2018 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. - -// Restore the option last saved. -window.onload = function() { - chrome.storage.local.get(['tabCaptureMethod'], function(result) { - if (result.tabCaptureMethod == 'streamId') { - document.getElementById('streamId').checked = true; - } else { - document.getElementById('capture').checked = true; - } - }); -} - -// Save option locally. -function saveOption(){ - var value = document.querySelector('input[name="method"]:checked').value; - chrome.storage.local.set({'tabCaptureMethod': value}, function() { - var status = document.getElementById('status'); - status.textContent = "Option saved."; - setTimeout(function() {status.textContent = '';}, 750); - }); -} - -document.getElementById('save').addEventListener('click', saveOption); \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/tabCapture/receiver.html b/chrome/common/extensions/docs/examples/api/tabCapture/receiver.html deleted file mode 100644 index 214e823..0000000 --- a/chrome/common/extensions/docs/examples/api/tabCapture/receiver.html +++ /dev/null
@@ -1,26 +0,0 @@ -<html> - <head> - <style> - body { - align-items: center; - background-color: #224; - display: flex; - justify-content: center; - margin: none; - padding: none; - } - - body.shutdown { - background-color: #422; - } - - body.shutdown #player { - display: none; - } - </style> - </head> - <body> - <video id="player"></video> - <script src="receiver.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/tabCapture/receiver.js b/chrome/common/extensions/docs/examples/api/tabCapture/receiver.js deleted file mode 100644 index 3ea7b40..0000000 --- a/chrome/common/extensions/docs/examples/api/tabCapture/receiver.js +++ /dev/null
@@ -1,49 +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. - -// Note: |window.currentStream| was set in background.js. - -// Stop video play-out, stop the MediaStreamTracks, and set style class to -// "shutdown". -function shutdownReceiver() { - if (!window.currentStream) { - return; - } - - var player = document.getElementById('player'); - player.srcObject = null; - var tracks = window.currentStream.getTracks(); - for (var i = 0; i < tracks.length; ++i) { - tracks[i].stop(); - } - window.currentStream = null; - - document.body.className = 'shutdown'; -} - -window.addEventListener('load', function() { - // Start video play-out of the captured audio/video MediaStream once the page - // has loaded. - var player = document.getElementById('player'); - player.addEventListener('canplay', function() { - this.volume = 0.75; - this.muted = false; - this.play(); - }); - player.setAttribute('controls', '1'); - player.srcObject = window.currentStream; - - // Add onended event listeners. This detects when tab capture was shut down by - // closing the tab being captured. - var tracks = window.currentStream.getTracks(); - for (var i = 0; i < tracks.length; ++i) { - tracks[i].addEventListener('ended', function() { - console.log('MediaStreamTrack[' + i + '] ended, shutting down...'); - shutdownReceiver(); - }); - } -}); - -// Shutdown when the receiver page is closed. -window.addEventListener('beforeunload', shutdownReceiver);
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/background.js b/chrome/common/extensions/docs/examples/api/tabs/inspector/background.js deleted file mode 100644 index a58a0036..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/inspector/background.js +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -chrome.browserAction.onClicked.addListener(function(tab) { - chrome.tabs.create({url:chrome.extension.getURL("tabs_api.html")}); -});
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js b/chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js deleted file mode 100644 index 2f62b316..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js +++ /dev/null
@@ -1,1182 +0,0 @@ -/** - * @fileoverview This file contains miscellaneous basic functionality. - * - */ - -/** - * Creates a DOM element with the given tag name in the document of the - * owner element. - * - * @param {String} tagName The name of the tag to create. - * @param {Element} owner The intended owner (i.e., parent element) of - * the created element. - * @param {Point} opt_position The top-left corner of the created element. - * @param {Size} opt_size The size of the created element. - * @param {Boolean} opt_noAppend Do not append the new element to the owner. - * @return {Element} The newly created element node. - */ -function createElement(tagName, owner, opt_position, opt_size, opt_noAppend) { - var element = ownerDocument(owner).createElement(tagName); - if (opt_position) { - setPosition(element, opt_position); - } - if (opt_size) { - setSize(element, opt_size); - } - if (owner && !opt_noAppend) { - appendChild(owner, element); - } - - return element; -} - -/** - * Creates a text node with the given value. - * - * @param {String} value The text to place in the new node. - * @param {Element} owner The owner (i.e., parent element) of the new - * text node. - * @return {Text} The newly created text node. - */ -function createTextNode(value, owner) { - var element = ownerDocument(owner).createTextNode(value); - if (owner) { - appendChild(owner, element); - } - return element; -} - -/** - * Returns the document owner of the given element. In particular, - * returns window.document if node is null or the browser does not - * support ownerDocument. - * - * @param {Node} node The node whose ownerDocument is required. - * @returns {Document|Null} The owner document or null if unsupported. - */ -function ownerDocument(node) { - return (node ? node.ownerDocument : null) || document; -} - -/** - * Wrapper function to create CSS units (pixels) string - * - * @param {Number} numPixels Number of pixels, may be floating point. - * @returns {String} Corresponding CSS units string. - */ -function px(numPixels) { - return round(numPixels) + "px"; -} - -/** - * Sets the left and top of the given element to the given point. - * - * @param {Element} element The dom element to manipulate. - * @param {Point} point The desired position. - */ -function setPosition(element, point) { - var style = element.style; - style.position = "absolute"; - style.left = px(point.x); - style.top = px(point.y); -} - -/** - * Sets the width and height style attributes to the given size. - * - * @param {Element} element The dom element to manipulate. - * @param {Size} size The desired size. - */ -function setSize(element, size) { - var style = element.style; - style.width = px(size.width); - style.height = px(size.height); -} - -/** - * Sets display to none. Doing this as a function saves a few bytes for - * the 'style.display' property and the 'none' literal. - * - * @param {Element} node The dom element to manipulate. - */ -function displayNone(node) { - node.style.display = 'none'; -} - -/** - * Sets display to default. - * - * @param {Element} node The dom element to manipulate. - */ -function displayDefault(node) { - node.style.display = ''; -} - -/** - * Appends the given child to the given parent in the DOM - * - * @param {Element} parent The parent dom element. - * @param {Node} child The new child dom node. - */ -function appendChild(parent, child) { - parent.appendChild(child); -} - - -/** - * Wrapper for the eval() builtin function to evaluate expressions and - * obtain their value. It wraps the expression in parentheses such - * that object literals are really evaluated to objects. Without the - * wrapping, they are evaluated as block, and create syntax - * errors. Also protects against other syntax errors in the eval()ed - * code and returns null if the eval throws an exception. - * - * @param {String} expr - * @return {Object|Null} - */ -function jsEval(expr) { - try { - return eval('[' + expr + '][0]'); - } catch (e) { - return null; - } -} - - -/** - * Wrapper for the eval() builtin function to execute statements. This - * guards against exceptions thrown, but doesn't return a - * value. Still, mostly for testability, it returns a boolean to - * indicate whether execution was successful. NOTE: - * javascript's eval semantics is murky in that it confounds - * expression evaluation and statement execution into a single - * construct. Cf. jsEval(). - * - * @param {String} stmt - * @return {Boolean} - */ -function jsExec(stmt) { - try { - eval(stmt); - return true; - } catch (e) { - return false; - } -} - - -/** - * Wrapper for eval with a context. NOTE: The style guide - * deprecates eval, so this is the exception that proves the - * rule. Notice also that since the value of the expression is - * returned rather than assigned to a local variable, one major - * objection aganist the use of the with() statement, namely that - * properties of the with() target override local variables of the - * same name, is void here. - * - * @param {String} expr - * @param {Object} context - * @return {Object|Null} - */ -function jsEvalWith(expr, context) { - try { - with (context) { - return eval('[' + expr + '][0]'); - } - } catch (e) { - return null; - } -} - - -var DOM_ELEMENT_NODE = 1; -var DOM_ATTRIBUTE_NODE = 2; -var DOM_TEXT_NODE = 3; -var DOM_CDATA_SECTION_NODE = 4; -var DOM_ENTITY_REFERENCE_NODE = 5; -var DOM_ENTITY_NODE = 6; -var DOM_PROCESSING_INSTRUCTION_NODE = 7; -var DOM_COMMENT_NODE = 8; -var DOM_DOCUMENT_NODE = 9; -var DOM_DOCUMENT_TYPE_NODE = 10; -var DOM_DOCUMENT_FRAGMENT_NODE = 11; -var DOM_NOTATION_NODE = 12; - -/** - * Traverses the element nodes in the DOM tree underneath the given - * node and finds the first node with elemId, or null if there is no such - * element. Traversal is in depth-first order. - * - * NOTE: The reason this is not combined with the elem() function is - * that the implementations are different. - * elem() is a wrapper for the built-in document.getElementById() function, - * whereas this function performs the traversal itself. - * Modifying elem() to take an optional root node is a possibility, - * but the in-built function would perform better than using our own traversal. - * - * @param {Element} node Root element of subtree to traverse. - * @param {String} elemId The id of the element to search for. - * @return {Element|Null} The corresponding element, or null if not found. - */ -function nodeGetElementById(node, elemId) { - for (var c = node.firstChild; c; c = c.nextSibling) { - if (c.id == elemId) { - return c; - } - if (c.nodeType == DOM_ELEMENT_NODE) { - var n = arguments.callee.call(this, c, elemId); - if (n) { - return n; - } - } - } - return null; -} - - -/** - * Get an attribute from the DOM. Simple redirect, exists to compress code. - * - * @param {Element} node Element to interrogate. - * @param {String} name Name of parameter to extract. - * @return {String} Resulting attribute. - */ -function domGetAttribute(node, name) { - return node.getAttribute(name); -} - -/** - * Set an attribute in the DOM. Simple redirect to compress code. - * - * @param {Element} node Element to interrogate. - * @param {String} name Name of parameter to set. - * @param {String} value Set attribute to this value. - */ -function domSetAttribute(node, name, value) { - node.setAttribute(name, value); -} - -/** - * Remove an attribute from the DOM. Simple redirect to compress code. - * - * @param {Element} node Element to interrogate. - * @param {String} name Name of parameter to remove. - */ -function domRemoveAttribute(node, name) { - node.removeAttribute(name); -} - -/** - * Clone a node in the DOM. - * - * @param {Node} node Node to clone. - * @return {Node} Cloned node. - */ -function domCloneNode(node) { - return node.cloneNode(true); -} - - -/** - * Return a safe string for the className of a node. - * If className is not a string, returns "". - * - * @param {Element} node DOM element to query. - * @return {String} - */ -function domClassName(node) { - return node.className ? "" + node.className : ""; -} - -/** - * Adds a class name to the class attribute of the given node. - * - * @param {Element} node DOM element to modify. - * @param {String} className Class name to add. - */ -function domAddClass(node, className) { - var name = domClassName(node); - if (name) { - var cn = name.split(/\s+/); - var found = false; - for (var i = 0; i < jsLength(cn); ++i) { - if (cn[i] == className) { - found = true; - break; - } - } - - if (!found) { - cn.push(className); - } - - node.className = cn.join(' '); - } else { - node.className = className; - } -} - -/** - * Removes a class name from the class attribute of the given node. - * - * @param {Element} node DOM element to modify. - * @param {String} className Class name to remove. - */ -function domRemoveClass(node, className) { - var c = domClassName(node); - if (!c || c.indexOf(className) == -1) { - return; - } - var cn = c.split(/\s+/); - for (var i = 0; i < jsLength(cn); ++i) { - if (cn[i] == className) { - cn.splice(i--, 1); - } - } - node.className = cn.join(' '); -} - -/** - * Checks if a node belongs to a style class. - * - * @param {Element} node DOM element to test. - * @param {String} className Class name to check for. - * @return {Boolean} Node belongs to style class. - */ -function domTestClass(node, className) { - var cn = domClassName(node).split(/\s+/); - for (var i = 0; i < jsLength(cn); ++i) { - if (cn[i] == className) { - return true; - } - } - return false; -} - -/** - * Inserts a new child before a given sibling. - * - * @param {Node} newChild Node to insert. - * @param {Node} oldChild Sibling node. - * @return {Node} Reference to new child. - */ -function domInsertBefore(newChild, oldChild) { - return oldChild.parentNode.insertBefore(newChild, oldChild); -} - -/** - * Appends a new child to the specified (parent) node. - * - * @param {Element} node Parent element. - * @param {Node} child Child node to append. - * @return {Node} Newly appended node. - */ -function domAppendChild(node, child) { - return node.appendChild(child); -} - -/** - * Remove a new child from the specified (parent) node. - * - * @param {Element} node Parent element. - * @param {Node} child Child node to remove. - * @return {Node} Removed node. - */ -function domRemoveChild(node, child) { - return node.removeChild(child); -} - -/** - * Replaces an old child node with a new child node. - * - * @param {Node} newChild New child to append. - * @param {Node} oldChild Old child to remove. - * @return {Node} Replaced node. - */ -function domReplaceChild(newChild, oldChild) { - return oldChild.parentNode.replaceChild(newChild, oldChild); -} - -/** - * Removes a node from the DOM. - * - * @param {Node} node The node to remove. - * @return {Node} The removed node. - */ -function domRemoveNode(node) { - return domRemoveChild(node.parentNode, node); -} - -/** - * Creates a new text node in the given document. - * - * @param {Document} doc Target document. - * @param {String} text Text composing new text node. - * @return {Text} Newly constructed text node. - */ -function domCreateTextNode(doc, text) { - return doc.createTextNode(text); -} - -/** - * Creates a new node in the given document - * - * @param {Document} doc Target document. - * @param {String} name Name of new element (i.e. the tag name).. - * @return {Element} Newly constructed element. - */ -function domCreateElement(doc, name) { - return doc.createElement(name); -} - -/** - * Creates a new attribute in the given document. - * - * @param {Document} doc Target document. - * @param {String} name Name of new attribute. - * @return {Attr} Newly constructed attribute. - */ -function domCreateAttribute(doc, name) { - return doc.createAttribute(name); -} - -/** - * Creates a new comment in the given document. - * - * @param {Document} doc Target document. - * @param {String} text Comment text. - * @return {Comment} Newly constructed comment. - */ -function domCreateComment(doc, text) { - return doc.createComment(text); -} - -/** - * Creates a document fragment. - * - * @param {Document} doc Target document. - * @return {DocumentFragment} Resulting document fragment node. - */ -function domCreateDocumentFragment(doc) { - return doc.createDocumentFragment(); -} - -/** - * Redirect to document.getElementById - * - * @param {Document} doc Target document. - * @param {String} id Id of requested node. - * @return {Element|Null} Resulting element. - */ -function domGetElementById(doc, id) { - return doc.getElementById(id); -} - -/** - * Redirect to window.setInterval - * - * @param {Window} win Target window. - * @param {Function} fun Callback function. - * @param {Number} time Time in milliseconds. - * @return {Object} Contract id. - */ -function windowSetInterval(win, fun, time) { - return win.setInterval(fun, time); -} - -/** - * Redirect to window.clearInterval - * - * @param {Window} win Target window. - * @param {object} id Contract id. - * @return {any} NOTE: Return type unknown? - */ -function windowClearInterval(win, id) { - return win.clearInterval(id); -} - -/** - * Determines whether one node is recursively contained in another. - * @param parent The parent node. - * @param child The node to look for in parent. - * @return parent recursively contains child - */ -function containsNode(parent, child) { - while (parent != child && child.parentNode) { - child = child.parentNode; - } - return parent == child; -}; -/** - * @fileoverview This file contains javascript utility functions that - * do not depend on anything defined elsewhere. - * - */ - -/** - * Returns the value of the length property of the given object. Used - * to reduce compiled code size. - * - * @param {Array | String} a The string or array to interrogate. - * @return {Number} The value of the length property. - */ -function jsLength(a) { - return a.length; -} - -var min = Math.min; -var max = Math.max; -var ceil = Math.ceil; -var floor = Math.floor; -var round = Math.round; -var abs = Math.abs; - -/** - * Copies all properties from second object to the first. Modifies to. - * - * @param {Object} to The target object. - * @param {Object} from The source object. - */ -function copyProperties(to, from) { - foreachin(from, function(p) { - to[p] = from[p]; - }); -} - -/** - * Iterates over the array, calling the given function for each - * element. - * - * @param {Array} array - * @param {Function} fn - */ -function foreach(array, fn) { - var I = jsLength(array); - for (var i = 0; i < I; ++i) { - fn(array[i], i); - } -} - -/** - * Safely iterates over all properties of the given object, calling - * the given function for each property. If opt_all isn't true, uses - * hasOwnProperty() to assure the property is on the object, not on - * its prototype. - * - * @param {Object} object - * @param {Function} fn - * @param {Boolean} opt_all If true, also iterates over inherited properties. - */ -function foreachin(object, fn, opt_all) { - for (var i in object) { - if (opt_all || !object.hasOwnProperty || object.hasOwnProperty(i)) { - fn(i, object[i]); - } - } -} - -/** - * Appends the second array to the first, copying its elements. - * Optionally only a slice of the second array is copied. - * - * @param {Array} a1 Target array (modified). - * @param {Array} a2 Source array. - * @param {Number} opt_begin Begin of slice of second array (optional). - * @param {Number} opt_end End (exclusive) of slice of second array (optional). - */ -function arrayAppend(a1, a2, opt_begin, opt_end) { - var i0 = opt_begin || 0; - var i1 = opt_end || jsLength(a2); - for (var i = i0; i < i1; ++i) { - a1.push(a2[i]); - } -} - -/** - * Trim whitespace from begin and end of string. - * - * @see testStringTrim(); - * - * @param {String} str Input string. - * @return {String} Trimmed string. - */ -function stringTrim(str) { - return stringTrimRight(stringTrimLeft(str)); -} - -/** - * Trim whitespace from beginning of string. - * - * @see testStringTrimLeft(); - * - * @param {String} str Input string. - * @return {String} Trimmed string. - */ -function stringTrimLeft(str) { - return str.replace(/^\s+/, ""); -} - -/** - * Trim whitespace from end of string. - * - * @see testStringTrimRight(); - * - * @param {String} str Input string. - * @return {String} Trimmed string. - */ -function stringTrimRight(str) { - return str.replace(/\s+$/, ""); -} - -/** - * Jscompiler wrapper for parseInt() with base 10. - * - * @param {String} s String repersentation of a number. - * - * @return {Number} The integer contained in s, converted on base 10. - */ -function parseInt10(s) { - return parseInt(s, 10); -} -/** - * @fileoverview A simple formatter to project JavaScript data into - * HTML templates. The template is edited in place. I.e. in order to - * instantiate a template, clone it from the DOM first, and then - * process the cloned template. This allows for updating of templates: - * If the templates is processed again, changed values are merely - * updated. - * - * NOTE: IE DOM doesn't have importNode(). - * - * NOTE: The property name "length" must not be used in input - * data, see comment in jstSelect_(). - */ - - -/** - * Names of jstemplate attributes. These attributes are attached to - * normal HTML elements and bind expression context data to the HTML - * fragment that is used as template. - */ -var ATT_select = 'jsselect'; -var ATT_instance = 'jsinstance'; -var ATT_display = 'jsdisplay'; -var ATT_values = 'jsvalues'; -var ATT_eval = 'jseval'; -var ATT_transclude = 'transclude'; -var ATT_content = 'jscontent'; - - -/** - * Names of special variables defined by the jstemplate evaluation - * context. These can be used in js expression in jstemplate - * attributes. - */ -var VAR_index = '$index'; -var VAR_this = '$this'; - - -/** - * Context for processing a jstemplate. The context contains a context - * object, whose properties can be referred to in jstemplate - * expressions, and it holds the locally defined variables. - * - * @param {Object} opt_data The context object. Null if no context. - * - * @param {Object} opt_parent The parent context, from which local - * variables are inherited. Normally the context object of the parent - * context is the object whose property the parent object is. Null for the - * context of the root object. - * - * @constructor - */ -function JsExprContext(opt_data, opt_parent) { - var me = this; - - /** - * The local context of the input data in which the jstemplate - * expressions are evaluated. Notice that this is usually an Object, - * but it can also be a scalar value (and then still the expression - * $this can be used to refer to it). Notice this can be a scalar - * value, including undefined. - * - * @type {Object} - */ - me.data_ = opt_data; - - /** - * The context for variable definitions in which the jstemplate - * expressions are evaluated. Other than for the local context, - * which replaces the parent context, variable definitions of the - * parent are inherited. The special variable $this points to data_. - * - * @type {Object} - */ - me.vars_ = {}; - if (opt_parent) { - copyProperties(me.vars_, opt_parent.vars_); - } - this.vars_[VAR_this] = me.data_; -} - - -/** - * Evaluates the given expression in the context of the current - * context object and the current local variables. - * - * @param {String} expr A javascript expression. - * - * @param {Element} template DOM node of the template. - * - * @return The value of that expression. - */ -JsExprContext.prototype.jseval = function(expr, template) { - with (this.vars_) { - with (this.data_) { - try { - return (function() { - return eval('[' + expr + '][0]'); - }).call(template); - } catch (e) { - return null; - } - } - } -} - - -/** - * Clones the current context for a new context object. The cloned - * context has the data object as its context object and the current - * context as its parent context. It also sets the $index variable to - * the given value. This value usually is the position of the data - * object in a list for which a template is instantiated multiply. - * - * @param {Object} data The new context object. - * - * @param {Number} index Position of the new context when multiply - * instantiated. (See implementation of jstSelect().) - * - * @return {JsExprContext} - */ -JsExprContext.prototype.clone = function(data, index) { - var ret = new JsExprContext(data, this); - ret.setVariable(VAR_index, index); - if (this.resolver_) { - ret.setSubTemplateResolver(this.resolver_); - } - return ret; -} - - -/** - * Binds a local variable to the given value. If set from jstemplate - * jsvalue expressions, variable names must start with $, but in the - * API they only have to be valid javascript identifier. - * - * @param {String} name - * - * @param {Object} value - */ -JsExprContext.prototype.setVariable = function(name, value) { - this.vars_[name] = value; -} - - -/** - * Sets the function used to resolve the values of the transclude - * attribute into DOM nodes. By default, this is jstGetTemplate(). The - * value set here is inherited by clones of this context. - * - * @param {Function} resolver The function used to resolve transclude - * ids into a DOM node of a subtemplate. The DOM node returned by this - * function will be inserted into the template instance being - * processed. Thus, the resolver function must instantiate the - * subtemplate as necessary. - */ -JsExprContext.prototype.setSubTemplateResolver = function(resolver) { - this.resolver_ = resolver; -} - - -/** - * Resolves a sub template from an id. Used to process the transclude - * attribute. If a resolver function was set using - * setSubTemplateResolver(), it will be used, otherwise - * jstGetTemplate(). - * - * @param {String} id The id of the sub template. - * - * @return {Node} The root DOM node of the sub template, for direct - * insertion into the currently processed template instance. - */ -JsExprContext.prototype.getSubTemplate = function(id) { - return (this.resolver_ || jstGetTemplate).call(this, id); -} - - -/** - * HTML template processor. Data values are bound to HTML templates - * using the attributes transclude, jsselect, jsdisplay, jscontent, - * jsvalues. The template is modifed in place. The values of those - * attributes are JavaScript expressions that are evaluated in the - * context of the data object fragment. - * - * @param {JsExprContext} context Context created from the input data - * object. - * - * @param {Element} template DOM node of the template. This will be - * processed in place. After processing, it will still be a valid - * template that, if processed again with the same data, will remain - * unchanged. - */ -function jstProcess(context, template) { - var processor = new JstProcessor(); - processor.run_([ processor, processor.jstProcess_, context, template ]); -} - - -/** - * Internal class used by jstemplates to maintain context. - * NOTE: This is necessary to process deep templates in Safari - * which has a relatively shallow stack. - * @class - */ -function JstProcessor() { -} - - -/** - * Runs the state machine, beginning with function "start". - * - * @param {Array} start The first function to run, in the form - * [object, method, args ...] - */ -JstProcessor.prototype.run_ = function(start) { - var me = this; - - me.queue_ = [ start ]; - while (jsLength(me.queue_)) { - var f = me.queue_.shift(); - f[1].apply(f[0], f.slice(2)); - } -} - - -/** - * Appends a function to be called later. - * Analogous to calling that function on a subsequent line, or a subsequent - * iteration of a loop. - * - * @param {Array} f A function in the form [object, method, args ...] - */ -JstProcessor.prototype.enqueue_ = function(f) { - this.queue_.push(f); -} - - -/** - * Implements internals of jstProcess. - * - * @param {JsExprContext} context - * - * @param {Element} template - */ -JstProcessor.prototype.jstProcess_ = function(context, template) { - var me = this; - - var transclude = domGetAttribute(template, ATT_transclude); - if (transclude) { - var tr = context.getSubTemplate(transclude); - if (tr) { - domReplaceChild(tr, template); - me.enqueue_([ me, me.jstProcess_, context, tr ]); - } else { - domRemoveNode(template); - } - return; - } - - var select = domGetAttribute(template, ATT_select); - if (select) { - me.jstSelect_(context, template, select); - return; - } - - var display = domGetAttribute(template, ATT_display); - if (display) { - if (!context.jseval(display, template)) { - displayNone(template); - return; - } - - displayDefault(template); - } - - - var values = domGetAttribute(template, ATT_values); - if (values) { - me.jstValues_(context, template, values); - } - - var expressions = domGetAttribute(template, ATT_eval); - if (expressions) { - foreach(expressions.split(/\s*;\s*/), function(expression) { - expression = stringTrim(expression); - if (jsLength(expression)) { - context.jseval(expression, template); - } - }); - } - - var content = domGetAttribute(template, ATT_content); - if (content) { - me.jstContent_(context, template, content); - - } else { - var childnodes = []; - for (var i = 0; i < jsLength(template.childNodes); ++i) { - if (template.childNodes[i].nodeType == DOM_ELEMENT_NODE) { - me.enqueue_( - [ me, me.jstProcess_, context, template.childNodes[i] ]); - } - } - } -} - - -/** - * Implements the jsselect attribute: evalutes the value of the - * jsselect attribute in the current context, with the current - * variable bindings (see JsExprContext.jseval()). If the value is an - * array, the current template node is multiplied once for every - * element in the array, with the array element being the context - * object. If the array is empty, or the value is undefined, then the - * current template node is dropped. If the value is not an array, - * then it is just made the context object. - * - * @param {JsExprContext} context The current evaluation context. - * - * @param {Element} template The currently processed node of the template. - * - * @param {String} select The javascript expression to evaluate. - * - * @param {Function} process The function to continue processing with. - */ -JstProcessor.prototype.jstSelect_ = function(context, template, select) { - var me = this; - - var value = context.jseval(select, template); - domRemoveAttribute(template, ATT_select); - - var instance = domGetAttribute(template, ATT_instance); - var instance_last = false; - if (instance) { - if (instance.charAt(0) == '*') { - instance = parseInt10(instance.substr(1)); - instance_last = true; - } else { - instance = parseInt10(instance); - } - } - - var multiple = (value !== null && - typeof value == 'object' && - typeof value.length == 'number'); - var multiple_empty = (multiple && value.length == 0); - - if (multiple) { - if (multiple_empty) { - if (!instance) { - domSetAttribute(template, ATT_select, select); - domSetAttribute(template, ATT_instance, '*0'); - displayNone(template); - } else { - domRemoveNode(template); - } - - } else { - displayDefault(template); - if (instance === null || instance === "" || instance === undefined || - (instance_last && instance < jsLength(value) - 1)) { - var templatenodes = []; - var instances_start = instance || 0; - for (var i = instances_start + 1; i < jsLength(value); ++i) { - var node = domCloneNode(template); - templatenodes.push(node); - domInsertBefore(node, template); - } - templatenodes.push(template); - - for (var i = 0; i < jsLength(templatenodes); ++i) { - var ii = i + instances_start; - var v = value[ii]; - var t = templatenodes[i]; - - me.enqueue_([ me, me.jstProcess_, context.clone(v, ii), t ]); - var instanceStr = (ii == jsLength(value) - 1 ? '*' : '') + ii; - me.enqueue_( - [ null, postProcessMultiple_, t, select, instanceStr ]); - } - - } else if (instance < jsLength(value)) { - var v = value[instance]; - - me.enqueue_( - [me, me.jstProcess_, context.clone(v, instance), template]); - var instanceStr = (instance == jsLength(value) - 1 ? '*' : '') - + instance; - me.enqueue_( - [ null, postProcessMultiple_, template, select, instanceStr ]); - } else { - domRemoveNode(template); - } - } - } else { - if (value == null) { - domSetAttribute(template, ATT_select, select); - displayNone(template); - } else { - me.enqueue_( - [ me, me.jstProcess_, context.clone(value, 0), template ]); - me.enqueue_( - [ null, postProcessSingle_, template, select ]); - } - } -} - - -/** - * Sets ATT_select and ATT_instance following recursion to jstProcess. - * - * @param {Element} template The template - * - * @param {String} select The jsselect string - * - * @param {String} instanceStr The new value for the jsinstance attribute - */ -function postProcessMultiple_(template, select, instanceStr) { - domSetAttribute(template, ATT_select, select); - domSetAttribute(template, ATT_instance, instanceStr); -} - - -/** - * Sets ATT_select and makes the element visible following recursion to - * jstProcess. - * - * @param {Element} template The template - * - * @param {String} select The jsselect string - */ -function postProcessSingle_(template, select) { - domSetAttribute(template, ATT_select, select); - displayDefault(template); -} - - -/** - * Implements the jsvalues attribute: evaluates each of the values and - * assigns them to variables in the current context (if the name - * starts with '$', javascript properties of the current template node - * (if the name starts with '.'), or DOM attributes of the current - * template node (otherwise). Since DOM attribute values are always - * strings, the value is coerced to string in the latter case, - * otherwise it's the uncoerced javascript value. - * - * @param {JsExprContext} context Current evaluation context. - * - * @param {Element} template Currently processed template node. - * - * @param {String} valuesStr Value of the jsvalues attribute to be - * processed. - */ -JstProcessor.prototype.jstValues_ = function(context, template, valuesStr) { - var values = valuesStr.split(/\s*;\s*/); - for (var i = 0; i < jsLength(values); ++i) { - var colon = values[i].indexOf(':'); - if (colon < 0) { - continue; - } - var label = stringTrim(values[i].substr(0, colon)); - var value = context.jseval(values[i].substr(colon + 1), template); - - if (label.charAt(0) == '$') { - context.setVariable(label, value); - - } else if (label.charAt(0) == '.') { - var nameSpaceLabel = label.substr(1).split('.'); - var nameSpaceObject = template; - var nameSpaceDepth = jsLength(nameSpaceLabel); - for (var j = 0, J = nameSpaceDepth - 1; j < J; ++j) { - var jLabel = nameSpaceLabel[j]; - if (!nameSpaceObject[jLabel]) { - nameSpaceObject[jLabel] = {}; - } - nameSpaceObject = nameSpaceObject[jLabel]; - } - nameSpaceObject[nameSpaceLabel[nameSpaceDepth - 1]] = value; - } else if (label) { - if (typeof value == 'boolean') { - if (value) { - domSetAttribute(template, label, label); - } else { - domRemoveAttribute(template, label); - } - } else { - domSetAttribute(template, label, '' + value); - } - } - } -} - - -/** - * Implements the jscontent attribute. Evalutes the expression in - * jscontent in the current context and with the current variables, - * and assigns its string value to the content of the current template - * node. - * - * @param {JsExprContext} context Current evaluation context. - * - * @param {Element} template Currently processed template node. - * - * @param {String} content Value of the jscontent attribute to be - * processed. - */ -JstProcessor.prototype.jstContent_ = function(context, template, content) { - var value = '' + context.jseval(content, template); - if (template.innerHTML == value) { - return; - } - while (template.firstChild) { - domRemoveNode(template.firstChild); - } - var t = domCreateTextNode(ownerDocument(template), value); - domAppendChild(template, t); -} - - -/** - * Helps to implement the transclude attribute, and is the initial - * call to get hold of a template from its ID. - * - * @param {String} name The ID of the HTML element used as template. - * - * @returns {Element} The DOM node of the template. (Only element - * nodes can be found by ID, hence it's a Element.) - */ -function jstGetTemplate(name) { - var section = domGetElementById(document, name); - if (section) { - var ret = domCloneNode(section); - domRemoveAttribute(ret, 'id'); - return ret; - } else { - return null; - } -} - -window['jstGetTemplate'] = jstGetTemplate; -window['jstProcess'] = jstProcess; -window['JsExprContext'] = JsExprContext;
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json b/chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json deleted file mode 100644 index 68b7728e..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "name": "Tab Inspector", - "description": "Utility for working with the extension tabs api", - "version": "0.3", - "permissions": ["tabs"], - "background": { - "persistent": false, - "scripts": ["background.js"] - }, - "browser_action": { - "default_title": "show tab inspector" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html b/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html deleted file mode 100644 index d58f8d8..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html +++ /dev/null
@@ -1,105 +0,0 @@ -<html> -<head> -<script src="jstemplate_compiled.js" type="text/javascript"></script> -<script src="tabs_api.js"></script> -</head> - <body> - <div id="windowList"> - <div style="background-color: #AAEEEE; margin: 4px; padding: 8px; margin: 20px" jsselect="$this" - jsvalues="id:'window_' + id"> - <div style="font-style: italic; width: 80px; display: inline-block"> - Window: <span jscontent="id"></span> - </div> - <div style="display: inline-block"> - left: <input style="width: 60px" type="text" jsvalues="value:$this.left;id:'left_' + id" /> - top: <input style="width: 60px" type="text" jsvalues="value:$this.top;id:'top_' + id" /> - width: <input style="width: 60px" type="text" jsvalues="value:$this.width;id:'width_' + id" /> - height: <input style="width: 60px" type="text" jsvalues="value:$this.height;id:'height_' + id" /> - <input type="checkbox" jsvalues="checked:focused; id:'focused_' + id" /> Focused - <input type="checkbox" jsvalues="checked:current; id:'current_' + id" /> Current - <button onclick="refreshWindow(this.jstdata);" jsvalues=".jstdata:id">Refresh</button> - </div> - <div id="tabList"> - <div jsselect="tabs"> - <div style="background-color: #EEEEEE; margin: 8px; padding: 4px" jsvalues="id:'tab_' + id"> - <div style="margin: 8px"> - <div style="font-style: italic; width: 80px; display: inline-block" jscontent="'TabId: ' + id"></div> - <div style="width: 300px; display: inline-block"> - index: <input style="width: 20px" type="text" jsvalues="value:$this.index;id:'index_' + id" /> - windowId: <input style="width: 20px" type="text" jsvalues="value:windowId;id:'windowId_' + id" /> - <button onclick="moveTab(this.jstdata);" jsvalues=".jstdata:id">Move</button> - <button onclick="refreshTab(this.jstdata);" jsvalues=".jstdata:id">Refresh</button> - </div> - </div> - <div style="margin: 8px"> - <div> - <div style="width: 40px; display:inline-block">title:</div> - <input style="width: 90%" type="text" jsvalues="value:title;id:'title_' + id" /> - </div> - <div> - <div style="width: 40px; display:inline-block">url:</div> - <input style="width: 90%" type="text" jsvalues="value:url;id:'url_' + id" /> - </div> - <div><input type="checkbox" jsvalues="checked:selected; id:'selected_' + id" /> Selected</div> - </div> - <button onclick="updateTab(this.jstdata)" jsvalues=".jstdata:id">Update Tab</button> - <button onclick="removeTab(this.jstdata);" jsvalues=".jstdata:id">Close Tab</button> - </div> - </div> - </div> - <button onclick="updateWindow(this.jstdata);" jsvalues=".jstdata:id">Update Window</button> - <button onclick="removeWindow(this.jstdata);" jsvalues=".jstdata:id">Close Window</button> - <button onclick="refreshSelectedTab(this.jstdata);" jsvalues=".jstdata:id">Refresh Selected Tab</button> - </div> - </div> - <div style="background-color: #EEEEBB; margin: 20px; padding: 8px"> - <h3 style="text-align: center; margin: 8px"> Create Window</h3> - <div style="margin: 8px"> - <div style="width: 300px; display: inline-block"> - left: <input style="width: 20px" type="text" id="new_window_left" /> - top: <input style="width: 20px" type="text" id="new_window_top" /> - width: <input style="width: 20px" type="text" id="new_window_width" /> - height: <input style="width: 20px" type="text" id="new_window_height" /> - </div> - </div> - <div style="margin: 8px"> - <div> - <div style="width: 40px; display:inline-block">url:</div> - <input style="width: 90%" type="text" id="new_window_url" /> - </div> - </div> - <button onclick="createWindow();">Create</button> - </div> - <div style="background-color: #EEEEAA; margin: 20px; padding: 8px"> - <h3 style="text-align: center; margin: 8px"> Create Tab</h3> - <div style="margin: 8px"> - <div style="width: 300px; display: inline-block"> - index: <input style="width: 20px" type="text" id="index_new" /> - windowId: <input style="width: 20px" type="text" id="windowId_new" /> - <button onclick="moveTab(this.jstdata);" jsvalues=".jstdata:id">Move</button> - </div> - </div> - <div style="margin: 8px"> - <div> - <div style="width: 40px; display:inline-block">title:</div> - <input style="width: 90%" type="text" id="title_new" /> - </div> - <div> - <div style="width: 40px; display:inline-block">url:</div> - <input style="width: 90%" type="text" id="url_new" /> - </div> - <div><input type="checkbox" id="selected_new" /> Selected</div> - </div> - <button onclick="createTab();">Create</button> - </div> - <div style="margin: 20px;"> - <button onclick="loadWindowList();">Refresh</button> - <button onclick="updateAll();">Update All</button> - <button onclick="moveAll();">Move All</button> - <button onclick="clearLog();">-->Clear Log</button> - <button onclick="chrome.windows.create();">New Window</button> - </div> - <div id="log" style="background-color: #EEAAEE; margin: 20px; padding: 8px"> - </div> - </body> -</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.js b/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.js deleted file mode 100644 index a14e260a..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.js +++ /dev/null
@@ -1,305 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -tabs = {}; -tabIds = []; - -focusedWindowId = undefined; -currentWindowId = undefined; - -function bootStrap() { - chrome.windows.getCurrent(function(currentWindow) { - currentWindowId = currentWindow.id; - chrome.windows.getLastFocused(function(focusedWindow) { - focusedWindowId = focusedWindow.id; - loadWindowList(); - }); - }); -} - -function isInt(i) { - return (typeof i == "number") && !(i % 1) && !isNaN(i); -} - -function loadWindowList() { - chrome.windows.getAll({ populate: true }, function(windowList) { - tabs = {}; - tabIds = []; - for (var i = 0; i < windowList.length; i++) { - windowList[i].current = (windowList[i].id == currentWindowId); - windowList[i].focused = (windowList[i].id == focusedWindowId); - - for (var j = 0; j < windowList[i].tabs.length; j++) { - tabIds[tabIds.length] = windowList[i].tabs[j].id; - tabs[windowList[i].tabs[j].id] = windowList[i].tabs[j]; - } - } - - var input = new JsExprContext(windowList); - var output = document.getElementById('windowList'); - jstProcess(input, output); - }); -} - -function updateTabData(id) { - var retval = { - url: document.getElementById('url_' + id).value, - selected: document.getElementById('selected_' + id).value ? true : false - } - - return retval; -} - -function updateTab(id){ - try { - chrome.tabs.update(id, updateTabData(id)); - } catch (e) { - alert(e); - } -} - -function moveTabData(id) { - return { - 'index': parseInt(document.getElementById('index_' + id).value), - 'windowId': parseInt(document.getElementById('windowId_' + id).value) - } -} -function moveTab(id) { - try { - chrome.tabs.move(id, moveTabData(id)); - } catch (e) { - alert(e); - } -} - -function createTabData(id) { - return { - 'index': parseInt(document.getElementById('index_' + id).value), - 'windowId': parseInt(document.getElementById('windowId_' + id).value), - 'index': parseInt(document.getElementById('index_' + id).value), - 'url': document.getElementById('url_' + id).value, - 'selected': document.getElementById('selected_' + id).value ? true : false - } -} - -function createTab() { - var args = createTabData('new') - - if (!isInt(args.windowId)) - delete args.windowId; - if (!isInt(args.index)) - delete args.index; - - try { - chrome.tabs.create(args); - } catch (e) { - alert(e); - } -} - -function updateAll() { - try { - for (var i = 0; i < tabIds.length; i++) { - chrome.tabs.update(tabIds[i], updateTabData(tabIds[i])); - } - } catch(e) { - alert(e); - } -} - -function moveAll() { - appendToLog('moving all'); - try { - for (var i = 0; i < tabIds.length; i++) { - chrome.tabs.move(tabIds[i], moveTabData(tabIds[i])); - } - } catch(e) { - alert(e); - } -} - -function removeTab(tabId) { - try { - chrome.tabs.remove(tabId, function() { - appendToLog('tab: ' + tabId + ' removed.'); - }); - } catch (e) { - alert(e); - } -} - -function appendToLog(logLine) { - document.getElementById('log') - .appendChild(document.createElement('div')) - .innerText = "> " + logLine; -} - -function clearLog() { - document.getElementById('log').innerText = ''; -} - -chrome.windows.onCreated.addListener(function(createInfo) { - appendToLog('windows.onCreated -- window: ' + createInfo.id); - loadWindowList(); -}); - -chrome.windows.onFocusChanged.addListener(function(windowId) { - focusedWindowId = windowId; - appendToLog('windows.onFocusChanged -- window: ' + windowId); - loadWindowList(); -}); - -chrome.windows.onRemoved.addListener(function(windowId) { - appendToLog('windows.onRemoved -- window: ' + windowId); - loadWindowList(); -}); - -chrome.tabs.onCreated.addListener(function(tab) { - appendToLog( - 'tabs.onCreated -- window: ' + tab.windowId + ' tab: ' + tab.id + - ' title: ' + tab.title + ' index ' + tab.index + ' url ' + tab.url); - loadWindowList(); -}); - -chrome.tabs.onAttached.addListener(function(tabId, props) { - appendToLog( - 'tabs.onAttached -- window: ' + props.newWindowId + ' tab: ' + tabId + - ' index ' + props.newPosition); - loadWindowList(); -}); - -chrome.tabs.onMoved.addListener(function(tabId, props) { - appendToLog( - 'tabs.onMoved -- window: ' + props.windowId + ' tab: ' + tabId + - ' from ' + props.fromIndex + ' to ' + props.toIndex); - loadWindowList(); -}); - -function refreshTab(tabId) { - chrome.tabs.get(tabId, function(tab) { - var input = new JsExprContext(tab); - var output = document.getElementById('tab_' + tab.id); - jstProcess(input, output); - appendToLog('tab refreshed -- tabId: ' + tab.id + ' url: ' + tab.url); - }); -} - -chrome.tabs.onUpdated.addListener(function(tabId, props) { - appendToLog( - 'tabs.onUpdated -- tab: ' + tabId + ' status ' + props.status + - ' url ' + props.url); - refreshTab(tabId); -}); - -chrome.tabs.onDetached.addListener(function(tabId, props) { - appendToLog( - 'tabs.onDetached -- window: ' + props.oldWindowId + ' tab: ' + tabId + - ' index ' + props.oldPosition); - loadWindowList(); -}); - -chrome.tabs.onSelectionChanged.addListener(function(tabId, props) { - appendToLog( - 'tabs.onSelectionChanged -- window: ' + props.windowId + ' tab: ' + - tabId); - loadWindowList(); -}); - -chrome.tabs.onRemoved.addListener(function(tabId) { - appendToLog('tabs.onRemoved -- tab: ' + tabId); - loadWindowList(); -}); - -function createWindow() { - var args = { - 'left': parseInt(document.getElementById('new_window_left').value), - 'top': parseInt(document.getElementById('new_window_top').value), - 'width': parseInt(document.getElementById('new_window_width').value), - 'height': parseInt(document.getElementById('new_window_height').value), - 'url': document.getElementById('new_window_url').value - } - - if (!isInt(args.left)) - delete args.left; - if (!isInt(args.top)) - delete args.top; - if (!isInt(args.width)) - delete args.width; - if (!isInt(args.height)) - delete args.height; - if (!args.url) - delete args.url; - - try { - chrome.windows.create(args); - } catch(e) { - alert(e); - } -} - -function refreshWindow(windowId) { - chrome.windows.get(windowId, function(window) { - chrome.tabs.getAllInWindow(window.id, function(tabList) { - window.tabs = tabList; - var input = new JsExprContext(window); - var output = document.getElementById('window_' + window.id); - jstProcess(input, output); - appendToLog( - 'window refreshed -- windowId: ' + window.id + ' tab count:' + - window.tabs.length); - }); - }); -} - -function updateWindowData(id) { - var retval = { - left: parseInt(document.getElementById('left_' + id).value), - top: parseInt(document.getElementById('top_' + id).value), - width: parseInt(document.getElementById('width_' + id).value), - height: parseInt(document.getElementById('height_' + id).value) - } - if (!isInt(retval.left)) - delete retval.left; - if (!isInt(retval.top)) - delete retval.top; - if (!isInt(retval.width)) - delete retval.width; - if (!isInt(retval.height)) - delete retval.height; - - return retval; -} - -function updateWindow(id){ - try { - chrome.windows.update(id, updateWindowData(id)); - } catch (e) { - alert(e); - } -} - -function removeWindow(windowId) { - try { - chrome.windows.remove(windowId, function() { - appendToLog('window: ' + windowId + ' removed.'); - }); - } catch (e) { - alert(e); - } -} - -function refreshSelectedTab(windowId) { - chrome.tabs.query({active: true, currentWindow: true} function(tabs) { - var input = new JsExprContext(tabs[0]); - var output = document.getElementById('tab_' + tabs[0].id); - jstProcess(input, output); - appendToLog( - 'selected tab refreshed -- tabId: ' + tabs[0].id + - ' url:' + tabs[0].url); - }); -} - -document.addEventListener('DOMContentLoaded', function() { - bootStrap(); -}); \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/tabs/pin/README b/chrome/common/extensions/docs/examples/api/tabs/pin/README deleted file mode 100644 index d9d5c65..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/pin/README +++ /dev/null
@@ -1,2 +0,0 @@ -Demo Chrome Extension that uses the Tab Pinning API. Enables a new keyboard -shortcut (Ctrl + Shift + P) to toggle pinning and unpinning of the current tab.
diff --git a/chrome/common/extensions/docs/examples/api/tabs/pin/background.js b/chrome/common/extensions/docs/examples/api/tabs/pin/background.js deleted file mode 100644 index 13d87cf7..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/pin/background.js +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -chrome.commands.onCommand.addListener(function(command) { - if (command == "toggle-pin") { - // Get the currently selected tab - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - // Toggle the pinned status - var current = tabs[0] - chrome.tabs.update(current.id, {'pinned': !current.pinned}); - }); - } -});
diff --git a/chrome/common/extensions/docs/examples/api/tabs/pin/manifest.json b/chrome/common/extensions/docs/examples/api/tabs/pin/manifest.json deleted file mode 100644 index 3154c8c..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/pin/manifest.json +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "name": "Keyboard Pin", - "version": "0.3", - "description": "Creates a keyboard shortcut (Alt + Shift + P) to toggle the pinned state of the currently selected tab", - "background": { - "persistent": false, - "scripts": ["background.js"] - }, - "commands": { - "toggle-pin": { - "suggested_key": { "default": "Alt+Shift+P" }, - "description": "Toggle tab pin" - } - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.js b/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.js deleted file mode 100644 index 7f9b7bce..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.js +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// To make sure we can uniquely identify each screenshot tab, add an id as a -// query param to the url that displays the screenshot. -// Note: It's OK that this is a global variable (and not in localStorage), -// because the event page will stay open as long as any screenshot tabs are -// open. -var id = 100; - -// Listen for a click on the camera icon. On that click, take a screenshot. -chrome.browserAction.onClicked.addListener(function() { - - chrome.tabs.captureVisibleTab(function(screenshotUrl) { - var viewTabUrl = chrome.extension.getURL('screenshot.html?id=' + id++) - var targetId = null; - - chrome.tabs.onUpdated.addListener(function listener(tabId, changedProps) { - // We are waiting for the tab we opened to finish loading. - // Check that the tab's id matches the tab we opened, - // and that the tab is done loading. - if (tabId != targetId || changedProps.status != "complete") - return; - - // Passing the above test means this is the event we were waiting for. - // There is nothing we need to do for future onUpdated events, so we - // use removeListner to stop getting called when onUpdated events fire. - chrome.tabs.onUpdated.removeListener(listener); - - // Look through all views to find the window which will display - // the screenshot. The url of the tab which will display the - // screenshot includes a query parameter with a unique id, which - // ensures that exactly one view will have the matching URL. - var views = chrome.extension.getViews(); - for (var i = 0; i < views.length; i++) { - var view = views[i]; - if (view.location.href == viewTabUrl) { - view.setScreenshotUrl(screenshotUrl); - break; - } - } - }); - - chrome.tabs.create({url: viewTabUrl}, function(tab) { - targetId = tab.id; - }); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.png b/chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.png deleted file mode 100644 index 37c5c04..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json b/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json deleted file mode 100644 index 2fae69d..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "Test Screenshot Extension", - "version": "1.3", - "description": "Demonstrate screenshot functionality in the chrome.tabs api.", - "background": { - "persistent": false, - "scripts": ["background.js"] - }, - "browser_action": { - "default_icon": "camera.png", - "default_title": "Take a screen shot!" - }, - "permissions": [ - "activeTab" - ], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html b/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html deleted file mode 100644 index 46d7e4d4..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html +++ /dev/null
@@ -1,10 +0,0 @@ -<html> -<script src="screenshot.js"></script> -<body> - Image here: - <p> - <img id="target" src="white.png" height="480"> - <p> - End image - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js b/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js deleted file mode 100644 index cf83d334..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright (c) 2011 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. - -function setScreenshotUrl(url) { - document.getElementById('target').src = url; -}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/white.png b/chrome/common/extensions/docs/examples/api/tabs/screenshot/white.png deleted file mode 100644 index 52b9a9f..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/screenshot/white.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/README b/chrome/common/extensions/docs/examples/api/tabs/zoom/README deleted file mode 100644 index caa44686..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/README +++ /dev/null
@@ -1,2 +0,0 @@ -Demo Chrome Extension that uses the Tab Zoom API. Demonstrates manipulation of -tab zoom levels and zoom modes and use of zoom-change event listeners.
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/background.js b/chrome/common/extensions/docs/examples/api/tabs/zoom/background.js deleted file mode 100644 index d2c5234..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/background.js +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2014 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. - -/** - * @fileoverview In this extension, the background page demonstrates how to - * listen for zoom change events. -*/ - -function zoomChangeListener(zoomChangeInfo) { - var settings_str = "mode:" + zoomChangeInfo.zoomSettings.mode + - ", scope:" + zoomChangeInfo.zoomSettings.scope; - - console.log('[ZoomDemoExtension] zoomChangeListener(tab=' + - zoomChangeInfo.tabId + ', new=' + - zoomChangeInfo.newZoomFactor + ', old=' + - zoomChangeInfo.oldZoomFactor + ', ' + - settings_str + ')'); -} - -chrome.tabs.onZoomChange.addListener(zoomChangeListener);
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/manifest.json b/chrome/common/extensions/docs/examples/api/tabs/zoom/manifest.json deleted file mode 100644 index 51db85b..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/manifest.json +++ /dev/null
@@ -1,24 +0,0 @@ -{ - "manifest_version": 2, - - "name": "Tabs Zoom API Demo", - "description": "This extension allows the user to explore features of the new tabs zoom api.", - - "version": "0.1", - - "icons": { - "16": "zoom16.png", - "48": "zoom48.png" - }, - - "background": { - "scripts": ["background.js"], - "persistent": false - }, - - "browser_action": { - "default_icon": "zoom19.png", - "default_title": "Zoom Extension Demo", - "default_popup": "popup.html" - } -}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/popup.html b/chrome/common/extensions/docs/examples/api/tabs/zoom/popup.html deleted file mode 100644 index 8b7f276..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/popup.html +++ /dev/null
@@ -1,55 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Tab Zoom Extension</title> - <style> - body { - width: 150px; - overflow-x: hidden; - color: #ffff00; - background-color: #186464; - } - - img { - margin: 5px; - border: 2px solid black; - vertical-align: middle; - width: 19px; - height: 19px; - } - </style> - <script src="popup.js"></script> - </head> - <body> - <div style="text-align: center"> - <table style="margin: 0px auto"> - <tr> - <td><button type="button" id="decreaseButton">-</button></td> - <td><div style="width: 50px; border-style: solid; border-width: 1px" - id="displayDiv">100%</div></td> - <td><button type="button" id="increaseButton">+</button></td> - </td> - </table> - <button type="button" id="defaultButton">Reset to Default</button> - <div id="defaultLabel"></div> - </div> - <p> - <div style="border-width: 2px; border-style: solid; border-color: #7f0000; padding: 2px"> - <form style="border-width: 2px; border-style: solid; border-color: #7f0000"> - <b>Mode:</b><br> - <input type="radio" name="modeRadio" value="automatic">automatic<br> - <input type="radio" name="modeRadio" value="manual">manual<br> - <input type="radio" name="modeRadio" value="disabled">disabled - </form><br> - <form style="border-width: 2px; border-style: solid; border-color: #7f0000"> - <b>Scope:</b><br> - <input type="radio" name="scopeRadio" value="per-origin">per-origin<br> - <input type="radio" name="scopeRadio" value="per-tab">per-tab - </form> - <button type="button" id="setModeButton">Set Zoom Settings</button> - </div> - <p> - <button type="button" id="closeButton">Close</button> - </body> -</html> -
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/popup.js b/chrome/common/extensions/docs/examples/api/tabs/zoom/popup.js deleted file mode 100644 index c680d5d..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/popup.js +++ /dev/null
@@ -1,141 +0,0 @@ -// Copyright 2014 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. - -/** - * @fileoverview This code supports the popup behaviour of the extension, and - * demonstrates how to: - * - * 1) Set the zoom for a tab using tabs.setZoom() - * 2) Read the current zoom of a tab using tabs.getZoom() - * 3) Set the zoom mode of a tab using tabs.setZoomSettings() - * 4) Read the current zoom mode of a tab using - * tabs.getZoomSettings() - * - * It also demonstrates using a zoom change listener to update the - * contents of a control. - */ - -zoomStep = 1.1; -tabId = -1; - -function displayZoomLevel(level) { - var percentZoom = parseFloat(level) * 100; - var zoom_percent_str = percentZoom.toFixed(1) + '%'; - - document.getElementById('displayDiv').textContent = zoom_percent_str; -} - -document.addEventListener('DOMContentLoaded', function() { - // Find the tabId of the current (active) tab. We could just omit the tabId - // parameter in the function calls below, and they would act on the current - // tab by default, but for the purposes of this demo we will always use the - // API with an explicit tabId to demonstrate its use. - chrome.tabs.query({active: true}, function (tabs) { - if (tabs.length > 1) - console.log( - '[ZoomDemoExtension] Query unexpectedly returned more than 1 tab.'); - tabId = tabs[0].id; - - chrome.tabs.getZoomSettings(tabId, function(zoomSettings) { - var modeRadios = document.getElementsByName('modeRadio'); - for (var i = 0; i < modeRadios.length; i++) { - if (modeRadios[i].value == zoomSettings.mode) - modeRadios[i].checked = true; - } - - var scopeRadios = document.getElementsByName('scopeRadio'); - for (var i = 0; i < scopeRadios.length; i++) { - if (scopeRadios[i].value == zoomSettings.scope) - scopeRadios[i].checked = true; - } - - var percentDefaultZoom = - parseFloat(zoomSettings.defaultZoomFactor) * 100; - document.getElementById('defaultLabel').textContent = - 'Default: ' + percentDefaultZoom.toFixed(1) + '%'; - }); - - chrome.tabs.getZoom(tabId, displayZoomLevel); - }); - - document.getElementById('increaseButton').onclick = doZoomIn; - document.getElementById('decreaseButton').onclick = doZoomOut; - document.getElementById('defaultButton').onclick = doZoomDefault; - document.getElementById('setModeButton').onclick = doSetMode; - document.getElementById('closeButton').onclick = doClose; -}); - -function zoomChangeListener(zoomChangeInfo) { - displayZoomLevel(zoomChangeInfo.newZoomFactor); -} - -chrome.tabs.onZoomChange.addListener(zoomChangeListener); - -function changeZoomByFactorDelta(factorDelta) { - if (tabId == -1) - return; - - chrome.tabs.getZoom(tabId, function(zoomFactor) { - var newZoomFactor = factorDelta * zoomFactor; - chrome.tabs.setZoom(tabId, newZoomFactor, function() { - if (chrome.runtime.lastError) - console.log('[ZoomDemoExtension] ' + chrome.runtime.lastError.message); - }); - }); -} - -function doZoomIn() { - changeZoomByFactorDelta(zoomStep); -} - -function doZoomOut() { - changeZoomByFactorDelta(1.0/zoomStep); -} - -function doZoomDefault() { - if (tabId == -1) - return; - - chrome.tabs.setZoom(tabId, 0, function() { - if (chrome.runtime.lastError) - console.log('[ZoomDemoExtension] ' + chrome.runtime.lastError.message); - }); -} - -function doSetMode() { - if (tabId == -1) - return; - - var modeVal; - var modeRadios = document.getElementsByName('modeRadio'); - for (var i = 0; i < modeRadios.length; i++) { - if (modeRadios[i].checked) - modeVal = modeRadios[i].value; - } - - var scopeVal; - var scopeRadios = document.getElementsByName('scopeRadio'); - for (var i = 0; i < scopeRadios.length; i++) { - if (scopeRadios[i].checked) - scopeVal = scopeRadios[i].value; - } - - if (!modeVal || !scopeVal) { - console.log( - '[ZoomDemoExtension] Must specify values for both mode & scope.'); - return; - } - - chrome.tabs.setZoomSettings(tabId, { mode: modeVal, scope: scopeVal }, - function() { - if (chrome.runtime.lastError) { - console.log('[ZoomDemoExtension] doSetMode() error: ' + - chrome.runtime.lastError.message); - } - }); -} - -function doClose() { - self.close(); -}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom16.png b/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom16.png deleted file mode 100644 index d1bdbdd..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom19.png b/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom19.png deleted file mode 100644 index 9f22ce22..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom48.png b/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom48.png deleted file mode 100644 index 8a4663a9..0000000 --- a/chrome/common/extensions/docs/examples/api/tabs/zoom/zoom48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/topsites/basic/icon.png b/chrome/common/extensions/docs/examples/api/topsites/basic/icon.png deleted file mode 100644 index ea42f3f..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/basic/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/topsites/basic/manifest.json b/chrome/common/extensions/docs/examples/api/topsites/basic/manifest.json deleted file mode 100644 index c042c09..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/basic/manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name": "Top Sites", - "version": "1.2", - "description": "Shows the top sites in a browser action", - "permissions": ["topSites"], - "browser_action": { - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/topsites/basic/popup.html b/chrome/common/extensions/docs/examples/api/topsites/basic/popup.html deleted file mode 100644 index 12473076..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/basic/popup.html +++ /dev/null
@@ -1,8 +0,0 @@ -<!DOCTYPE HTML> -<html> - <body> - <h2>Most Visited:</h2> - <div id='mostVisited_div'></div> - <script src='popup.js'></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/topsites/basic/popup.js b/chrome/common/extensions/docs/examples/api/topsites/basic/popup.js deleted file mode 100644 index 5f6761dc..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/basic/popup.js +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2013 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. - -// Event listener for clicks on links in a browser action popup. -// Open the link in a new tab of the current window. -function onAnchorClick(event) { - chrome.tabs.create({ url: event.srcElement.href }); - return false; -} - -// Given an array of URLs, build a DOM list of these URLs in the -// browser action popup. -function buildPopupDom(mostVisitedURLs) { - var popupDiv = document.getElementById('mostVisited_div'); - var ol = popupDiv.appendChild(document.createElement('ol')); - - for (var i = 0; i < mostVisitedURLs.length; i++) { - var li = ol.appendChild(document.createElement('li')); - var a = li.appendChild(document.createElement('a')); - a.href = mostVisitedURLs[i].url; - a.appendChild(document.createTextNode(mostVisitedURLs[i].title)); - a.addEventListener('click', onAnchorClick); - } -} - -chrome.topSites.get(buildPopupDom);
diff --git a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/manifest.json b/chrome/common/extensions/docs/examples/api/topsites/magic8ball/manifest.json deleted file mode 100644 index 84f12ac..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/manifest.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "name": "NTP prototyping extension", - "version": "1.1", - "description": "extension to prototype new NTP designs", - "chrome_url_overrides" : { - "newtab": "newTab.html" - }, - "permissions": [ - "topSites", - "chrome://favicon/" - ], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.css b/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.css deleted file mode 100644 index 6c070fb8..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.css +++ /dev/null
@@ -1,28 +0,0 @@ -/* Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -html { - background-color: #ddd; -} - -#spacer { - height: 200px; -} - -#title { - color: #555; - font-weight: bold; - height: 200px; - vertical-align: middle; -} - -#mostVisitedThumb { - background-repeat: no-repeat; - height: 200px; - margin-left: 20px; - padding-left: 20px; - vertical-align: middle; - width: 212px; -}
diff --git a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.html b/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.html deleted file mode 100644 index 4539728a..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. ---> - -<html> -<meta charset="utf-8"> -<script src="newTab.js"></script> -<link rel="stylesheet" href="newTab.css"> - -<title>New 8ball</title> - -<body> - <center> - <div id="spacer"></div> - <span id='title'>Magic 8 ball says to visit</span> - <a id='mostVisitedThumb'> - <span></span> - </a> - </center> -</body> - -</html>
diff --git a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.js b/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.js deleted file mode 100644 index 69ffad6..0000000 --- a/chrome/common/extensions/docs/examples/api/topsites/magic8ball/newTab.js +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function $(id) { - return document.getElementById(id); -} - -function thumbnailsGotten(data) { - var eightBallWindow = $('mostVisitedThumb'); - var rand = Math.floor(Math.random() * data.length); - eightBallWindow.href = data[rand].url; - eightBallWindow.textContent = data[rand].title; - eightBallWindow.style.backgroundImage = 'url(chrome://favicon/' + - data[rand].url + ')'; -} - -window.onload = function() { - chrome.topSites.get(thumbnailsGotten); -}
diff --git a/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/console_tts_engine.html b/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/console_tts_engine.html deleted file mode 100644 index f142127..0000000 --- a/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/console_tts_engine.html +++ /dev/null
@@ -1,47 +0,0 @@ -<html> -<head> - <title>Console TTS Engine</title> - <style> - body { - font-family: arial, helvetica, sans-serif; - } - table { - text-align: center; - padding: 10px; - } - #text { - text-align: left; - padding: 4px; - border: 1px solid #aaa; - width: 99%; - min-height: 100px; - overflow: auto; - } - </style> - <script type="text/javascript"> - function clearText() { - document.getElementById("text").innerHTML = ""; - } - </script> -</head> -<body> - <table> - <tr> - <th>Voice Name</th> - <th>Language</th> - <th>Rate</th> - <th>Pitch</th> - <th>Volume</th> - </tr> - <tr> - <td id="voiceName"></td> - <td id="lang"></td> - <td id="rate"></td> - <td id="pitch"></td> - <td id="volume"></td> - </tr> - </table> - <button onclick="clearText()">Clear</button> - <p id="text"></p> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/console_tts_engine.js b/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/console_tts_engine.js deleted file mode 100644 index 0d607e43..0000000 --- a/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/console_tts_engine.js +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var timeoutId; -var ttsId = -1; -var ttsWindow; -var milliseconds; -var curOptions; - -function areNewOptions(options) { - var properties = ['voiceName', 'lang', 'rate', 'pitch', 'volume']; - - for (var i = 0; i < properties.length; ++i) { - if (options[properties[i]] != curOptions[properties[i]]) { - return true; - } - } - - return false; -} - -function getTtsElement(element) { - return ttsWindow.document.getElementById(element); -} - -function appendText(text) { - getTtsElement("text").innerHTML += text; -} - -function logOptions() { - getTtsElement("voiceName").innerHTML = curOptions.voiceName; - getTtsElement("lang").innerHTML = curOptions.lang; - getTtsElement("rate").innerHTML = curOptions.rate; - getTtsElement("pitch").innerHTML = curOptions.pitch; - getTtsElement("volume").innerHTML = curOptions.volume; -} - -function logUtterance(utterance, index, sendTtsEvent) { - if (index == utterance.length) { - sendTtsEvent({'type': 'end', 'charIndex': utterance.length}); - return; - } - - appendText(utterance[index]); - - if (utterance[index] == ' ') { - sendTtsEvent({'type': 'word', 'charIndex': index}); - } - else if (utterance[index] == '.' || - utterance[index] == '?' || - utterance[index] == '!') { - sendTtsEvent({'type': 'sentence', 'charIndex': index}); - } - - timeoutId = setTimeout(function() { - logUtterance(utterance, ++index, sendTtsEvent) - }, milliseconds); -} - -var speakListener = function(utterance, options, sendTtsEvent) { - clearTimeout(timeoutId); - - sendTtsEvent({'type': 'start', 'charIndex': 0}); - - if (ttsId == -1) { - // Create a new window that overlaps the bottom 40% of the current window - chrome.windows.getCurrent(function(curWindow) { - chrome.windows.create( - {"url": "console_tts_engine.html", - "focused": false, - "top": Math.round(curWindow.top + 6/10 * curWindow.height), - "left": curWindow.left, - "width": curWindow.width, - "height": Math.round(4/10 * curWindow.height)}, - function(newWindow) { - ttsId = newWindow.id; - ttsWindow = chrome.extension.getViews({"windowId": ttsId})[0]; - - curOptions = options; - logOptions(); - - // Fastest timeout == 1 ms (@ options.rate = 10.0) - milliseconds = 10 / curOptions.rate; - logUtterance(utterance, 0, sendTtsEvent); - } - ); - }); - } else { - if (areNewOptions(options)) { - curOptions = options; - logOptions(); - - milliseconds = 10 / curOptions.rate; - } - - logUtterance(utterance, 0, sendTtsEvent); - } - -}; - -var stopListener = function() { - clearTimeout(timeoutId); -}; - -var removedListener = function(windowId, removeInfo) { - if (ttsId == windowId) { - ttsId = -1; - } -} - -chrome.ttsEngine.onSpeak.addListener(speakListener); -chrome.ttsEngine.onStop.addListener(stopListener); -chrome.windows.onRemoved.addListener(removedListener);
diff --git a/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/manifest.json b/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/manifest.json deleted file mode 100644 index 35be832e..0000000 --- a/chrome/common/extensions/docs/examples/api/ttsEngine/console_tts_engine/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "name": "Console TTS Engine", - "manifest_version": 2, - "version": "2.1", - "description": "A \"silent\" TTS engine that prints text to a small window rather than synthesizing speech.", - "permissions": ["ttsEngine", "tabs"], - "background": { - "persistent": false, - "scripts": ["console_tts_engine.js"] - }, - "tts_engine": { - "voices": [ - { - "voice_name": "Console", - "event_types": ["start", "word", "sentence", "end"] - } - ] - } -}
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/background.js b/chrome/common/extensions/docs/examples/api/water_alarm_notification/background.js deleted file mode 100644 index f3fb248..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/background.js +++ /dev/null
@@ -1,24 +0,0 @@ -// 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. -'use strict'; - -chrome.alarms.onAlarm.addListener(function() { - chrome.browserAction.setBadgeText({text: ''}); - chrome.notifications.create({ - type: 'basic', - iconUrl: 'stay_hydrated.png', - title: 'Time to Hydrate', - message: 'Everyday I\'m Guzzlin\'!', - buttons: [ - {title: 'Keep it Flowing.'} - ], - priority: 0}); -}); - -chrome.notifications.onButtonClicked.addListener(function() { - chrome.storage.sync.get(['minutes'], function(item) { - chrome.browserAction.setBadgeText({text: 'ON'}); - chrome.alarms.create({delayInMinutes: item.minutes}); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water128.png b/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water128.png deleted file mode 100644 index e669740..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water16.png b/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water16.png deleted file mode 100644 index 831d708..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water32.png b/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water32.png deleted file mode 100644 index a12983c0..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water48.png b/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water48.png deleted file mode 100644 index 0af36a5..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/drink_water48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/manifest.json b/chrome/common/extensions/docs/examples/api/water_alarm_notification/manifest.json deleted file mode 100644 index a4832da..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/manifest.json +++ /dev/null
@@ -1,21 +0,0 @@ -{ - "name": "Drink Water Event Popup", - "description": "Demonstrates usage and features of the event page by reminding user to drink water", - "version": "1.0", - "manifest_version": 2, - "permissions": ["alarms", "notifications", "storage"], - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "browser_action": { - "default_title": "Drink Water Event", - "default_popup": "popup.html" - }, - "icons": { - "16": "drink_water16.png", - "32": "drink_water32.png", - "48": "drink_water48.png", - "128": "drink_water128.png" - } -}
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/popup.html b/chrome/common/extensions/docs/examples/api/water_alarm_notification/popup.html deleted file mode 100644 index e792182..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/popup.html +++ /dev/null
@@ -1,44 +0,0 @@ -<!-- 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. --> -<html> - <head> - <title>Water Popup</title> - <style> - body { - text-align: center; - } - - #hydrateImage { - width: 100px; - margin: 5px; - } - - button { - margin: 5px; - outline: none; - } - - button:hover { - outline: #80DEEA dotted thick; - } - </style> - <!-- - - JavaScript and HTML must be in separate files: see our Content Security - - Policy documentation[1] for details and explanation. - - - - [1]: https://developer.chrome.com/extensions/contentSecurityPolicy - --> - </head> - <body> - <img src='./stay_hydrated.png' id='hydrateImage'> - <!-- An Alarm delay of less than the minimum 1 minute will fire - in approximately 1 minute incriments if released --> - <button id='sampleSecond' value='0.1'>Sample Second</button> - <button id='15min' value='15'>15 Minutes</button> - <button id='30min' value='30'>30 Minutes</button> - <button id='cancelAlarm'>Cancel Alarm</button> - <!-- link to non-persistent background script --> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/popup.js b/chrome/common/extensions/docs/examples/api/water_alarm_notification/popup.js deleted file mode 100644 index 2d18c12..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/popup.js +++ /dev/null
@@ -1,25 +0,0 @@ -// 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. -'use strict'; - -function setAlarm(event) { - let minutes = parseFloat(event.target.value); - chrome.browserAction.setBadgeText({text: 'ON'}); - chrome.alarms.create({delayInMinutes: minutes}); - chrome.storage.sync.set({minutes: minutes}); - window.close(); -} - -function clearAlarm() { - chrome.browserAction.setBadgeText({text: ''}); - chrome.alarms.clearAll(); - window.close(); -} - -//An Alarm delay of less than the minimum 1 minute will fire -// in approximately 1 minute incriments if released -document.getElementById('sampleSecond').addEventListener('click', setAlarm); -document.getElementById('15min').addEventListener('click', setAlarm); -document.getElementById('30min').addEventListener('click', setAlarm); -document.getElementById('cancelAlarm').addEventListener('click', clearAlarm);
diff --git a/chrome/common/extensions/docs/examples/api/water_alarm_notification/stay_hydrated.png b/chrome/common/extensions/docs/examples/api/water_alarm_notification/stay_hydrated.png deleted file mode 100644 index c44deee5..0000000 --- a/chrome/common/extensions/docs/examples/api/water_alarm_notification/stay_hydrated.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/_locales/en/messages.json b/chrome/common/extensions/docs/examples/api/webNavigation/basic/_locales/en/messages.json deleted file mode 100644 index e639880..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/_locales/en/messages.json +++ /dev/null
@@ -1,52 +0,0 @@ -{ - "extName": { - "message": "WebNavigation Tech Demo", - "description": "The extension name." - }, - "extDescription": { - "message": "Demonstration of the WebNavigation extension API.", - "description": "The extension description." - }, - - "navigationDescription": { - "message": ", requested $NUM$ times. Loaded in an average of $LOAD$ miliseconds.", - "description": "The message posted in the popup for each stored navigation.", - "placeholders": { - "NUM": { - "content": "$1", - "example": "4 (The number of times this URL was accessed.)" - }, - "LOAD": { - "content": "$2", - "example": "12.345 (The average load time in miliseconds.)" - } - } - }, - - "inHandler": { - "message": "In webNavigation[`%s`] handler: %o", - "description": "Notification displayed for each webNavigation event." - }, - - "inHandlerError": { - "message": "In webNavigation[`%s`] handler: No data!", - "description": "Notification displayed in a webNavigation event handler without data!" - }, - - "errorCommittedWithoutPending": { - "message": "Wha? `onCommitted` for `%s` called, though it's not pending: %o", - "description": "Error logged when `onCommitted` is triggered on a non-pending request." - }, - "errorCompletedWithoutPending": { - "message": "Wha? `onCompleted` for `%s` called, though it's not pending: %o", - "description": "Error logged when `onCompleted` is triggered on a non-pending request." - }, - "errorErrorOccurredWithoutPending": { - "message": "Wha? `onErrorOccurred` for `%s` called, though it's not pending: %o", - "description": "Error logged when `onErrorOccurred` is triggered on a non-pending request." - }, - "errorCommittedWithoutPending": { - "message": "Wha? `onCompleted` for `%s` called, though it's not pending: %o", - "description": "Error logged when `onCompleted` is triggered on a non-pending request." - } -}
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/background.js b/chrome/common/extensions/docs/examples/api/webNavigation/basic/background.js deleted file mode 100644 index a056515..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/background.js +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @filedescription Initializes the extension's background page. - */ - -var nav = new NavigationCollector(); - -var eventList = ['onBeforeNavigate', 'onCreatedNavigationTarget', - 'onCommitted', 'onCompleted', 'onDOMContentLoaded', - 'onErrorOccurred', 'onReferenceFragmentUpdated', 'onTabReplaced', - 'onHistoryStateUpdated']; - -eventList.forEach(function(e) { - chrome.webNavigation[e].addListener(function(data) { - if (typeof data) - console.log(chrome.i18n.getMessage('inHandler'), e, data); - else - console.error(chrome.i18n.getMessage('inHandlerError'), e); - }); -}); - -// Reset the navigation state on startup. We only want to collect data within a -// session. -chrome.runtime.onStartup.addListener(function() { - nav.resetDataStorage(); -});
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/icon.png b/chrome/common/extensions/docs/examples/api/webNavigation/basic/icon.png deleted file mode 100644 index d86677db..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/manifest.json b/chrome/common/extensions/docs/examples/api/webNavigation/basic/manifest.json deleted file mode 100644 index 2c0d435..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "name": "__MSG_extName__", - "version": "0.2", - "description": "__MSG_extDescription__", - "default_locale": "en", - "background": { - "persistent": false, - "scripts": ["navigation_collector.js", "background.js"] - }, - "browser_action": { - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "permissions": [ - "webNavigation", "storage" - ], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/navigation_collector.js b/chrome/common/extensions/docs/examples/api/webNavigation/basic/navigation_collector.js deleted file mode 100644 index 56faa35b..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/navigation_collector.js +++ /dev/null
@@ -1,500 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Implements the NavigationCollector object that powers the extension. - * - * @author mkwst@google.com (Mike West) - */ - -/** - * Collects navigation events, and provides a list of successful requests - * that you can do interesting things with. Calling the constructor will - * automatically bind handlers to the relevant webnavigation API events, - * and to a `getMostRequestedUrls` extension message for internal - * communication between background pages and popups. - * - * @constructor - */ -function NavigationCollector() { - /** - * A list of currently pending requests, implemented as a hash of each - * request's tab ID, frame ID, and URL in order to ensure uniqueness. - * - * @type {Object<string, {start: number}>} - * @private - */ - this.pending_ = {}; - - /** - * A list of completed requests, implemented as a hash of each - * request's tab ID, frame ID, and URL in order to ensure uniqueness. - * - * @type {Object<string, Array<NavigationCollector.Request>>} - * @private - */ - this.completed_ = {}; - - /** - * A list of requests that errored off, implemented as a hash of each - * request's tab ID, frame ID, and URL in order to ensure uniqueness. - * - * @type {Object<string, Array<NavigationCollector.Request>>} - * @private - */ - this.errored_ = {}; - - // Bind handlers to the 'webNavigation' events that we're interested - // in handling in order to build up a complete picture of the whole - // navigation event. - chrome.webNavigation.onCreatedNavigationTarget.addListener( - this.onCreatedNavigationTargetListener_.bind(this)); - chrome.webNavigation.onBeforeNavigate.addListener( - this.onBeforeNavigateListener_.bind(this)); - chrome.webNavigation.onCompleted.addListener( - this.onCompletedListener_.bind(this)); - chrome.webNavigation.onCommitted.addListener( - this.onCommittedListener_.bind(this)); - chrome.webNavigation.onErrorOccurred.addListener( - this.onErrorOccurredListener_.bind(this)); - chrome.webNavigation.onReferenceFragmentUpdated.addListener( - this.onReferenceFragmentUpdatedListener_.bind(this)); - chrome.webNavigation.onHistoryStateUpdated.addListener( - this.onHistoryStateUpdatedListener_.bind(this)); - - // Bind handler to extension messages for communication from popup. - chrome.runtime.onMessage.addListener(this.onMessageListener_.bind(this)); - - this.loadDataStorage_(); -} - -/////////////////////////////////////////////////////////////////////////////// - -/** - * The possible transition types that explain how the navigation event - * was generated (i.e. "The user clicked on a link." or "The user submitted - * a form"). - * - * @see http://code.google.com/chrome/extensions/trunk/history.html - * @enum {string} - */ -NavigationCollector.NavigationType = { - AUTO_BOOKMARK: 'auto_bookmark', - AUTO_SUBFRAME: 'auto_subframe', - FORM_SUBMIT: 'form_submit', - GENERATED: 'generated', - KEYWORD: 'keyword', - KEYWORD_GENERATED: 'keyword_generated', - LINK: 'link', - MANUAL_SUBFRAME: 'manual_subframe', - RELOAD: 'reload', - START_PAGE: 'start_page', - TYPED: 'typed' -}; - -/** - * The possible transition qualifiers: - * - * * CLIENT_REDIRECT: Redirects caused by JavaScript, or a refresh meta tag - * on a page. - * - * * SERVER_REDIRECT: Redirected by the server via a 301/302 response. - * - * * FORWARD_BACK: User used the forward or back buttons to navigate through - * their browsing history. - * - * @enum {string} - */ -NavigationCollector.NavigationQualifier = { - CLIENT_REDIRECT: 'client_redirect', - FORWARD_BACK: 'forward_back', - SERVER_REDIRECT: 'server_redirect' -}; - -/** - * @typedef {{url: string, transitionType: NavigationCollector.NavigationType, - * transitionQualifier: Array<NavigationCollector.NavigationQualifier>, - * openedInNewTab: boolean, source: {frameId: ?number, tabId: ?number}, - * duration: number}} - */ -NavigationCollector.Request; - -/////////////////////////////////////////////////////////////////////////////// - -NavigationCollector.prototype = { - /** - * Returns a somewhat unique ID for a given WebNavigation request. - * - * @param {!{tabId: ?number, frameId: ?number}} data Information - * about the navigation event we'd like an ID for. - * @return {!string} ID created by combining the source tab ID and frame ID - * (or target tab/frame IDs if there's no source), as the API ensures - * that these will be unique across a single navigation event. - * @private - */ - parseId_: function(data) { - return data.tabId + '-' + (data.frameId ? data.frameId : 0); - }, - - - /** - * Creates an empty entry in the pending array if one doesn't already exist, - * and prepopulates the errored and completed arrays for ease of insertion - * later. - * - * @param {!string} id The request's ID, as produced by parseId_. - * @param {!string} url The request's URL. - */ - prepareDataStorage_: function(id, url) { - this.pending_[id] = this.pending_[id] || { - openedInNewTab: false, - source: { - frameId: null, - tabId: null - }, - start: null, - transitionQualifiers: [], - transitionType: null - }; - this.completed_[url] = this.completed_[url] || []; - this.errored_[url] = this.errored_[url] || []; - }, - - - /** - * Retrieves our saved data from storage. - * @private - */ - loadDataStorage_: function() { - chrome.storage.local.get({ - "completed": {}, - "errored": {}, - }, function(storage) { - this.completed_ = storage.completed; - this.errored_ = storage.errored; - }.bind(this)); - }, - - - /** - * Persists our state to the storage API. - * @private - */ - saveDataStorage_: function() { - chrome.storage.local.set({ - "completed": this.completed_, - "errored": this.errored_, - }); - }, - - - /** - * Resets our saved state to empty. - */ - resetDataStorage: function() { - this.completed_ = {}; - this.errored_ = {}; - this.saveDataStorage_(); - // Load again, in case there is an outstanding storage.get request. This - // one will reload the newly-cleared data. - this.loadDataStorage_(); - }, - - - /** - * Handler for the 'onCreatedNavigationTarget' event. Updates the - * pending request with a source frame/tab, and notes that it was opened in a - * new tab. - * - * Pushes the request onto the - * 'pending_' object, and stores it for later use. - * - * @param {!Object} data The event data generated for this request. - * @private - */ - onCreatedNavigationTargetListener_: function(data) { - var id = this.parseId_(data); - this.prepareDataStorage_(id, data.url); - this.pending_[id].openedInNewTab = data.tabId; - this.pending_[id].source = { - tabId: data.sourceTabId, - frameId: data.sourceFrameId - }; - this.pending_[id].start = data.timeStamp; - }, - - - /** - * Handler for the 'onBeforeNavigate' event. Pushes the request onto the - * 'pending_' object, and stores it for later use. - * - * @param {!Object} data The event data generated for this request. - * @private - */ - onBeforeNavigateListener_: function(data) { - var id = this.parseId_(data); - this.prepareDataStorage_(id, data.url); - this.pending_[id].start = this.pending_[id].start || data.timeStamp; - }, - - - /** - * Handler for the 'onCommitted' event. Updates the pending request with - * transition information. - * - * Pushes the request onto the - * 'pending_' object, and stores it for later use. - * - * @param {!Object} data The event data generated for this request. - * @private - */ - onCommittedListener_: function(data) { - var id = this.parseId_(data); - if (!this.pending_[id]) { - console.warn( - chrome.i18n.getMessage('errorCommittedWithoutPending'), - data.url, - data); - } else { - this.prepareDataStorage_(id, data.url); - this.pending_[id].transitionType = data.transitionType; - this.pending_[id].transitionQualifiers = - data.transitionQualifiers; - } - }, - - - /** - * Handler for the 'onReferenceFragmentUpdated' event. Updates the pending - * request with transition information. - * - * Pushes the request onto the - * 'pending_' object, and stores it for later use. - * - * @param {!Object} data The event data generated for this request. - * @private - */ - onReferenceFragmentUpdatedListener_: function(data) { - var id = this.parseId_(data); - if (!this.pending_[id]) { - this.completed_[data.url] = this.completed_[data.url] || []; - this.completed_[data.url].push({ - duration: 0, - openedInNewWindow: false, - source: { - frameId: null, - tabId: null - }, - transitionQualifiers: data.transitionQualifiers, - transitionType: data.transitionType, - url: data.url - }); - this.saveDataStorage_(); - } else { - this.prepareDataStorage_(id, data.url); - this.pending_[id].transitionType = data.transitionType; - this.pending_[id].transitionQualifiers = - data.transitionQualifiers; - } - }, - - - /** - * Handler for the 'onHistoryStateUpdated' event. Updates the pending - * request with transition information. - * - * Pushes the request onto the - * 'pending_' object, and stores it for later use. - * - * @param {!Object} data The event data generated for this request. - * @private - */ - onHistoryStateUpdatedListener_: function(data) { - var id = this.parseId_(data); - if (!this.pending_[id]) { - this.completed_[data.url] = this.completed_[data.url] || []; - this.completed_[data.url].push({ - duration: 0, - openedInNewWindow: false, - source: { - frameId: null, - tabId: null - }, - transitionQualifiers: data.transitionQualifiers, - transitionType: data.transitionType, - url: data.url - }); - this.saveDataStorage_(); - } else { - this.prepareDataStorage_(id, data.url); - this.pending_[id].transitionType = data.transitionType; - this.pending_[id].transitionQualifiers = - data.transitionQualifiers; - } - }, - - - /** - * Handler for the 'onCompleted` event. Pulls the request's data from the - * 'pending_' object, combines it with the completed event's data, and pushes - * a new NavigationCollector.Request object onto 'completed_'. - * - * @param {!Object} data The event data generated for this request. - * @private - */ - onCompletedListener_: function(data) { - var id = this.parseId_(data); - if (!this.pending_[id]) { - console.warn( - chrome.i18n.getMessage('errorCompletedWithoutPending'), - data.url, - data); - } else { - this.completed_[data.url].push({ - duration: (data.timeStamp - this.pending_[id].start), - openedInNewWindow: this.pending_[id].openedInNewWindow, - source: this.pending_[id].source, - transitionQualifiers: this.pending_[id].transitionQualifiers, - transitionType: this.pending_[id].transitionType, - url: data.url - }); - delete this.pending_[id]; - this.saveDataStorage_(); - } - }, - - - /** - * Handler for the 'onErrorOccurred` event. Pulls the request's data from the - * 'pending_' object, combines it with the completed event's data, and pushes - * a new NavigationCollector.Request object onto 'errored_'. - * - * @param {!Object} data The event data generated for this request. - * @private - */ - onErrorOccurredListener_: function(data) { - var id = this.parseId_(data); - if (!this.pending_[id]) { - console.error( - chrome.i18n.getMessage('errorErrorOccurredWithoutPending'), - data.url, - data); - } else { - this.prepareDataStorage_(id, data.url); - this.errored_[data.url].push({ - duration: (data.timeStamp - this.pending_[id].start), - openedInNewWindow: this.pending_[id].openedInNewWindow, - source: this.pending_[id].source, - transitionQualifiers: this.pending_[id].transitionQualifiers, - transitionType: this.pending_[id].transitionType, - url: data.url - }); - delete this.pending_[id]; - this.saveDataStorage_(); - } - }, - - /** - * Handle messages from the popup. - * - * @param {!{type:string}} message The external message to answer. - * @param {!MessageSender} sender Info about the script context that sent - * the message. - * @param {!function} sendResponse Function to call to send a response. - * @private - */ - onMessageListener_: function(message, sender, sendResponse) { - if (message.type === 'getMostRequestedUrls') - sendResponse({result: this.getMostRequestedUrls(message.num)}); - else - sendResponse({}); - }, - -/////////////////////////////////////////////////////////////////////////////// - - /** - * @return {Object<string, NavigationCollector.Request>} The complete list of - * successful navigation requests. - */ - get completed() { - return this.completed_; - }, - - - /** - * @return {Object<string, Navigationcollector.Request>} The complete list of - * unsuccessful navigation requests. - */ - get errored() { - return this.errored_; - }, - - - /** - * Get a list of the X most requested URLs. - * - * @param {number=} num The number of successful navigation requests to - * return. If 0 is passed in, or the argument left off entirely, all - * successful requests are returned. - * @return {Object<string, NavigationCollector.Request>} The list of - * successful navigation requests, sorted in decending order of frequency. - */ - getMostRequestedUrls: function(num) { - return this.getMostFrequentUrls_(this.completed, num); - }, - - - /** - * Get a list of the X most errored URLs. - * - * @param {number=} num The number of unsuccessful navigation requests to - * return. If 0 is passed in, or the argument left off entirely, all - * successful requests are returned. - * @return {Object<string, NavigationCollector.Request>} The list of - * unsuccessful navigation requests, sorted in decending order - * of frequency. - */ - getMostErroredUrls: function(num) { - return this.getMostErroredUrls_(this.errored, num); - }, - - - /** - * Get a list of the most frequent URLs in a list. - * - * @param {NavigationCollector.Request} list A list of URLs to parse. - * @param {number=} num The number of navigation requests to return. If - * 0 is passed in, or the argument left off entirely, all requests - * are returned. - * @return {Object<string, NavigationCollector.Request>} The list of - * navigation requests, sorted in decending order of frequency. - * @private - */ - getMostFrequentUrls_: function(list, num) { - var result = []; - var avg; - // Convert the 'completed_' object to an array. - for (var x in list) { - avg = 0; - if (list.hasOwnProperty(x) && list[x].length) { - list[x].forEach(function(o) { - avg += o.duration; - }); - avg = avg / list[x].length; - result.push({ - url: x, - numRequests: list[x].length, - requestList: list[x], - average: avg - }); - } - } - // Sort the array. - result.sort(function(a, b) { - return b.numRequests - a.numRequests; - }); - // Return the requested number of results. - return num ? result.slice(0, num) : result; - } -};
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.css b/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.css deleted file mode 100644 index e5512260..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.css +++ /dev/null
@@ -1,63 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - - -body { - margin: 5px 10px 10px; -} - -h1 { - color: #53637D; - font: 26px/1.2 Helvetica, sans-serif; - font-size: 200%; - margin: 0; - padding-bottom: 4px; - text-shadow: white 0 1px 2px; -} - -body > section { - border-radius: 5px; - background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #EAEEF3), - -webkit-linear-gradient( - left, #EAEEF3, #EAEEF3 97%, #D3D7DB); - font: 14px/1 Arial,Sans Serif; - padding: 10px; - width: 563px; - max-height: 400px; - overflow-y: auto; - box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5); -} - -body > section > ol { - padding: 0; - margin: 0; - list-style: none inside; -} - -body > section > ol > li { - position: relative; - margin: 0.5em 0 0.5em 40px; -} - -code { - word-wrap: break-word; - background: rgba(255,255,0, 0.5); -} - -em { - position: absolute; - top: 0px; - left: -40px; - width: 30px; - text-align: right; - font: 30px/1 Helvetica, sans-serif; - font-weight: 700; -} - -p { - min-height: 30px; - line-height: 1.2; -}
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.html b/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.html deleted file mode 100644 index 1f518020..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!doctype html> -<!-- - * Copyright (c) 2011 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. ---> -<html> - <head> - <title>WebNavigation Tech Demo Popup</title> - <link href="popup.css" rel="stylesheet" type="text/css"> - </head> - <body> - <h1>Most Requested URLs</h1> - <section></section> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.js b/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.js deleted file mode 100644 index ccb3243..0000000 --- a/chrome/common/extensions/docs/examples/api/webNavigation/basic/popup.js +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * @filedescription Initializes the extension's popup page. - */ - -chrome.runtime.sendMessage( - {'type': 'getMostRequestedUrls'}, - function generateList(response) { - var section = document.querySelector('body>section'); - var results = response.result; - var ol = document.createElement('ol'); - var li, p, em, code, text; - var i; - for (i = 0; i < results.length; i++ ) { - li = document.createElement('li'); - p = document.createElement('p'); - em = document.createElement('em'); - em.textContent = i + 1; - code = document.createElement('code'); - code.textContent = results[i].url; - text = document.createTextNode( - chrome.i18n.getMessage('navigationDescription', - [results[i].numRequests, - results[i].average])); - p.appendChild(em); - p.appendChild(code); - p.appendChild(text); - li.appendChild(p); - ol.appendChild(li); - } - section.innerHTML = ''; - section.appendChild(ol); - });
diff --git a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/display.html b/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/display.html deleted file mode 100644 index 2dfdc4f3..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/display.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Display Screenshot</title> - <style type="text/css"> -body { - background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg=='); - margin: 0; -} - </style> - </head> - <body> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/main.js b/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/main.js deleted file mode 100644 index 91816208..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/main.js +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright (c) 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. - -chrome.app.runtime.onLaunched.addListener(function() { - chrome.app.window.create('test.html', { - innerBounds: { - 'width': 1280, - 'height': 800 - } - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/manifest.json b/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/manifest.json deleted file mode 100644 index 6b27ec4..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/manifest.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "manifest_version": 2, - "name": "Webview transparency", - "description": "Sample of the webview.captureVisibleRegion api", - "version": "1", - "app": { - "background": { - "scripts": ["main.js"] - } - }, - "permissions": [ - "webview" - ], - "webview": { - "partitions": [ - { - "name": "partition", - "accessible_resources": [ "test2.html" ] - } - ] - } -}
diff --git a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test.html b/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test.html deleted file mode 100644 index b5d498048..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <script src="test.js"></script> -<style type="text/css"> -.ib { - position: relative; - display: inline-block; -} -.controls { - margin: 4px; - position: absolute; - right: 0px; - top: 0px; -} -</style> - </head> - <body bgColor='teal'> - <br> - <button id="add_wv">Add webview</button> - <button id="delete_wv">Delete webview</button> - <span><input type="checkbox" id="transparent" checked="checked"><label for="transparent">Transparent</label></span> - <br> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test.js b/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test.js deleted file mode 100644 index c5a92c9..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test.js +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright (c) 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. - -document.addEventListener('DOMContentLoaded', function() { - - var deleteNode = function(node) { - node.parentNode.removeChild(node); - }; - - var deleteAWebview = function() { - deleteNode(document.querySelector('.ib')); - }; - - var findContainer = function(node) { - var container = node; - while (container && !container.classList.contains('ib')) { - container = container.parentElement; - } - return container; - }; - - var handleDelete = function(event) { - var container = findContainer(event.target); - if (container) { - deleteNode(container); - } - }; - - var viewScreenshot = function(wv) { - return function(data) { - chrome.app.window.create('display.html', { - innerBounds: { width: wv.clientWidth, height: wv.clientHeight } - }, - function(aw) { - var d = aw.contentWindow.document; - d.addEventListener('DOMContentLoaded', function() { - var img = d.createElement('img'); - img.src = data; - d.body.appendChild(img); - }); - }); - }; - }; - - var handleScreenshot = function(event) { - var container = findContainer(event.target); - var wv = container.querySelector('webview'); - wv.captureVisibleRegion({format:'png'}, viewScreenshot(wv)); - }; - - var getControls = (function() { - var controls = document.createElement('div'); - controls.className = 'controls'; - controls.innerHTML = '<button id="screenshot">Screenshot</button>' + - '<button id="delete">Delete webview</button>'; - - return function() { - var c = controls.cloneNode(true); - c.querySelector('#delete').addEventListener('click', handleDelete); - c.querySelector('#screenshot'). - addEventListener('click', handleScreenshot); - return c; - }; - })(); - - var createWebview = (function(){ - var id = 0; - return function() { - var wv = document.createElement('webview'); - wv.partition = "partition"; - wv.src = 'test2.html'; - wv.allowtransparency = document.getElementById('transparent').checked; - wv.style.width = "640px"; - wv.style.height = "480px"; - - var container = document.createElement('div'); - container.id = 'wvid0' + id; - id++; - - container.className = 'ib'; - - container.appendChild(wv); - container.appendChild(getControls()); - return container; - }; - })(); - - document.getElementById('delete_wv'). - addEventListener('click', deleteAWebview); - document.getElementById('add_wv'). - addEventListener('click', function() { - document.body.appendChild(createWebview()); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test2.html b/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test2.html deleted file mode 100644 index 6d31d82..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/capturevisibleregion/test2.html +++ /dev/null
@@ -1,9 +0,0 @@ -<!DOCTYPE html> -<html> - <head></head> - <body> - Hello world! - - <button id="newwindow" onclick="window.open('http://www.google.com/');">newwindow</button> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/app.js b/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/app.js deleted file mode 100644 index 0b473f0e..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/app.js +++ /dev/null
@@ -1,165 +0,0 @@ -// Copyright 2018 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. - -'use strict;' - -const kWhitelistedExtensionId = 'dpicdiinminmigempanoghnpckmkfepi'; -const kExtensionIds = [kWhitelistedExtensionId]; - -let portMap = {}; -let webview = null; - -let initScripts = []; - -function createWebView(initScripts) { - let container = document.getElementById('webview-container'); - webview = document.createElement('webview'); - webview.partition = 'partition'; - webview.style = 'width: 640px; height: 400px'; - - webview.addContentScripts([{ - // The value of |embedder| in the script below will persist, and can be - // used by content script injected into the guest any time to send data - // back to us. - name: 'embedderVar', - matches: ['<all_urls>'], - js: {code: 'var embedder = null;\n'}, - all_frames: true, - run_at: 'document_start' - }]); - webview.addContentScripts(initScripts); - - webview.addEventListener('contentload', function() { - webview.executeScript({ - code: 'window.addEventListener(\'message\', function(e){\n' + - ' if (e.data != \'connect\')\n' + - ' return;\n' + - ' console.log(\'msg = \' + e.data);\n' + - ' embedder = e.source;\n' + - ' embedder.postMessage(JSON.stringify({\n' + - ' \'ext_id\' : \'0\',\n' + - ' \'msg\' : \'Hello from guest!\'}), \'*\');\n' + - '});' - }); - // Here we aren't enforcing any particular origin on the guest, but we - // could if security needs required it. - webview.contentWindow.postMessage('connect', '*'); - }); - - addEventListener('message', function(e) { - if (e.source != webview.contentWindow) - return; - - let data; - try { - data = JSON.parse(e.data); - } catch (err) { - console.warn('invalid JSON format for incoming message: ' + err.message); - } - - if (!data) { - console.warn('Malformed message: ' + e.data); - return; - } - - if (data.extensionId) { - if (!data.extensionId in portMap) { - console.warn('Message for unknown extension: ' + data.extensionId); - return; - } - if (!data.request) { - console.warn('malformed messgae (no request):' + e.data); - return; - } - // Relay this to the appropriate extension. - // If the app wants to monitor messages from injected code, this is one - // place to do it. - console.log('Request: ' + data.request + ' => ' + data.extensionId); - portMap[data.extensionId].postMessage({request: data.request}); - } else { - if (!data.msg) { - console.warn('malformed message (no msg): ' + e.data); - } - console.log('Message for us: ' + data.msg); - } - }); - - webview.src = 'http://example.com'; - container.appendChild(webview); -} - -function connectToExtension(extensionId) { - let port; - try { - port = chrome.runtime.connect(extensionId); - } catch (e) { - console.error('Could not connect to extension: ' + e.message); - return; - } - // Save port in map. - portMap[extensionId] = port; - port.onDisconnect.addListener(() => { - delete portMap[extensionId]; - }); - - let initPromise = new Promise((resolve, reject) => { - port.onMessage.addListener(function(msg) { - // Perhaps check here to make sure |msg.code| exists. - console.log('Incoming from extension: ' + msg.name + ' -> ' + msg.code); - if (msg.name == 'ext_getInitScripts') { - initScripts.push({ - name: 'initScripts-' + extensionId, - matches: ['<all_urls>'], - js: {code: msg.code}, - run_at: 'document_start' - }); - resolve(); - } else { - webview.executeScript({code: msg.code}); - } - }); - setTimeout(function() { - reject('Timeout waiting for initScripts from ' + extensionId); - }, 5000); - }); - - port.postMessage({request: 'getInitScripts'}); - - return initPromise; -} - -function setUpExtensionHandlers() { - let port = portMap[kWhitelistedExtensionId]; - // Some examples of UI in the app requesting services from the guest. - // The replies from the extension are injected into the guest and executed - // via the port.onMessage handler declared above. - document.getElementById('magnify_button') - .addEventListener('click', function() { - port.postMessage({request: 'magnify'}); - }); - document.getElementById('background_button') - .addEventListener('click', function() { - port.postMessage({request: 'setBackground'}); - }); - document.getElementById('add_div_button') - .addEventListener('click', function() { - port.postMessage({request: 'addDiv'}); - }); - document.getElementById('iframe_dataurl_button') - .addEventListener('click', function() { - port.postMessage({request: 'iFrameDataURL'}); - }); -} - -document.addEventListener('DOMContentLoaded', function() { - promises = []; - for (let extensionId of kExtensionIds) - promises.push(connectToExtension(extensionId)); - - setUpExtensionHandlers(); - - Promise.all(promises).then(function() { - createWebView(initScripts); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/main.js b/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/main.js deleted file mode 100644 index c512efa1..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/main.js +++ /dev/null
@@ -1,12 +0,0 @@ -// Copyright 2018 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. - -chrome.app.runtime.onLaunched.addListener(function() { - chrome.app.window.create('test.html', { - innerBounds: { - 'width': 1000, - 'height': 800 - } - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/manifest.json b/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/manifest.json deleted file mode 100644 index 340d5901..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "manifest_version": 2, - "name": "WebView Extension Communications Demo: App", - "version": "1", - "app": { - "background": { - "scripts": ["main.js"] - } - }, - "permissions": ["webview"], - "webview": { - "partitions": [ - { - "name": "partition", - "accessible_resources": [""] - } - ] - } -}
diff --git a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/test.html b/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/test.html deleted file mode 100644 index afb3b38..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/comm_demo_app/test.html +++ /dev/null
@@ -1,16 +0,0 @@ -<!DOCTYPE html> -<head> - <script src="app.js"></script> -</head> -<html> - <body bgColor='teal'> - <div id='webview-container'> - </div> - <input type=button value="Magnify" id=magnify_button> - <input type=button value="Background" id=background_button> - <input type=button value="Add Div" id=add_div_button> - <input type=button value="Scripting Data URL in IFrame" - id=iframe_dataurl_button> - <p>Try typing 'm' in the guest window above.</p> - <body> -</html>
diff --git a/chrome/common/extensions/docs/examples/api/webview/comm_demo_ext/background.js b/chrome/common/extensions/docs/examples/api/webview/comm_demo_ext/background.js deleted file mode 100644 index f42e0bb..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/comm_demo_ext/background.js +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2018 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. - -'use strict;' - -// Define globals. - -// This DataURI image will allow us to demonstrate injecting non-html content -// into a guest. -var chromiumLogoDataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABHNCSVQICAgIfAhkiAAACmlJREFUaIG9mmtsXMd1x39n5i53yeVDlESRlERaVEXKqmq7iZW6lZyoTtzYQhuraGK7RSCnTZAoMGw0Sd0U/UQILfqhddqkeRQN0CA2EjT1AwjSvFzYUOyEslzZkS1XimW2jiTqRVkiKT72de/M6Ye7S652l8sl7fgAF7t75szM/3/mzMyZuSu8DTI8fLzpDaKhqWl3y5wGv0UgN0XebiJyqwCsmEnv3Rk1/mizFF5MJd0LZ58+9tpLL+0P32rfstKKu4cPBmuijp1Xr6b+IkqYuwqhLhRqtX2lKhEI1uW/m05Of+kHX3j6OTjgV4Jj2QSGh483/Twb7btaCP4xikz7InirlLVstKgMrL/anJj7y86x9COPP769sBw8yyLwh391bM+VTPDvTqVjKXDLIVASQzjREczs+/E/7/pho5gaIrDvH15JX7iQeCIbmjvjjqvhVGkaCKPKZkq/kzbzVI//v488/rV7ZpfCtiSBP/mbE4Nnx8PDXpKrFzr61RIAsBpeSSXP7Tr4pT0n6+GrS2Dv8NGdk5cTP3UmMFVgKnp/uwkAOHFujZ5733/9yx2HFsO4KIG9w6/unJwMRryC1jB7JwgAiFFaE+d3PvPF25+vhbMmgbs/f2zrhRk9oUHCQJXz35EQWqijROLdajn968989fdfryyvQnf38MHWsVl3yEtg1AuoorXXmXdMAjV2xvWN/N6+R9OVZVUExt/sfFJ8sDoeG0VVEaW2e4rSCL236gKVYO1sy/VPUBE11xD4+NenPtmcNh9EHd57UA8SD2NpHtQKn1+VVI58ZFrvvPX+g3eU6+bZDB/UYOwXMzNQSB1/6QSSaMNIgBqLIIiAR5GKaVN7E1PwjriGr2lXM94b2Pysj6ZeeP37XTx7ILqGwP5vzt3nQnlEgIunT3DpQg6TaAMTzJtJyVoWSJR30p5y7L6phZu3trCpJ8GqtEWA2axj/Eqe18fmOP5GhlwBjAhiBESwIhijgMFYwRiDFJcPkfi3CQQRwVqDBHzir+/d9I15Ao89pvapK5kJCaQdQDTklZFnkaa1ELTHcWZK0Sbz+EvgUwnHvb/bzt5dbTTZGqtW2ffIKUdOZHj++CyIjdszgjFgioSMEQJjMVYQK1gTgxfAWAPOTX7mw91rREQDgMNz2feUwAOoJBjYuo1fvjaKEQM2jWrMVqQUmTGLnk5leF8vfV0BChw9IxwaFUbH4cpc3GlnqzLYDbcOKjf2we/ckGbouhT/eWiO2azEo2ENQWCwgSGwBimCjruJnVYiIU10fvuZ7A7gSAAwE+pny8MCoG1tL02pU4ThDEoCE6QAwWtpHii9ncLf7++lM20Ym4R//YnhjUvVc+TStHBpGkZGhS3rlP23eTasstx7WxvfO5InHyYWvCzxxikmBm4k9pUUQ1cMCMJ0pJ8BPirDBzU4N5qdz+bLeYTZKV576RiaSILtwJgmMIIgJBPwxfu76esK+J+zwsNPCYWoxo5dpYGkVR7ao2zfoFzNKD86WvTyvKfjevEcAVNkYErgjBCGBR2/oyMwM2cKm8s7UV14EskO2le3gQshmkU1nC/749va6OsKGJtkWeBRyEfCwz8Szk1BR4twQ79ircEGgg0M1hqChCWwhsBaTBB/2sAQBJaEMTSnmuX6w7l+M+v9jlr9AKgIGwe3gYvAezTMIC6kowX27mpFicOmYfBlko+Erx80KHD9BkNzwhPYeA6YhCkSiudDovjdSqw31mCNoGJuNt7pogQATJCid/N1gAMc3mXZfWOKJmt4+YxUxXxd8BUFo+PCsbOCNbCxi9jrxmCL3i59GmsWlt2ypryTHSYK/Y6lvNW1vj/egX28Kb17awqAQ6MrB19SjZyM21jfIYgxmCD2rpGF5XqxRqNIf9uot79Wslns8VgGtw/GqYVXBnqSAIyOrxx8SU4W22hrAVjeuV6RAWOksLYR41THGppaEuAdq1otEK/zS2JcpKCknii2kQwU9TUI1EnLhXy3cSrRkugBMGzZtpV4LpQaWBiluigbUy9bvEpkAsulRivYZCud69qZmnUo8Q67qDSIck1r/JmP4jmwVBvlKueazhv1croq6GvVKq7/6wcG+OXZLACD3csHX1m0tTvWTGdBpDqPqieG8JzxRg4vBrgWITFJRi/HHd062MC5cYmiXUOx9vKMLGlcqbKBPWSs8vPFu6wtoxNtFELlxj5lyzpdaH2Z4Id64IaNivPCxau2vnEtkfCoUY1ebNB8XmYLlp/8r+YF2H+bJ2nrHzdrlaYS8OndDgGOjxXI+6Bun7XayOfDI6Z/vOPUco6JJUDP/qIpeXEaNqyCh/YoyaCBm4oy8J/f4+nthItXQk5NpupWqg0+p+dv7zxrDhwQ75Vv19vIak2HQiQ8MhIwk4PtG5S//YhnsDgh60XTUA/83R85tq1XpuYcz50sEARN9RnXECPBowdEvAB8/MuXd2hTy5HGqy9IV7vysZ0R3e1x/8fOCiMnhZPjC5vUmtZ4tdk1pNywMb4eOHc54smRSbZs6a/LeDFO2Wz4m5++I/1K6apB7vtK5pJtkoZ25UppCuD92zzvHfI01ZkPAPkQnnk1yw8PT/Ded/XQ1ta6bPC+EL75px9o6Z4/UiKi9msTD0DqOyshUIjgx68aRkYNN230bF3v6W2HdCqGMJsTzk85jp/O8+Jojpm5iKG+9hWBB3AUPiWSVii7lbj7MbXpK9PnxSTWrYREpcwfZ4lzwHx2GheGeHU0kWf3jl6SiVTNuvXAh4Xo0tgHmnsPiHgou9h6/B5x1hXufjvAlzJvV3qcQ9UVr4sc2wbaVgQewPnsXSXw1xAA+LcHup4r5HNPvBXg1Re2ivch3gvqHZ1pZeO61bXrL9F+oRD+x/4PrnmhXFeVfARtV/f5MGw4wSs/Q9cUr/EI+AjnHdcPdFQnbQ2Ad4XwwtmJU/dV6qtaeuTPBnJ5M7vDF/KusqwcbF3Q8/aK1zjPV1X6uxKs6+yotlsCvM/nwqlc7j0H7ql+AVgz/fvO/RvGLHM3e+8bBluTgFecd/EIhCFDm1Y1dP95DXj1hC7zrs/9wZpztcoXzV+/8eDGVySau1ELuaqRWBI44Oe9H4GP2HZdC+lU6hqbRjwfZqd+41N39hxfzKZuAv7NB7tfzQfZgTCTv9gI6HJQWryh9j6iOaH0bei4xnYpCbPhhcl8OFAPPCxBAOJwmggub8rn5p5cDHAlIC3GvfOKho5t/c0kg0RDXldVMpm5x8auntq0WNiUy7JedN/38Nj7okT6yUQytXjKoeC9w0ceFxVY3Zzllu3dVN691pK5fP5Nn5ve+8CHNtR8oVdLlnWGe/ShvufCnz3dk81M3xuFmYlaNqrxiuOdw4V5BvvblgRfyMxezs5MfXj89tae5YCHt/BnD1TlY1848+7QJv/cJ+xHk0HaqCrqPN55fJinf62yfXNnzbDJZGYV9FthPvdPD961/mURWdFlxcoJlMnwsJrRVWc24e3NKsEtuSi7Q1xu867NbetaOlsiCnrBWn/OGfO8cf7lQjT335c/dN3p8pRgpfL/IYD7eLJbZAcAAAAASUVORK5CYII='; - -var iframeDataURL = - 'data:text/html,' + - '<html>' + - ' <head>' + - ' <script>' + - ' document.addEventListener("DOMContentLoaded", function(){' + - ' document.getElementById("target").innerText = "Fred.";' + - ' });' + - ' </script>' + - ' </head>' + - ' <body>' + - ' <h1>Data URL IFrame</h1>' + - ' <img src="' + chromiumLogoDataURI + '"><br>' + - ' <p>A data-url based iframe that has scripts.</p>' + - ' <p id="target"></p>' + - ' </body>' + - '</html>'; - -let handlers = {}; - -handlers['magnify'] = - 'els = document.getElementsByTagName(\'div\'); ' + - 'for (i = 0; i < els.length; i++) {' + - ' els[i].style.fontSize = "200%";' + - '}' - -handlers['setBackground'] = - 'document.body.style.backgroundColor=\'pink\';'; - -handlers['addDiv'] = - 'el = document.createElement(\'div\'); ' + - 'el.innerText = \'Greetings from the extension!\'; ' + - 'document.body.appendChild(el);'; - -handlers['iFrameDataURL'] = - 'el = document.createElement(\'iframe\');\n' + - 'document.body.appendChild(el);\n' + - 'el.src = \'' + iframeDataURL + '\';'; - -handlers['getInitScripts'] = - 'window.addEventListener(\'keypress\', function(e){\n' + - ' console.log(\'keypress!!\');\n' + - ' if (!embedder)\n' + - ' return;\n' + - ' if (e.keyCode == 109)\n' + - ' embedder.postMessage(JSON.stringify({\n' + - ' \'extensionId\' : \'' + chrome.runtime.id + '\',\n' + - ' \'request\' : \'magnify\'}), \'*\');\n' + - '});'; - -chrome.runtime.onConnectExternal.addListener(function(port) { - port.onMessage.addListener((msg) => { - if (!handlers.hasOwnProperty(msg.request)) { - console.error('Unknown request: ' + msg.request); - return; - } - port.postMessage({code: handlers[msg.request], name: 'ext_' + msg.request}); - }); -});
diff --git a/chrome/common/extensions/docs/examples/api/webview/comm_demo_ext/manifest.json b/chrome/common/extensions/docs/examples/api/webview/comm_demo_ext/manifest.json deleted file mode 100644 index 0869009..0000000 --- a/chrome/common/extensions/docs/examples/api/webview/comm_demo_ext/manifest.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "manifest_version": 2, - - "name": "WebView Extension Communications Demo: Extension", - "description": "Provides content scripts to an app hosting a WebView.", - "version": "1.0", - - "background": { - "scripts": ["background.js"] - }, - "permissions": [ - ] -}
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/NOTICE b/chrome/common/extensions/docs/examples/api/windows/merge_windows/NOTICE deleted file mode 100644 index d86114b..0000000 --- a/chrome/common/extensions/docs/examples/api/windows/merge_windows/NOTICE +++ /dev/null
@@ -1,2 +0,0 @@ -This extension uses icons based on the famfamfam silk series. -http://www.famfamfam.com/lab/icons/silk/ \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.png b/chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.png deleted file mode 100644 index f0da7b15..0000000 --- a/chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/background.js b/chrome/common/extensions/docs/examples/api/windows/merge_windows/background.js deleted file mode 100644 index e9789210..0000000 --- a/chrome/common/extensions/docs/examples/api/windows/merge_windows/background.js +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright (c) 2011 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. - -var targetWindow = null; -var tabCount = 0; - -function start(tab) { - chrome.windows.getCurrent(getWindows); -} - -function getWindows(win) { - targetWindow = win; - chrome.tabs.getAllInWindow(targetWindow.id, getTabs); -} - -function getTabs(tabs) { - tabCount = tabs.length; - // We require all the tab information to be populated. - chrome.windows.getAll({"populate" : true}, moveTabs); -} - -function moveTabs(windows) { - var numWindows = windows.length; - var tabPosition = tabCount; - - for (var i = 0; i < numWindows; i++) { - var win = windows[i]; - - if (targetWindow.id != win.id) { - var numTabs = win.tabs.length; - - for (var j = 0; j < numTabs; j++) { - var tab = win.tabs[j]; - // Move the tab into the window that triggered the browser action. - chrome.tabs.move(tab.id, - {"windowId": targetWindow.id, "index": tabPosition}); - tabPosition++; - } - } - } -} - -// Set up a click handler so that we can merge all the windows. -chrome.browserAction.onClicked.addListener(start);
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json b/chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json deleted file mode 100644 index b5b51737..0000000 --- a/chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "name": "Merge Windows", - "version": "1.0.2", - "description": "Merges all of the browser's windows into the current window", - "icons": { - "48": "merge_windows_48.png", - "128": "merge_windows_128.png" - }, - "background": { - "persistent": false, - "scripts": ["background.js"] - }, - "browser_action": { - "default_icon": "arrow_in.png", - "default_title": "Merge Windows" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.png b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.png deleted file mode 100644 index a37b606..0000000 --- a/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.png b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.png deleted file mode 100644 index 3542c6a..0000000 --- a/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/README b/chrome/common/extensions/docs/examples/apps/background-simple/README deleted file mode 100644 index dc74c5a6..0000000 --- a/chrome/common/extensions/docs/examples/apps/background-simple/README +++ /dev/null
@@ -1,19 +0,0 @@ -This example demonstrates background window functionality in a hosted app. -To run the app, you first need to edit it and install it: - -1. Put index.html and background.html in a directory where the HTTP server - can find them. - -2. Edit manifest.json. Search for SOME_, replacing the text with URLs - pointing to the launch page (index.html) and to the directory where - index.html and background.html live. - -3. Install the app from manifest.json. You can use the Load unpacked extension - button on the chrome://extensions page. - -Once the app is installed, you can launch it by clicking its icon on the -New Tab page. - -For more information, see the documentation: - - http://code.google.com/chrome/apps/docs/developers_guide.html
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/background.html b/chrome/common/extensions/docs/examples/apps/background-simple/background.html deleted file mode 100644 index 7095d3f..0000000 --- a/chrome/common/extensions/docs/examples/apps/background-simple/background.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2009 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. ---> -<html> - <script> - new Notification("Simple Background App", { - body: "A background window has been created" - }); - </script> -</html>
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/index.html b/chrome/common/extensions/docs/examples/apps/background-simple/index.html deleted file mode 100644 index 025c8a6..0000000 --- a/chrome/common/extensions/docs/examples/apps/background-simple/index.html +++ /dev/null
@@ -1,53 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2009 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. ---> -<html> - <head> - <title>Simple Background App</title> - <style> - .hidden { display: none; } - #unsupported { color: #d00; } - </style> - </head> - <body> - <h1>Simple Background App</h1> - <p id="supported" class="hidden"> - <button id="openBackgroundWindow">Open background window</button> - <button id="closeBackgroundWindow">Close background window</button> - </p> - <p id="unsupported" class="hidden"> - You are not using Chrome or have not installed the application for this - page. - </p> - <script src="index.js"></script> - <p> - This app displays a notification - whenever its background window is created. - Background windows and this app are described in the - <a href="http://code.google.com/chrome/apps/docs/developers_guide.html">apps documentation</a>. - </p> - <p> - The generic source code is available for - <a href="http://code.google.com/chrome/extensions/trunk/examples/apps/background-simple.zip">download</a>. - The - <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/docs/examples/apps/background-simple/README">README</a> - tells you how to modify the code. - </p> - <p> - If you just want to run a version of this app that's already on the web, - here's how: - </p> - <ol> - <li> - <a href="http://background-simple.appspot.com/app.crx">Install the app</a> - from background-simple.appspot.com. - </li> - <li> - Launch Simple Background App from the New Tab page. - </li> - </ol> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/index.js b/chrome/common/extensions/docs/examples/apps/background-simple/index.js deleted file mode 100644 index 970810c..0000000 --- a/chrome/common/extensions/docs/examples/apps/background-simple/index.js +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Check for support -if (window.chrome && window.chrome.app && window.chrome.app.isInstalled) { - document.getElementById('supported').className = ''; -} else { - document.getElementById('unsupported').className = ''; -} -var bgWinUrl = "background.html#yay"; -var bgWinName = "bgNotifier"; - -function openBackgroundWindow() { - window.open(bgWinUrl, bgWinName, "background"); -} - -function closeBackgroundWindow() { - var w = window.open(bgWinUrl, bgWinName, "background"); - w.close(); -} - -document.addEventListener('DOMContentLoaded', function() { - document.querySelector('#openBackgroundWindow').addEventListener( - 'click', openBackgroundWindow); - document.querySelector('#closeBackgroundWindow').addEventListener( - 'click', closeBackgroundWindow); -}); \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/apps/background-simple/manifest.json b/chrome/common/extensions/docs/examples/apps/background-simple/manifest.json deleted file mode 100644 index 0861384..0000000 --- a/chrome/common/extensions/docs/examples/apps/background-simple/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "Simple Background App", - "version": "0.2", - "app": { - "urls": [ "http://SOME_SITE_WITHOUT_PORT_NUMBERS/SOME_PATH/" ], - "launch": { - "web_url": "http://SOME_SITE/SOME_PATH/index.html" - } - }, - "permissions": ["background", "notifications"], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/LICENSE b/chrome/common/extensions/docs/examples/apps/calculator/LICENSE deleted file mode 100644 index e6c0d72..0000000 --- a/chrome/common/extensions/docs/examples/apps/calculator/LICENSE +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/chrome/common/extensions/docs/examples/apps/hello-java/HelloLicenseServlet.java b/chrome/common/extensions/docs/examples/apps/hello-java/HelloLicenseServlet.java deleted file mode 100644 index 059f8ad..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-java/HelloLicenseServlet.java +++ /dev/null
@@ -1,120 +0,0 @@ -/* - * Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * The "Hello world!" of the Chrome Web Store Licensing API, in Java. This - * program logs the user in with OpenID, fetches their license state with OAuth, - * and prints one of these greetings as appropriate: - * - * 1. Hello *no* license! - * 2. Hello *free trial* license! - * 3. Hello *full* license! - * - * Brian Kennish <bkennish@chromium.org> - */ -package com.example; - -import com.google.appengine.api.users.*; -import com.google.appengine.repackaged.org.json.JSONObject; - -import java.io.*; -import java.net.*; -import java.util.HashSet; - -import javax.servlet.http.*; - -import oauth.signpost.OAuthConsumer; -import oauth.signpost.basic.DefaultOAuthConsumer; - -/* A Google App Engine servlet. */ -@SuppressWarnings("serial") -public class HelloLicenseServlet extends HttpServlet { - /* TODO: The app ID from the Chrome Developer Dashboard. */ - public static final String APP_ID = "[INSERT APP ID HERE]"; - - /* TODO: The token from the Chrome Developer Dashboard. */ - private static final String TOKEN = "[INSERT TOKEN HERE]"; - - /* TODO: The token secret from the Chrome Developer Dashboard. */ - private static final String TOKEN_SECRET = "[INSERT TOKEN SECRET HERE]"; - - /* - * The license server URL, where %s are placeholders for app and - * user IDs - */ - public static final String SERVER_URL = - "https://www.googleapis.com/chromewebstore/v1/licenses/%s/%s"; - - /* The consumer key. */ - public static final String CONSUMER_KEY = "anonymous"; - - /* The consumer secret. */ - public static final String CONSUMER_SECRET = CONSUMER_KEY; - - /* Handles "GET" requests. */ - public void doGet(HttpServletRequest request, HttpServletResponse response) - throws IOException { - response.setContentType("text/html; charset=UTF-8"); - UserService userService = UserServiceFactory.getUserService(); - PrintWriter output = response.getWriter(); - String url = request.getRequestURI(); - - if (userService.isUserLoggedIn()) { - // Provide a logout path. - User user = userService.getCurrentUser(); - output.printf( - "<strong>%s</strong> | <a href=\"%s\">Sign out</a><br><br>", - user.getEmail(), - userService.createLogoutURL(url) - ); - - try { - // Send a signed request for the user's license state. - OAuthConsumer oauth = - new DefaultOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET); - oauth.setTokenWithSecret(TOKEN, TOKEN_SECRET); - URLConnection http = - new URL( - String.format( - SERVER_URL, - APP_ID, - URLEncoder.encode(user.getFederatedIdentity(), "UTF-8") - ) - ).openConnection(); - oauth.sign(http); - http.connect(); - - // Convert the response from the license server to a string. - BufferedReader input = - new BufferedReader(new InputStreamReader(http.getInputStream())); - String file = ""; - for (String line; (line = input.readLine()) != null; file += line); - input.close(); - - // Parse the string as JSON and display the license state. - JSONObject json = new JSONObject(file); - output.printf( - "Hello <strong>%s</strong> license!", - "YES".equals(json.get("result")) ? - "FULL".equals(json.get("accessLevel")) ? "full" : "free trial" : - "no" - ); - } catch (Exception exception) { - // Dump any error. - output.printf("Oops! <strong>%s</strong>", exception.getMessage()); - } - } else { // The user isn't logged in. - // Prompt for login. - output.printf( - "<a href=\"%s\">Sign in</a>", - userService.createLoginURL( - url, - null, - "https://www.google.com/accounts/o8/id", - new HashSet<String>() - ) - ); - } - } -}
diff --git a/chrome/common/extensions/docs/examples/apps/hello-java/README b/chrome/common/extensions/docs/examples/apps/hello-java/README deleted file mode 100644 index 11ef20c7..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-java/README +++ /dev/null
@@ -1,10 +0,0 @@ -See the documentation at - http://code.google.com/chrome/webstore/docs/get_started.html -for instructions on how to use these files. - -"HelloLicenseServlet.java" contains all the code you need to talk to the Chrome -Web Store Licensing API. - -"workspace" contains a complete Eclipse project, "HelloLicense", which you can -import and deploy to Google App Engine after updating -"HelloLicenseServlet.java".
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/NOTICE b/chrome/common/extensions/docs/examples/apps/hello-php/NOTICE deleted file mode 100644 index 261a4094..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/NOTICE +++ /dev/null
@@ -1,97 +0,0 @@ -====================================================================== -./popuplib.js (PopupManager): -====================================================================== - -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -====================================================================== -./index.php JS templating engine: -====================================================================== - -The MIT License - -Copyright (c) 2010 John Resig - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -====================================================================== -./lib/oauth/ is licensed as follows - (Cf. ../lib/oauth/LICENSE.txt): -====================================================================== - -The MIT License - -Copyright (c) 2007 Andy Smith - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -====================================================================== -./lib/lightopenid/ is licensed as follows - (Cf. ../lib/lightopenid/openid.php): -====================================================================== - -The MIT License - -Copyright (c) 2010, Mewp - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/README b/chrome/common/extensions/docs/examples/apps/hello-php/README deleted file mode 100644 index c6566e92..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/README +++ /dev/null
@@ -1,9 +0,0 @@ -See the documentation at - http://code.google.com/chrome/webstore/docs/get_started.html -for instructions on how to use these files. - -"lib" contains the necessary OAuth and OpenID libraries to talk to the Chrome -Web Store Licensing API and Google's OpenID endpoint. - -To "index.php", replace APP_ID, TOKEN, and TOKEN_SECRET with your app's id, your -developer OAuth access token, and its token secret, respectively.
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/index.php b/chrome/common/extensions/docs/examples/apps/hello-php/index.php deleted file mode 100644 index 8b0d3cf..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/index.php +++ /dev/null
@@ -1,288 +0,0 @@ -<?php -/** - * Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * A "Hello world!" for the Chrome Web Store Licensing API, in PHP. This - * program logs the user in with Google's Federated Login API (OpenID), fetches - * their license state with OAuth, and prints one of these greetings as - * appropriate: - * - * 1. This user has FREE_TRIAL access to this application ( appId: 1 ) - * 2. This user has FULL access to this application ( appId: 1 ) - * 3. This user has NO access to this application ( appId: 1 ) - * - * This code makes use of a popup ui extension to the OpenID protocol. Instead - * of the user being redirected to the Google login page, a popup window opens - * to the login page, keeping the user on the main application page. See - * popuplib.js - * - * Eric Bidelman <ericbidelman@chromium.org> - */ - -session_start(); - -require_once 'lib/oauth/OAuth.php'; -require_once 'lib/lightopenid/openid.php'; - -// Full URL of the current application is running under. -$scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on') ? 'http' : - 'https'; -$selfUrl = "$scheme://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}"; - - -/** - * Wrapper class to make calls to the Chrome Web Store License Server. - */ -class LicenseServerClient { - - const LICENSE_SERVER_HOST = 'https://www.googleapis.com'; - const CONSUMER_KEY = 'anonymous'; - const CONSUMER_SECRET = 'anonymous'; - const APP_ID = '1'; // Change to the correct id of your application. - const TOKEN = '[REPLACE THIS WITH YOUR OAUTH TOKEN]'; - const TOKEN_SECRET = '[REPLACE THIS WITH YOUR OAUTH TOKEN SECRET]'; - public $consumer; - public $token; - public $signatureMethod; - - public function __construct() { - $this->consumer = new OAuthConsumer( - self::CONSUMER_KEY, self::CONSUMER_SECRET, NULL); - $this->token = new OAuthToken(self::TOKEN, self::TOKEN_SECRET); - $this->signatureMethod = new OAuthSignatureMethod_HMAC_SHA1(); - } - - /** - * Makes an HTTP GET request to the specified URL. - * - * @param string $url Full URL of the resource to access - * @param string $request OAuthRequest containing the signed request to make. - * @param array $extraHeaders (optional) Array of headers. - * @param bool $returnResponseHeaders True if resp headers should be returned. - * @return string Response body from the server. - */ - protected function send_signed_get($request, $extraHeaders=NULL, - $returnRequestHeaders=false, - $returnResponseHeaders=false) { - $url = explode('?', $request->to_url()); - $curl = curl_init($url[0]); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_FAILONERROR, false); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - - // Return request headers in the response. - curl_setopt($curl, CURLINFO_HEADER_OUT, $returnRequestHeaders); - - // Return response headers in the response? - if ($returnResponseHeaders) { - curl_setopt($curl, CURLOPT_HEADER, true); - } - - $headers = array($request->to_header()); - if (is_array($extraHeaders)) { - $headers = array_merge($headers, $extraHeaders); - } - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - - // Execute the request. If an error occurs fill the response body with it. - $response = curl_exec($curl); - if (!$response) { - $response = curl_error($curl); - } - - // Add server's response headers to our response body - $response = curl_getinfo($curl, CURLINFO_HEADER_OUT) . $response; - - curl_close($curl); - - return $response; - } - - public function checkLicense($userId) { - $url = self::LICENSE_SERVER_HOST . '/chromewebstore/v1/licenses/' . - self::APP_ID . '/' . urlencode($userId); - - $request = OAuthRequest::from_consumer_and_token( - $this->consumer, $this->token, 'GET', $url, array()); - - $request->sign_request($this->signatureMethod, $this->consumer, - $this->token); - - return $this->send_signed_get($request); - } -} - -try { - $openid = new LightOpenID(); - $userId = $openid->identity; - if (!isset($_GET['openid_mode'])) { - // This section performs the OpenID dance with the normal redirect. Use it - // if you want an alternative to the popup UI. - if (isset($_GET['login'])) { - $openid->identity = 'https://www.google.com/accounts/o8/id'; - $openid->required = array('namePerson/first', 'namePerson/last', - 'contact/email'); - header('Location: ' . $openid->authUrl()); - } - } else if ($_GET['openid_mode'] == 'cancel') { - echo 'User has canceled authentication!'; - } else { - $userId = $openid->validate() ? $openid->identity : ''; - $_SESSION['userId'] = $userId; - $attributes = $openid->getAttributes(); - $_SESSION['attributes'] = $attributes; - } -} catch(ErrorException $e) { - echo $e->getMessage(); - exit; -} - -if (isset($_REQUEST['popup']) && !isset($_SESSION['redirect_to'])) { - $_SESSION['redirect_to'] = $selfUrl; - echo '<script type = "text/javascript">window.close();</script>'; - exit; -} else if (isset($_SESSION['redirect_to'])) { - $redirect = $_SESSION['redirect_to']; - unset($_SESSION['redirect_to']); - header('Location: ' . $redirect); -} else if (isset($_REQUEST['queryLicenseServer'])) { - $ls = new LicenseServerClient(); - echo $ls->checkLicense($_REQUEST['user_id']); - exit; -} else if (isset($_GET['logout'])) { - unset($_SESSION['attributes']); - unset($_SESSION['userId']); - header('Location: ' . $selfUrl); -} -?> - -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8" /> - <link href="main.css" type="text/css" rel="stylesheet" /> - <script type="text/javascript" src="popuplib.js"></script> - <script type="text/html" id="ls_tmpl"> - <div id="access-level"> - <% if (result.toLowerCase() == 'yes') { %> - This user has <span class="<%= accessLevel.toLowerCase() %>"><%= accessLevel %></span> access to this application ( appId: <%= appId %> ) - <% } else { %> - This user has <span class="<%= result.toLowerCase() %>"><%= result %></span> access to this application ( appId: <%= appId %> ) - <% } %> - </div> - </script> - </head> - <body> - <nav> - <?php if (!isset($_SESSION['userId'])): ?> - <a href="javascript:" onclick="openPopup(450, 500, this);">Sign in</a> - <?php else: ?> - <span>Welcome <?php echo @$_SESSION['attributes']['namePerson/first'] ?> <?php echo @$_SESSION['attributes']['namePerson/last'] ?> ( <?php echo $_SESSION['attributes']['contact/email'] ?> )</span> - <a href="?logout">Sign out</a> - <?php endif; ?> - </nav> - <?php if (isset($_SESSION['attributes'])): ?> - <div id="container"> - <form action="<?php echo "$selfUrl?queryLicenseServer" ?>" onsubmit="return queryLicenseServer(this);"> - <input type="hidden" id="user_id" name="user_id" value="<?php echo $_SESSION['userId'] ?>" /> - <input type="submit" value="Check user's access" /> - </form> - <div id="license-server-response"></div> - </div> - <?php endif; ?> - <script> - // Simple JavaScript Templating - // John Resig - http://ejohn.org/ - MIT Licensed - (function(){ - var cache = {}; - - this.tmpl = function tmpl(str, data){ - // Figure out if we're getting a template, or if we need to - // load the template - and be sure to cache the result. - var fn = !/\W/.test(str) ? - cache[str] = cache[str] || - tmpl(document.getElementById(str).innerHTML) : - - // Generate a reusable function that will serve as a template - // generator (and which will be cached). - new Function("obj", - "var p=[],print=function(){p.push.apply(p,arguments);};" + - - // Introduce the data as local variables using with(){} - "with(obj){p.push('" + - - // Convert the template into pure JavaScript - str - .replace(/[\r\t\n]/g, " ") - .split("<%").join("\t") - .replace(/((^|%>)[^\t]*)'/g, "$1\r") - .replace(/\t=(.*?)%>/g, "',$1,'") - .split("\t").join("');") - .split("%>").join("p.push('") - .split("\r").join("\\'") - + "');}return p.join('');"); - - // Provide some basic currying to the user - return data ? fn( data ) : fn; - }; - })(); - - function queryLicenseServer(form) { - var userId = form.user_id.value; - - if (!userId) { - alert('No OpenID specified!'); - return false; - } - - var req = new XMLHttpRequest(); - req.onreadystatechange = function(e) { - if (this.readyState == 4) { - var resp = JSON.parse(this.responseText); - var el = document.getElementById('license-server-response'); - if (resp.error) { - el.innerHTML = ['<div class="error">Error ', resp.error.code, - ': ', resp.error.message, '</div>'].join(''); - } else { - el.innerHTML = tmpl('ls_tmpl', resp); - } - } - }; - var url = - [form.action, '&user_id=', encodeURIComponent(userId)].join(''); - req.open('GET', url, true); - req.send(null); - - return false; - } - - function openPopup(w, h, link) { - var extensions = { - 'openid.ns.ext1': 'http://openid.net/srv/ax/1.0', - 'openid.ext1.mode': 'fetch_request', - 'openid.ext1.type.email': 'http://axschema.org/contact/email', - 'openid.ext1.type.first': 'http://axschema.org/namePerson/first', - 'openid.ext1.type.last': 'http://axschema.org/namePerson/last', - 'openid.ext1.required': 'email,first,last', - 'openid.ui.icon': 'true' - }; - - var googleOpener = popupManager.createPopupOpener({ - opEndpoint: 'https://www.google.com/accounts/o8/ud', - returnToUrl: '<?php echo "$selfUrl?popup=true" ?>', - onCloseHandler: function() { - window.location = '<?php echo $selfUrl ?>'; - }, - shouldEncodeUrls: false, - extensions: extensions - }); - link.parentNode.appendChild( - document.createTextNode('Authenticating...')); - link.parentNode.removeChild(link); - googleOpener.popup(w, h); - } - </script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/lib/lightopenid/openid.php b/chrome/common/extensions/docs/examples/apps/hello-php/lib/lightopenid/openid.php deleted file mode 100644 index 4fa6cdc..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/lib/lightopenid/openid.php +++ /dev/null
@@ -1,563 +0,0 @@ -<?php -/** - * This class provides a simple interface for OpenID (1.1 and 2.0) authentication. - * Supports Yadis discovery. - * The authentication process is stateless/dumb. - * - * Usage: - * Sign-on with OpenID is a two step process: - * Step one is authentication with the provider: - * <code> - * $openid = new LightOpenID; - * $openid->identity = 'ID supplied by user'; - * header('Location: ' . $openid->authUrl()); - * </code> - * The provider then sends various parameters via GET, one of them is openid_mode. - * Step two is verification: - * <code> - * if ($this->data['openid_mode']) { - * $openid = new LightOpenID; - * echo $openid->validate() ? 'Logged in.' : 'Failed'; - * } - * </code> - * - * Optionally, you can set $returnUrl and $realm (or $trustRoot, which is an alias). - * The default values for those are: - * $openid->realm = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; - * $openid->returnUrl = $openid->realm . $_SERVER['REQUEST_URI']; - * If you don't know their meaning, refer to any openid tutorial, or specification. Or just guess. - * - * AX and SREG extensions are supported. - * To use them, specify $openid->required and/or $openid->optional. - * These are arrays, with values being AX schema paths (the 'path' part of the URL). - * For example: - * $openid->required = array('namePerson/friendly', 'contact/email'); - * $openid->optional = array('namePerson/first'); - * If the server supports only SREG or OpenID 1.1, these are automaticaly - * mapped to SREG names, so that user doesn't have to know anything about the server. - * - * To get the values, use $openid->getAttributes(). - * - * - * The library depends on curl, and requires PHP 5. - * @author Mewp - * @copyright Copyright (c) 2010, Mewp - * @license http://www.opensource.org/licenses/mit-license.php MIT - */ -class LightOpenID -{ - public $returnUrl - , $required = array() - , $optional = array(); - private $identity, $claimed_id; - protected $server, $version, $trustRoot, $aliases, $identifier_select = false - , $ax = false, $sreg = false, $data; - static protected $ax_to_sreg = array( - 'namePerson/friendly' => 'nickname', - 'contact/email' => 'email', - 'namePerson' => 'fullname', - 'birthDate' => 'dob', - 'person/gender' => 'gender', - 'contact/postalCode/home' => 'postcode', - 'contact/country/home' => 'country', - 'pref/language' => 'language', - 'pref/timezone' => 'timezone', - ); - - function __construct() - { - $this->trustRoot = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST']; - $this->returnUrl = $this->trustRoot . $_SERVER['REQUEST_URI']; - - if (!function_exists('curl_exec')) { - throw new ErrorException('Curl extension is required.'); - } - - $this->data = $_POST + $_GET; # OPs may send data as POST or GET. - } - - function __set($name, $value) - { - switch ($name) { - case 'identity': - if (strlen($value = trim($value))) { - if (preg_match('#^xri:/*#i', $value, $m)) { - $value = substr($value, strlen($m[0])); - } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) { - $value = "http://$value"; - } - if (preg_match('#^https?://[^/]+$#i', $value, $m)) { - $value .= '/'; - } - } - $this->$name = $this->claimed_id = $value; - break; - case 'trustRoot': - case 'realm': - $this->trustRoot = trim($value); - } - } - - function __get($name) - { - switch ($name) { - case 'identity': - # We return claimed_id instead of identity, - # because the developer should see the claimed identifier, - # i.e. what they set as identity, not the op-local identifier (which is what we verify) - return $this->claimed_id; - case 'trustRoot': - case 'realm': - return $this->trustRoot; - } - } - - protected function request($url, $method='GET', $params=array()) - { - $params = http_build_query($params, '', '&'); - $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : '')); - curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); - curl_setopt($curl, CURLOPT_HEADER, false); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - if ($method == 'POST') { - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, $params); - } elseif ($method == 'HEAD') { - curl_setopt($curl, CURLOPT_HEADER, true); - curl_setopt($curl, CURLOPT_NOBODY, true); - } else { - curl_setopt($curl, CURLOPT_HTTPGET, true); - } - $response = curl_exec($curl); - - if (curl_errno($curl)) { - throw new ErrorException(curl_error($curl), curl_errno($curl)); - } - - return $response; - } - - protected function build_url($url, $parts) - { - if (isset($url['query'], $parts['query'])) { - $parts['query'] = $url['query'] . '&' . $parts['query']; - } - - $url = $parts + $url; - $url = $url['scheme'] . '://' - . (empty($url['username'])?'' - :(empty($url['password'])? "{$url['username']}@" - :"{$url['username']}:{$url['password']}@")) - . $url['host'] - . (empty($url['port'])?'':":{$url['port']}") - . (empty($url['path'])?'':$url['path']) - . (empty($url['query'])?'':"?{$url['query']}") - . (empty($url['fragment'])?'':":{$url['fragment']}"); - return $url; - } - - /** - * Helper function used to scan for <meta>/<link> tags and extract information - * from them - */ - protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName) - { - preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1); - preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2); - - $result = array_merge($matches1[1], $matches2[1]); - return empty($result)?false:$result[0]; - } - - /** - * Performs Yadis and HTML discovery. Normally not used. - * @param $url Identity URL. - * @return String OP Endpoint (i.e. OpenID provider address). - * @throws ErrorException - */ - function discover($url) - { - if (!$url) throw new ErrorException('No identity supplied.'); - # Use xri.net proxy to resolve i-name identities - if (!preg_match('#^https?:#', $url)) { - $url = "https://xri.net/$url"; - } - - # We save the original url in case of Yadis discovery failure. - # It can happen when we'll be lead to an XRDS document - # which does not have any OpenID2 services. - $originalUrl = $url; - - # A flag to disable yadis discovery in case of failure in headers. - $yadis = true; - - # We'll jump a maximum of 5 times, to avoid endless redirections. - for ($i = 0; $i < 5; $i ++) { - if ($yadis) { - $headers = explode("\n",$this->request($url, 'HEAD')); - - $next = false; - foreach ($headers as $header) { - if (preg_match('#X-XRDS-Location\s*:\s*(.*)#', $header, $m)) { - $url = $this->build_url(parse_url($url), parse_url(trim($m[1]))); - $next = true; - } - - if (preg_match('#Content-Type\s*:\s*application/xrds\+xml#i', $header)) { - # Found an XRDS document, now let's find the server, and optionally delegate. - $content = $this->request($url, 'GET'); - - # OpenID 2 - # We ignore it for MyOpenID, as it breaks sreg if using OpenID 2.0 - $ns = preg_quote('http://specs.openid.net/auth/2.0/'); - if (preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'(.*?)\s*</Type>(.*)</Service>#s', $content, $m)) { - $content = ' ' . $m[1] . $m[3]; # The space is added, so that strpos doesn't return 0. - if ($m[2] == 'server') $this->identifier_select = true; - - preg_match('#<URI.*?>(.*)</URI>#', $content, $server); - preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $content, $delegate); - if (empty($server)) { - return false; - } - # Does the server advertise support for either AX or SREG? - $this->ax = (bool) strpos($content, '<Type>http://openid.net/srv/ax/1.0</Type>'); - $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>') - || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>'); - - $server = $server[1]; - if (isset($delegate[2])) $this->identity = trim($delegate[2]); - $this->version = 2; - - $this->server = $server; - return $server; - } - - # OpenID 1.1 - $ns = preg_quote('http://openid.net/signon/1.1'); - if (preg_match('#<Service.*?>(.*)<Type>\s*'.$ns.'\s*</Type>(.*)</Service>#s', $content, $m)) { - $content = ' ' . $m[1] . $m[2]; - - preg_match('#<URI.*?>(.*)</URI>#', $content, $server); - preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate); - if (empty($server)) { - return false; - } - # AX can be used only with OpenID 2.0, so checking only SREG - $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>') - || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>'); - - $server = $server[1]; - if (isset($delegate[1])) $this->identity = $delegate[1]; - $this->version = 1; - - $this->server = $server; - return $server; - } - - $next = true; - $yadis = false; - $url = $originalUrl; - $content = null; - break; - } - } - if ($next) continue; - - # There are no relevant information in headers, so we search the body. - $content = $this->request($url, 'GET'); - if ($location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'value')) { - $url = $this->build_url(parse_url($url), parse_url($location)); - continue; - } - } - - if (!$content) $content = $this->request($url, 'GET'); - - # At this point, the YADIS Discovery has failed, so we'll switch - # to openid2 HTML discovery, then fallback to openid 1.1 discovery. - $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href'); - $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href'); - $this->version = 2; - - if (!$server) { - # The same with openid 1.1 - $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href'); - $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href'); - $this->version = 1; - } - - if ($server) { - # We found an OpenID2 OP Endpoint - if ($delegate) { - # We have also found an OP-Local ID. - $this->identity = $delegate; - } - $this->server = $server; - return $server; - } - - throw new ErrorException('No servers found!'); - } - throw new ErrorException('Endless redirection!'); - } - - protected function sregParams() - { - $params = array(); - # We always use SREG 1.1, even if the server is advertising only support for 1.0. - # That's because it's fully backwards compatibile with 1.0, and some providers - # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com - $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1'; - if ($this->required) { - $params['openid.sreg.required'] = array(); - foreach ($this->required as $required) { - if (!isset(self::$ax_to_sreg[$required])) continue; - $params['openid.sreg.required'][] = self::$ax_to_sreg[$required]; - } - $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']); - } - - if ($this->optional) { - $params['openid.sreg.optional'] = array(); - foreach ($this->optional as $optional) { - if (!isset(self::$ax_to_sreg[$optional])) continue; - $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional]; - } - $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']); - } - return $params; - } - protected function axParams() - { - $params = array(); - if ($this->required || $this->optional) { - $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0'; - $params['openid.ax.mode'] = 'fetch_request'; - $this->aliases = array(); - $counts = array(); - $required = array(); - $optional = array(); - foreach (array('required','optional') as $type) { - foreach ($this->$type as $alias => $field) { - if (is_int($alias)) $alias = strtr($field, '/', '_'); - $this->aliases[$alias] = 'http://axschema.org/' . $field; - if (empty($counts[$alias])) $counts[$alias] = 0; - $counts[$alias] += 1; - ${$type}[] = $alias; - } - } - foreach ($this->aliases as $alias => $ns) { - $params['openid.ax.type.' . $alias] = $ns; - } - foreach ($counts as $alias => $count) { - if ($count == 1) continue; - $params['openid.ax.count.' . $alias] = $count; - } - - # Don't send empty ax.requied and ax.if_available. - # Google and possibly other providers refuse to support ax when one of these is empty. - if($required) { - $params['openid.ax.required'] = implode(',', $required); - } - if($optional) { - $params['openid.ax.if_available'] = implode(',', $optional); - } - } - return $params; - } - - protected function authUrl_v1() - { - $returnUrl = $this->returnUrl; - # If we have an openid.delegate that is different from our claimed id, - # we need to somehow preserve the claimed id between requests. - # The simplest way is to just send it along with the return_to url. - if($this->identity != $this->claimed_id) { - $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id; - } - - $params = array( - 'openid.return_to' => $returnUrl, - 'openid.mode' => 'checkid_setup', - 'openid.identity' => $this->identity, - 'openid.trust_root' => $this->trustRoot, - ) + $this->sregParams(); - - return $this->build_url(parse_url($this->server) - , array('query' => http_build_query($params, '', '&'))); - } - - protected function authUrl_v2($identifier_select) - { - $params = array( - 'openid.ns' => 'http://specs.openid.net/auth/2.0', - 'openid.mode' => 'checkid_setup', - 'openid.return_to' => $this->returnUrl, - 'openid.realm' => $this->trustRoot, - ); - if ($this->ax) { - $params += $this->axParams(); - } - if ($this->sreg) { - $params += $this->sregParams(); - } - if (!$this->ax && !$this->sreg) { - # If OP doesn't advertise either SREG, nor AX, let's send them both - # in worst case we don't get anything in return. - $params += $this->axParams() + $this->sregParams(); - } - - if ($identifier_select) { - $params['openid.identity'] = $params['openid.claimed_id'] - = 'http://specs.openid.net/auth/2.0/identifier_select'; - } else { - $params['openid.identity'] = $this->identity; - $params['openid.claimed_id'] = $this->claimed_id; - } - - return $this->build_url(parse_url($this->server) - , array('query' => http_build_query($params, '', '&'))); - } - - /** - * Returns authentication url. Usually, you want to redirect your user to it. - * @return String The authentication url. - * @param String $select_identifier Whether to request OP to select identity for an user in OpenID 2. Does not affect OpenID 1. - * @throws ErrorException - */ - function authUrl($identifier_select = null) - { - if (!$this->server) $this->discover($this->identity); - - if ($this->version == 2) { - if ($identifier_select === null) { - return $this->authUrl_v2($this->identifier_select); - } - return $this->authUrl_v2($identifier_select); - } - return $this->authUrl_v1(); - } - - /** - * Performs OpenID verification with the OP. - * @return Bool Whether the verification was successful. - * @throws ErrorException - */ - function validate() - { - $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity']; - $params = array( - 'openid.assoc_handle' => $this->data['openid_assoc_handle'], - 'openid.signed' => $this->data['openid_signed'], - 'openid.sig' => $this->data['openid_sig'], - ); - - if (isset($this->data['openid_op_endpoint'])) { - # We're dealing with an OpenID 2.0 server, so let's set an ns - # Even though we should know location of the endpoint, - # we still need to verify it by discovery, so $server is not set here - $params['openid.ns'] = 'http://specs.openid.net/auth/2.0'; - } - $server = $this->discover($this->data['openid_identity']); - - foreach (explode(',', $this->data['openid_signed']) as $item) { - # Checking whether magic_quotes_gpc is turned on, because - # the function may fail if it is. For example, when fetching - # AX namePerson, it might containg an apostrophe, which will be escaped. - # In such case, validation would fail, since we'd send different data than OP - # wants to verify. stripslashes() should solve that problem, but we can't - # use it when magic_quotes is off. - $value = $this->data['openid_' . str_replace('.','_',$item)]; - $params['openid.' . $item] = get_magic_quotes_gpc() ? stripslashes($value) : $value; - } - - $params['openid.mode'] = 'check_authentication'; - - $response = $this->request($server, 'POST', $params); - - return preg_match('/is_valid\s*:\s*true/i', $response); - } - protected function getAxAttributes() - { - $alias = null; - if (isset($this->data['openid_ns_ax']) - && $this->data['openid_ns_ax'] != 'http://openid.net/srv/ax/1.0' - ) { # It's the most likely case, so we'll check it before - $alias = 'ax'; - } else { - # 'ax' prefix is either undefined, or points to another extension, - # so we search for another prefix - foreach ($this->data as $key => $val) { - if (substr($key, 0, strlen('openid_ns_')) == 'openid_ns_' - && $val == 'http://openid.net/srv/ax/1.0' - ) { - $alias = substr($key, strlen('openid_ns_')); - break; - } - } - } - if (!$alias) { - # An alias for AX schema has not been found, - # so there is no AX data in the OP's response - return array(); - } - - foreach ($this->data as $key => $value) { - $keyMatch = 'openid_' . $alias . '_value_'; - if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { - continue; - } - $key = substr($key, strlen($keyMatch)); - if (!isset($this->data['openid_' . $alias . '_type_' . $key])) { - # OP is breaking the spec by returning a field without - # associated ns. This shouldn't happen, but it's better - # to check, than cause an E_NOTICE. - continue; - } - $key = substr($this->data['openid_' . $alias . '_type_' . $key], - strlen('http://axschema.org/')); - $attributes[$key] = $value; - } - # Found the AX attributes, so no need to scan for SREG. - return $attributes; - } - protected function getSregAttributes() - { - $attributes = array(); - $sreg_to_ax = array_flip(self::$ax_to_sreg); - foreach ($this->data as $key => $value) { - $keyMatch = 'openid_sreg_'; - if (substr($key, 0, strlen($keyMatch)) != $keyMatch) { - continue; - } - $key = substr($key, strlen($keyMatch)); - if (!isset($sreg_to_ax[$key])) { - # The field name isn't part of the SREG spec, so we ignore it. - continue; - } - $attributes[$sreg_to_ax[$key]] = $value; - } - return $attributes; - } - /** - * Gets AX/SREG attributes provided by OP. should be used only after successful validaton. - * Note that it does not guarantee that any of the required/optional parameters will be present, - * or that there will be no other attributes besides those specified. - * In other words. OP may provide whatever information it wants to. - * * SREG names will be mapped to AX names. - * * @return Array Array of attributes with keys being the AX schema names, e.g. 'contact/email' - * @see http://www.axschema.org/types/ - */ - function getAttributes() - { - $attributes; - if (isset($this->data['openid_ns']) - && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0' - ) { # OpenID 2.0 - # We search for both AX and SREG attributes, with AX taking precedence. - return $this->getAxAttributes() + $this->getSregAttributes(); - } - return $this->getSregAttributes(); - } -}
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/CHANGELOG.txt b/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/CHANGELOG.txt deleted file mode 100644 index b12ff1c5..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/CHANGELOG.txt +++ /dev/null
@@ -1,15 +0,0 @@ -== 2008.08.04 == -* Added LICENSE.txt file with MIT license, copyright owner is perhaps - dubious however. -== 2008.07.22 == -* Change to encoding to fix last change to encoding of spaces -== 2008.07.15 == -* Another change to encoding per - http://groups.google.com/group/oauth/browse_thread/thread/d39931d39b4af4bd -* A change to port handling to better deal with https and the like per - http://groups.google.com/group/oauth/browse_thread/thread/1b203a51d9590226 -* Fixed a small bug per - http://code.google.com/p/oauth/issues/detail?id=26 -* Added missing base_string debug info when using RSA-SHA1 -* Increased size of example endpoint input field and added note about - query strings
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/LICENSE.txt b/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/LICENSE.txt deleted file mode 100644 index 89f0591..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/LICENSE.txt +++ /dev/null
@@ -1,22 +0,0 @@ -The MIT License - -Copyright (c) 2007 Andy Smith - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/OAuth.php b/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/OAuth.php deleted file mode 100644 index d32db32..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/lib/oauth/OAuth.php +++ /dev/null
@@ -1,879 +0,0 @@ -<?php -// vim: foldmethod=marker - -/* Generic exception class - */ -class OAuthException extends Exception { - // pass -} - -class OAuthConsumer { - public $key; - public $secret; - - function __construct($key, $secret, $callback_url=NULL) { - $this->key = $key; - $this->secret = $secret; - $this->callback_url = $callback_url; - } - - function __toString() { - return "OAuthConsumer[key=$this->key,secret=$this->secret]"; - } -} - -class OAuthToken { - // access tokens and request tokens - public $key; - public $secret; - - /** - * key = the token - * secret = the token secret - */ - function __construct($key, $secret) { - $this->key = $key; - $this->secret = $secret; - } - - /** - * generates the basic string serialization of a token that a server - * would respond to request_token and access_token calls with - */ - function to_string() { - return "oauth_token=" . - OAuthUtil::urlencode_rfc3986($this->key) . - "&oauth_token_secret=" . - OAuthUtil::urlencode_rfc3986($this->secret); - } - - function __toString() { - return $this->to_string(); - } -} - -/** - * A class for implementing a Signature Method - * See section 9 ("Signing Requests") in the spec - */ -abstract class OAuthSignatureMethod { - /** - * Needs to return the name of the Signature Method (ie HMAC-SHA1) - * @return string - */ - abstract public function get_name(); - - /** - * Build up the signature - * NOTE: The output of this function MUST NOT be urlencoded. - * the encoding is handled in OAuthRequest when the final - * request is serialized - * @param OAuthRequest $request - * @param OAuthConsumer $consumer - * @param OAuthToken $token - * @return string - */ - abstract public function build_signature($request, $consumer, $token); - - /** - * Verifies that a given signature is correct - * @param OAuthRequest $request - * @param OAuthConsumer $consumer - * @param OAuthToken $token - * @param string $signature - * @return bool - */ - public function check_signature($request, $consumer, $token, $signature) { - $built = $this->build_signature($request, $consumer, $token); - return $built == $signature; - } -} - -/** - * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] - * where the Signature Base String is the text and the key is the concatenated values (each first - * encoded per Parameter Encoding) of the Consumer Secret and Token Secret, separated by an '&' - * character (ASCII code 38) even if empty. - * - Chapter 9.2 ("HMAC-SHA1") - */ -class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { - function get_name() { - return "HMAC-SHA1"; - } - - public function build_signature($request, $consumer, $token) { - $base_string = $request->get_signature_base_string(); - $request->base_string = $base_string; - - $key_parts = array( - $consumer->secret, - ($token) ? $token->secret : "" - ); - - $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); - $key = implode('&', $key_parts); - - return base64_encode(hash_hmac('sha1', $base_string, $key, true)); - } -} - -/** - * The PLAINTEXT method does not provide any security protection and SHOULD only be used - * over a secure channel such as HTTPS. It does not use the Signature Base String. - * - Chapter 9.4 ("PLAINTEXT") - */ -class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { - public function get_name() { - return "PLAINTEXT"; - } - - /** - * oauth_signature is set to the concatenated encoded values of the Consumer Secret and - * Token Secret, separated by a '&' character (ASCII code 38), even if either secret is - * empty. The result MUST be encoded again. - * - Chapter 9.4.1 ("Generating Signatures") - * - * Please note that the second encoding MUST NOT happen in the SignatureMethod, as - * OAuthRequest handles this! - */ - public function build_signature($request, $consumer, $token) { - $key_parts = array( - $consumer->secret, - ($token) ? $token->secret : "" - ); - - $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); - $key = implode('&', $key_parts); - $request->base_string = $key; - - return $key; - } -} - -/** - * The RSA-SHA1 signature method uses the RSASSA-PKCS1-v1_5 signature algorithm as defined in - * [RFC3447] section 8.2 (more simply known as PKCS#1), using SHA-1 as the hash function for - * EMSA-PKCS1-v1_5. It is assumed that the Consumer has provided its RSA public key in a - * verified way to the Service Provider, in a manner which is beyond the scope of this - * specification. - * - Chapter 9.3 ("RSA-SHA1") - */ -abstract class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { - public function get_name() { - return "RSA-SHA1"; - } - - // Up to the SP to implement this lookup of keys. Possible ideas are: - // (1) do a lookup in a table of trusted certs keyed off of consumer - // (2) fetch via http using a url provided by the requester - // (3) some sort of specific discovery code based on request - // - // Either way should return a string representation of the certificate - protected abstract function fetch_public_cert(&$request); - - // Up to the SP to implement this lookup of keys. Possible ideas are: - // (1) do a lookup in a table of trusted certs keyed off of consumer - // - // Either way should return a string representation of the certificate - protected abstract function fetch_private_cert(&$request); - - public function build_signature($request, $consumer, $token) { - $base_string = $request->get_signature_base_string(); - $request->base_string = $base_string; - - // Fetch the private key cert based on the request - $cert = $this->fetch_private_cert($request); - - // Pull the private key ID from the certificate - $privatekeyid = openssl_get_privatekey($cert); - - // Sign using the key - $ok = openssl_sign($base_string, $signature, $privatekeyid); - - // Release the key resource - openssl_free_key($privatekeyid); - - return base64_encode($signature); - } - - public function check_signature($request, $consumer, $token, $signature) { - $decoded_sig = base64_decode($signature); - - $base_string = $request->get_signature_base_string(); - - // Fetch the public key cert based on the request - $cert = $this->fetch_public_cert($request); - - // Pull the public key ID from the certificate - $publickeyid = openssl_get_publickey($cert); - - // Check the computed signature against the one passed in the query - $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); - - // Release the key resource - openssl_free_key($publickeyid); - - return $ok == 1; - } -} - -class OAuthRequest { - protected $parameters; - protected $http_method; - protected $http_url; - // for debug purposes - public $base_string; - public static $version = '1.0'; - public static $POST_INPUT = 'php://input'; - - function __construct($http_method, $http_url, $parameters=NULL) { - $parameters = ($parameters) ? $parameters : array(); - $parameters = array_merge( OAuthUtil::parse_parameters(parse_url($http_url, PHP_URL_QUERY)), $parameters); - $this->parameters = $parameters; - $this->http_method = $http_method; - $this->http_url = $http_url; - } - - - /** - * attempt to build up a request from what was passed to the server - */ - public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) { - $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") - ? 'http' - : 'https'; - $http_url = ($http_url) ? $http_url : $scheme . - '://' . $_SERVER['HTTP_HOST'] . - ':' . - $_SERVER['SERVER_PORT'] . - $_SERVER['REQUEST_URI']; - $http_method = ($http_method) ? $http_method : $_SERVER['REQUEST_METHOD']; - - // We weren't handed any parameters, so let's find the ones relevant to - // this request. - // If you run XML-RPC or similar you should use this to provide your own - // parsed parameter-list - if (!$parameters) { - // Find request headers - $request_headers = OAuthUtil::get_headers(); - - // Parse the query-string to find GET parameters - $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']); - - // It's a POST request of the proper content-type, so parse POST - // parameters and add those overriding any duplicates from GET - if ($http_method == "POST" - && isset($request_headers['Content-Type']) - && strstr($request_headers['Content-Type'], - 'application/x-www-form-urlencoded') - ) { - $post_data = OAuthUtil::parse_parameters( - file_get_contents(self::$POST_INPUT) - ); - $parameters = array_merge($parameters, $post_data); - } - - // We have a Authorization-header with OAuth data. Parse the header - // and add those overriding any duplicates from GET or POST - if (isset($request_headers['Authorization']) && substr($request_headers['Authorization'], 0, 6) == 'OAuth ') { - $header_parameters = OAuthUtil::split_header( - $request_headers['Authorization'] - ); - $parameters = array_merge($parameters, $header_parameters); - } - - } - - return new OAuthRequest($http_method, $http_url, $parameters); - } - - /** - * pretty much a helper function to set up the request - */ - public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { - $parameters = ($parameters) ? $parameters : array(); - $defaults = array("oauth_version" => OAuthRequest::$version, - "oauth_nonce" => OAuthRequest::generate_nonce(), - "oauth_timestamp" => OAuthRequest::generate_timestamp(), - "oauth_consumer_key" => $consumer->key); - if ($token) - $defaults['oauth_token'] = $token->key; - - $parameters = array_merge($defaults, $parameters); - - return new OAuthRequest($http_method, $http_url, $parameters); - } - - public function set_parameter($name, $value, $allow_duplicates = true) { - if ($allow_duplicates && isset($this->parameters[$name])) { - // We have already added parameter(s) with this name, so add to the list - if (is_scalar($this->parameters[$name])) { - // This is the first duplicate, so transform scalar (string) - // into an array so we can add the duplicates - $this->parameters[$name] = array($this->parameters[$name]); - } - - $this->parameters[$name][] = $value; - } else { - $this->parameters[$name] = $value; - } - } - - public function get_parameter($name) { - return isset($this->parameters[$name]) ? $this->parameters[$name] : null; - } - - public function get_parameters() { - return $this->parameters; - } - - public function unset_parameter($name) { - unset($this->parameters[$name]); - } - - /** - * The request parameters, sorted and concatenated into a normalized string. - * @return string - */ - public function get_signable_parameters() { - // Grab all parameters - $params = $this->parameters; - - // Remove oauth_signature if present - // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") - if (isset($params['oauth_signature'])) { - unset($params['oauth_signature']); - } - - return OAuthUtil::build_http_query($params); - } - - /** - * Returns the base string of this request - * - * The base string defined as the method, the url - * and the parameters (normalized), each urlencoded - * and the concated with &. - */ - public function get_signature_base_string() { - $parts = array( - $this->get_normalized_http_method(), - $this->get_normalized_http_url(), - $this->get_signable_parameters() - ); - - $parts = OAuthUtil::urlencode_rfc3986($parts); - - return implode('&', $parts); - } - - /** - * just uppercases the http method - */ - public function get_normalized_http_method() { - return strtoupper($this->http_method); - } - - /** - * parses the url and rebuilds it to be - * scheme://host/path - */ - public function get_normalized_http_url() { - $parts = parse_url($this->http_url); - - $scheme = (isset($parts['scheme'])) ? $parts['scheme'] : 'http'; - $port = (isset($parts['port'])) ? $parts['port'] : (($scheme == 'https') ? '443' : '80'); - $host = (isset($parts['host'])) ? $parts['host'] : ''; - $path = (isset($parts['path'])) ? $parts['path'] : ''; - - if (($scheme == 'https' && $port != '443') - || ($scheme == 'http' && $port != '80')) { - $host = "$host:$port"; - } - return "$scheme://$host$path"; - } - - /** - * builds a url usable for a GET request - */ - public function to_url() { - $post_data = $this->to_postdata(); - $out = $this->get_normalized_http_url(); - if ($post_data) { - $out .= '?'.$post_data; - } - return $out; - } - - /** - * builds the data one would send in a POST request - */ - public function to_postdata() { - return OAuthUtil::build_http_query($this->parameters); - } - - /** - * builds the Authorization: header - */ - public function to_header($realm=null) { - $first = true; - if($realm) { - $out = 'Authorization: OAuth realm="' . OAuthUtil::urlencode_rfc3986($realm) . '"'; - $first = false; - } else - $out = 'Authorization: OAuth'; - - $total = array(); - foreach ($this->parameters as $k => $v) { - if (substr($k, 0, 5) != "oauth") continue; - if (is_array($v)) { - throw new OAuthException('Arrays not supported in headers'); - } - $out .= ($first) ? ' ' : ','; - $out .= OAuthUtil::urlencode_rfc3986($k) . - '="' . - OAuthUtil::urlencode_rfc3986($v) . - '"'; - $first = false; - } - return $out; - } - - public function __toString() { - return $this->to_url(); - } - - - public function sign_request($signature_method, $consumer, $token) { - $this->set_parameter( - "oauth_signature_method", - $signature_method->get_name(), - false - ); - $signature = $this->build_signature($signature_method, $consumer, $token); - $this->set_parameter("oauth_signature", $signature, false); - } - - public function build_signature($signature_method, $consumer, $token) { - $signature = $signature_method->build_signature($this, $consumer, $token); - return $signature; - } - - /** - * util function: current timestamp - */ - private static function generate_timestamp() { - return time(); - } - - /** - * util function: current nonce - */ - private static function generate_nonce() { - $mt = microtime(); - $rand = mt_rand(); - - return md5($mt . $rand); // md5s look nicer than numbers - } -} - -class OAuthServer { - protected $timestamp_threshold = 300; // in seconds, five minutes - protected $version = '1.0'; // hi blaine - protected $signature_methods = array(); - - protected $data_store; - - function __construct($data_store) { - $this->data_store = $data_store; - } - - public function add_signature_method($signature_method) { - $this->signature_methods[$signature_method->get_name()] = - $signature_method; - } - - // high level functions - - /** - * process a request_token request - * returns the request token on success - */ - public function fetch_request_token(&$request) { - $this->get_version($request); - - $consumer = $this->get_consumer($request); - - // no token required for the initial token request - $token = NULL; - - $this->check_signature($request, $consumer, $token); - - // Rev A change - $callback = $request->get_parameter('oauth_callback'); - $new_token = $this->data_store->new_request_token($consumer, $callback); - - return $new_token; - } - - /** - * process an access_token request - * returns the access token on success - */ - public function fetch_access_token(&$request) { - $this->get_version($request); - - $consumer = $this->get_consumer($request); - - // requires authorized request token - $token = $this->get_token($request, $consumer, "request"); - - $this->check_signature($request, $consumer, $token); - - // Rev A change - $verifier = $request->get_parameter('oauth_verifier'); - $new_token = $this->data_store->new_access_token($token, $consumer, $verifier); - - return $new_token; - } - - /** - * verify an api call, checks all the parameters - */ - public function verify_request(&$request) { - $this->get_version($request); - $consumer = $this->get_consumer($request); - $token = $this->get_token($request, $consumer, "access"); - $this->check_signature($request, $consumer, $token); - return array($consumer, $token); - } - - // Internals from here - /** - * version 1 - */ - private function get_version(&$request) { - $version = $request->get_parameter("oauth_version"); - if (!$version) { - // Service Providers MUST assume the protocol version to be 1.0 if this parameter is not present. - // Chapter 7.0 ("Accessing Protected Ressources") - $version = '1.0'; - } - if ($version !== $this->version) { - throw new OAuthException("OAuth version '$version' not supported"); - } - return $version; - } - - /** - * figure out the signature with some defaults - */ - private function get_signature_method($request) { - $signature_method = $request instanceof OAuthRequest - ? $request->get_parameter("oauth_signature_method") - : NULL; - - if (!$signature_method) { - // According to chapter 7 ("Accessing Protected Ressources") the signature-method - // parameter is required, and we can't just fallback to PLAINTEXT - throw new OAuthException('No signature method parameter. This parameter is required'); - } - - if (!in_array($signature_method, - array_keys($this->signature_methods))) { - throw new OAuthException( - "Signature method '$signature_method' not supported " . - "try one of the following: " . - implode(", ", array_keys($this->signature_methods)) - ); - } - return $this->signature_methods[$signature_method]; - } - - /** - * try to find the consumer for the provided request's consumer key - */ - private function get_consumer($request) { - $consumer_key = $request instanceof OAuthRequest - ? $request->get_parameter("oauth_consumer_key") - : NULL; - - if (!$consumer_key) { - throw new OAuthException("Invalid consumer key"); - } - - $consumer = $this->data_store->lookup_consumer($consumer_key); - if (!$consumer) { - throw new OAuthException("Invalid consumer"); - } - - return $consumer; - } - - /** - * try to find the token for the provided request's token key - */ - private function get_token($request, $consumer, $token_type="access") { - $token_field = $request instanceof OAuthRequest - ? $request->get_parameter('oauth_token') - : NULL; - - $token = $this->data_store->lookup_token( - $consumer, $token_type, $token_field - ); - if (!$token) { - throw new OAuthException("Invalid $token_type token: $token_field"); - } - return $token; - } - - /** - * all-in-one function to check the signature on a request - * should guess the signature method appropriately - */ - private function check_signature($request, $consumer, $token) { - // this should probably be in a different method - $timestamp = $request instanceof OAuthRequest - ? $request->get_parameter('oauth_timestamp') - : NULL; - $nonce = $request instanceof OAuthRequest - ? $request->get_parameter('oauth_nonce') - : NULL; - - $this->check_timestamp($timestamp); - $this->check_nonce($consumer, $token, $nonce, $timestamp); - - $signature_method = $this->get_signature_method($request); - - $signature = $request->get_parameter('oauth_signature'); - $valid_sig = $signature_method->check_signature( - $request, - $consumer, - $token, - $signature - ); - - if (!$valid_sig) { - throw new OAuthException("Invalid signature"); - } - } - - /** - * check that the timestamp is new enough - */ - private function check_timestamp($timestamp) { - if( ! $timestamp ) - throw new OAuthException( - 'Missing timestamp parameter. The parameter is required' - ); - - // verify that timestamp is recentish - $now = time(); - if (abs($now - $timestamp) > $this->timestamp_threshold) { - throw new OAuthException( - "Expired timestamp, yours $timestamp, ours $now" - ); - } - } - - /** - * check that the nonce is not repeated - */ - private function check_nonce($consumer, $token, $nonce, $timestamp) { - if( ! $nonce ) - throw new OAuthException( - 'Missing nonce parameter. The parameter is required' - ); - - // verify that the nonce is uniqueish - $found = $this->data_store->lookup_nonce( - $consumer, - $token, - $nonce, - $timestamp - ); - if ($found) { - throw new OAuthException("Nonce already used: $nonce"); - } - } - -} - -class OAuthDataStore { - function lookup_consumer($consumer_key) { - // implement me - } - - function lookup_token($consumer, $token_type, $token) { - // implement me - } - - function lookup_nonce($consumer, $token, $nonce, $timestamp) { - // implement me - } - - function new_request_token($consumer, $callback = null) { - // return a new token attached to this consumer - } - - function new_access_token($token, $consumer, $verifier = null) { - // return a new access token attached to this consumer - // for the user associated with this token if the request token - // is authorized - // should also invalidate the request token - } - -} - -class OAuthUtil { - public static function urlencode_rfc3986($input) { - if (is_array($input)) { - return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input); - } else if (is_scalar($input)) { - return str_replace( - '+', - ' ', - str_replace('%7E', '~', rawurlencode($input)) - ); - } else { - return ''; - } -} - - - // This decode function isn't taking into consideration the above - // modifications to the encoding process. However, this method doesn't - // seem to be used anywhere so leaving it as is. - public static function urldecode_rfc3986($string) { - return urldecode($string); - } - - // Utility function for turning the Authorization: header into - // parameters, has to do some unescaping - // Can filter out any non-oauth parameters if needed (default behaviour) - // May 28th, 2010 - method updated to tjerk.meesters for a speed improvement. - // see http://code.google.com/p/oauth/issues/detail?id=163 - public static function split_header($header, $only_allow_oauth_parameters = true) { - $params = array(); - if (preg_match_all('/('.($only_allow_oauth_parameters ? 'oauth_' : '').'[a-z_-]*)=(:?"([^"]*)"|([^,]*))/', $header, $matches)) { - foreach ($matches[1] as $i => $h) { - $params[$h] = OAuthUtil::urldecode_rfc3986(empty($matches[3][$i]) ? $matches[4][$i] : $matches[3][$i]); - } - if (isset($params['realm'])) { - unset($params['realm']); - } - } - return $params; - } - - // helper to try to sort out headers for people who aren't running apache - public static function get_headers() { - if (function_exists('apache_request_headers')) { - // we need this to get the actual Authorization: header - // because apache tends to tell us it doesn't exist - $headers = apache_request_headers(); - - // sanitize the output of apache_request_headers because - // we always want the keys to be Cased-Like-This and arh() - // returns the headers in the same case as they are in the - // request - $out = array(); - foreach ($headers AS $key => $value) { - $key = str_replace( - " ", - "-", - ucwords(strtolower(str_replace("-", " ", $key))) - ); - $out[$key] = $value; - } - } else { - // otherwise we don't have apache and are just going to have to hope - // that $_SERVER actually contains what we need - $out = array(); - if( isset($_SERVER['CONTENT_TYPE']) ) - $out['Content-Type'] = $_SERVER['CONTENT_TYPE']; - if( isset($_ENV['CONTENT_TYPE']) ) - $out['Content-Type'] = $_ENV['CONTENT_TYPE']; - - foreach ($_SERVER as $key => $value) { - if (substr($key, 0, 5) == "HTTP_") { - // this is chaos, basically it is just there to capitalize the first - // letter of every word that is not an initial HTTP and strip HTTP - // code from przemek - $key = str_replace( - " ", - "-", - ucwords(strtolower(str_replace("_", " ", substr($key, 5)))) - ); - $out[$key] = $value; - } - } - } - return $out; - } - - // This function takes a input like a=b&a=c&d=e and returns the parsed - // parameters like this - // array('a' => array('b','c'), 'd' => 'e') - public static function parse_parameters( $input ) { - if (!isset($input) || !$input) return array(); - - $pairs = explode('&', $input); - - $parsed_parameters = array(); - foreach ($pairs as $pair) { - $split = explode('=', $pair, 2); - $parameter = OAuthUtil::urldecode_rfc3986($split[0]); - $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : ''; - - if (isset($parsed_parameters[$parameter])) { - // We have already received parameter(s) with this name, so add to the list - // of parameters with this name - - if (is_scalar($parsed_parameters[$parameter])) { - // This is the first duplicate, so transform scalar (string) into an array - // so we can add the duplicates - $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]); - } - - $parsed_parameters[$parameter][] = $value; - } else { - $parsed_parameters[$parameter] = $value; - } - } - return $parsed_parameters; - } - - public static function build_http_query($params) { - if (!$params) return ''; - - // Urlencode both keys and values - $keys = OAuthUtil::urlencode_rfc3986(array_keys($params)); - $values = OAuthUtil::urlencode_rfc3986(array_values($params)); - $params = array_combine($keys, $values); - - // Parameters are sorted by name, using lexicographical byte value ordering. - // Ref: Spec: 9.1.1 (1) - uksort($params, 'strcmp'); - - $pairs = array(); - foreach ($params as $parameter => $value) { - if (is_array($value)) { - // If two or more parameters share the same name, they are sorted by their value - // Ref: Spec: 9.1.1 (1) - // June 12th, 2010 - changed to sort because of issue 164 by hidetaka - sort($value, SORT_STRING); - foreach ($value as $duplicate_value) { - $pairs[] = $parameter . '=' . $duplicate_value; - } - } else { - $pairs[] = $parameter . '=' . $value; - } - } - // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) - // Each name-value pair is separated by an '&' character (ASCII code 38) - return implode('&', $pairs); - } -} - -?>
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/main.css b/chrome/common/extensions/docs/examples/apps/hello-php/main.css deleted file mode 100644 index 109547df..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/main.css +++ /dev/null
@@ -1,89 +0,0 @@ -body { - font-family: Arial, Verdana, san-serif; - font-size: 11pt; - color: #666; - margin: 0; -} - -nav { - display: block; /* for older browsers */ - text-align: right; - margin-bottom: 10px; - padding: 10px; - border-bottom: 1px solid #C6D2EB; - background: -moz-linear-gradient(#fff, #EEF1F9 60%, #EEF1F9); - background: -webkit-linear-gradient(#fff, #EEF1F9 60%, #EEF1F9); - text-shadow: 1px 1px 1px #fff; -} - -nav span { - float: left; - font-weight: bold; -} - -a { - color: #2F58A4; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -form { - margin: 0; -} - -input[type='text'] { - padding: 3px; -} - -li { - list-style: none; -} - -.error { - margin: 10px 0 10px; - padding: 10px; - text-align: center; - border: 1px solid red; - color: red; - font-weight: bold; - background-color: #ffffcc; - -moz-border-radius: 5px; - border-radius: 5px; - text-shadow: 2px 2px 2px #ccc; -} - -#container { - margin-top: 10px; - padding: 10px; -} - -#access-level { - text-align: center; - padding: 15px; - border: 1px dotted #C6D2EB; - font-size: 12pt; - -moz-border-radius: 15px; - border-radius: 15px; - width: 550px; - margin-left: auto; - margin-right: auto; -} - -#license-server-response span { - font-weight: bold; -} - -#license-server-response span.full { - color: green; -} - -#license-server-response span.free_trial { - color: orange; -} - -#license-server-response span.no { - color: red; -}
diff --git a/chrome/common/extensions/docs/examples/apps/hello-php/popuplib.js b/chrome/common/extensions/docs/examples/apps/hello-php/popuplib.js deleted file mode 100644 index 4b0fd408..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-php/popuplib.js +++ /dev/null
@@ -1,279 +0,0 @@ -// Copyright 2009 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - - -// PopupManager is a library to facilitate integration with OpenID -// identity providers (OP)s that support a pop-up authentication interface. -// To create a popup window, you first construct a popupOpener customized -// for your site and a particular identity provider, E.g.: -// -// var googleOpener = popupManager.createOpener(openidParams); -// -// where 'openidParams' are customized for Google in this instance. -// (typically you just change the openidpoint, the version number -// (the openid.ns parameter) and the extensions based on what -// the OP supports. -// OpenID libraries can often discover these properties -// automatically from the location of an XRD document. -// -// Then, you can either directly call -// googleOpener.popup(width, height), where 'width' and 'height' are your choices -// for popup size, or you can display a button 'Sign in with Google' and set the -//..'onclick' handler of the button to googleOpener.popup() - -var popupManager = {}; - -// Library constants - -popupManager.constants = { - 'darkCover' : 'popupManager_darkCover_div', - 'darkCoverStyle' : ['position:absolute;', - 'top:0px;', - 'left:0px;', - 'padding-right:0px;', - 'padding-bottom:0px;', - 'background-color:#000000;', - 'opacity:0.5;', //standard-compliant browsers - '-moz-opacity:0.5;', // old Mozilla - 'filter:alpha(opacity=0.5);', // IE - 'z-index:10000;', - 'width:100%;', - 'height:100%;' - ].join(''), - 'openidSpec' : { - 'identifier_select' : 'http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select', - 'namespace2' : 'http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0' - } }; - -// Computes the size of the window contents. Returns a pair of -// coordinates [width, height] which can be [0, 0] if it was not possible -// to compute the values. -popupManager.getWindowInnerSize = function() { - var width = 0; - var height = 0; - var elem = null; - if ('innerWidth' in window) { - // For non-IE - width = window.innerWidth; - height = window.innerHeight; - } else { - // For IE, - if (('BackCompat' === window.document.compatMode) - && ('body' in window.document)) { - elem = window.document.body; - } else if ('documentElement' in window.document) { - elem = window.document.documentElement; - } - if (elem !== null) { - width = elem.offsetWidth; - height = elem.offsetHeight; - } - } - return [width, height]; -}; - -// Computes the coordinates of the parent window. -// Gets the coordinates of the parent frame -popupManager.getParentCoords = function() { - var width = 0; - var height = 0; - if ('screenLeft' in window) { - // IE-compatible variants - width = window.screenLeft; - height = window.screenTop; - } else if ('screenX' in window) { - // Firefox-compatible - width = window.screenX; - height = window.screenY; - } - return [width, height]; -}; - -// Computes the coordinates of the new window, so as to center it -// over the parent frame -popupManager.getCenteredCoords = function(width, height) { - var parentSize = this.getWindowInnerSize(); - var parentPos = this.getParentCoords(); - var xPos = parentPos[0] + - Math.max(0, Math.floor((parentSize[0] - width) / 2)); - var yPos = parentPos[1] + - Math.max(0, Math.floor((parentSize[1] - height) / 2)); - return [xPos, yPos]; -}; - -// A utility class, implements an onOpenHandler that darkens the screen -// by overlaying it with a semi-transparent black layer. To use, ensure that -// no screen element has a z-index at or above 10000. -// This layer will be suppressed automatically after the screen closes. -// -// Note: If you want to perform other operations before opening the popup, but -// also would like the screen to darken, you can define a custom handler -// as such: -// var myOnOpenHandler = function(inputs) { -// .. do something -// popupManager.darkenScreen(); -// .. something else -// }; -// Then you pass myOnOpenHandler as input to the opener, as in: -// var openidParams = {}; -// openidParams.onOpenHandler = myOnOpenHandler; -// ... other customizations -// var myOpener = popupManager.createOpener(openidParams); -popupManager.darkenScreen = function() { - var darkCover = window.document.getElementById(window.popupManager.constants['darkCover']); - if (!darkCover) { - darkCover = window.document.createElement('div'); - darkCover['id'] = window.popupManager.constants['darkCover']; - darkCover.setAttribute('style', window.popupManager.constants['darkCoverStyle']); - window.document.body.appendChild(darkCover); - } - darkCover.style.visibility = 'visible'; -}; - -// Returns a an object that can open a popup window customized for an OP & RP. -// to use you call var opener = popupManager.cretePopupOpener(openidParams); -// and then you can assign the 'onclick' handler of a button to -// opener.popup(width, height), where width and height are the values of the popup size; -// -// To use it, you would typically have code such as: -// var myLoginCheckFunction = ... some AJAXy call or page refresh operation -// that will cause the user to see the logged-in experience in the current page. -// var openidParams = { realm : 'openid.realm', returnToUrl : 'openid.return_to', -// opEndpoint : 'openid.op_endpoint', onCloseHandler : myLoginCheckFunction, -// shouldEncodeUrls : 'true' (default) or 'false', extensions : myOpenIDExtensions }; -// -// Here extensions include any OpenID extensions that you support. For instance, -// if you support Attribute Exchange v.1.0, you can say: -// (Example for attribute exchange request for email and name, -// assuming that shouldEncodeUrls = 'true':) -// var myOpenIDExtensions = { -// 'openid.ax.ns' : 'http://openid.net/srv/ax/1.0', -// 'openid.ax.type.email' : 'http://axschema.org/contact/email', -// 'openid.ax.type.name1' : 'http://axschema.org/namePerson/first', -// 'openid.ax.type.name2' : 'http://axschema.org/namePerson/last', -// 'openid.ax.required' : 'email,name1,name2' }; -// Note that the 'ui' namespace is reserved by this library for the OpenID -// UI extension, and that the mode 'popup' is automatically applied. -// If you wish to make use of the 'language' feature of the OpenID UI extension -// simply add the following entry (example assumes the language requested -// is Swiss French: -// var my OpenIDExtensions = { -// ... // other extension parameters -// 'openid.ui.language' : 'fr_CH', -// ... }; -popupManager.createPopupOpener = (function(openidParams) { - var interval_ = null; - var popupWindow_ = null; - var that = this; - var shouldEscape_ = ('shouldEncodeUrls' in openidParams) ? openidParams.shouldEncodeUrls : true; - var encodeIfRequested_ = function(url) { - return (shouldEscape_ ? encodeURIComponent(url) : url); - }; - var identifier_ = ('identifier' in openidParams) ? encodeIfRequested_(openidParams.identifier) : - this.constants.openidSpec.identifier_select; - var identity_ = ('identity' in openidParams) ? encodeIfRequested_(openidParams.identity) : - this.constants.openidSpec.identifier_select; - var openidNs_ = ('namespace' in openidParams) ? encodeIfRequested_(openidParams.namespace) : - this.constants.openidSpec.namespace2; - var onOpenHandler_ = (('onOpenHandler' in openidParams) && - ('function' === typeof(openidParams.onOpenHandler))) ? - openidParams.onOpenHandler : this.darkenScreen; - var onCloseHandler_ = (('onCloseHandler' in openidParams) && - ('function' === typeof(openidParams.onCloseHandler))) ? - openidParams.onCloseHandler : null; - var returnToUrl_ = ('returnToUrl' in openidParams) ? openidParams.returnToUrl : null; - var realm_ = ('realm' in openidParams) ? openidParams.realm : null; - var endpoint_ = ('opEndpoint' in openidParams) ? openidParams.opEndpoint : null; - var extensions_ = ('extensions' in openidParams) ? openidParams.extensions : null; - - // processes key value pairs, escaping any input; - var keyValueConcat_ = function(keyValuePairs) { - var result = ""; - for (key in keyValuePairs) { - result += ['&', key, '=', encodeIfRequested_(keyValuePairs[key])].join(''); - } - return result; - }; - - //Assembles the OpenID request from customizable parameters - var buildUrlToOpen_ = function() { - var connector = '&'; - var encodedUrl = null; - var urlToOpen = null; - if ((null === endpoint_) || (null === returnToUrl_)) { - return; - } - if (endpoint_.indexOf('?') === -1) { - connector = '?'; - } - encodedUrl = encodeIfRequested_(returnToUrl_); - urlToOpen = [ endpoint_, connector, - 'openid.ns=', openidNs_, - '&openid.mode=checkid_setup', - '&openid.claimed_id=', identifier_, - '&openid.identity=', identity_, - '&openid.return_to=', encodedUrl ].join(''); - if (realm_ !== null) { - urlToOpen += "&openid.realm=" + encodeIfRequested_(realm_); - } - if (extensions_ !== null) { - urlToOpen += keyValueConcat_(extensions_); - } - urlToOpen += '&openid.ns.ui=' + encodeURIComponent( - 'http://specs.openid.net/extensions/ui/1.0'); - urlToOpen += '&openid.ui.mode=popup'; - return urlToOpen; - }; - - // Tests that the popup window has closed - var isPopupClosed_ = function() { - return (!popupWindow_ || popupWindow_.closed); - }; - - // Check to perform at each execution of the timed loop. It also triggers - // the action that follows the closing of the popup - var waitForPopupClose_ = function() { - if (isPopupClosed_()) { - popupWindow_ = null; - var darkCover = window.document.getElementById(window.popupManager.constants['darkCover']); - if (darkCover) { - darkCover.style.visibility = 'hidden'; - } - if (onCloseHandler_ !== null) { - onCloseHandler_(); - } - if ((null !== interval_)) { - window.clearInterval(interval_); - interval_ = null; - } - } - }; - - return { - // Function that opens the window. - popup: function(width, height) { - var urlToOpen = buildUrlToOpen_(); - if (onOpenHandler_ !== null) { - onOpenHandler_(); - } - var coordinates = that.getCenteredCoords(width, height); - popupWindow_ = window.open(urlToOpen, "", - "width=" + width + ",height=" + height + - ",status=1,location=1,resizable=yes" + - ",left=" + coordinates[0] +",top=" + coordinates[1]); - interval_ = window.setInterval(waitForPopupClose_, 80); - return true; - } - }; -});
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/NOTICE b/chrome/common/extensions/docs/examples/apps/hello-python/NOTICE deleted file mode 100644 index 2e0d217..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/NOTICE +++ /dev/null
@@ -1,53 +0,0 @@ -This sample application includes two Python libraries: - - -Name: python-oauth2 -URL: http://github.com/simplegeo/python-oauth2/ -================================================================================ -The MIT License - -Copyright (c) 2007 Leah Culver - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -Name: httplib2 -URL: http://code.google.com/p/httplib2/ -================================================================================ -The MIT License - -Copyright (c) <year> <copyright holders> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/README b/chrome/common/extensions/docs/examples/apps/hello-python/README deleted file mode 100644 index 53ff640..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/README +++ /dev/null
@@ -1,30 +0,0 @@ -Hello License Python -==================== - -Overview --------- -This application implements a sample client for the Chrome Web Store Licensing -API on Google's Python App Engine service. - -For information about this API, please see: -http://code.google.com/chrome/webstore/ - -Usage ------ -First, register an App Engine app at www.appspot.com. Make sure you select -Federated Login as the login provider for the app. - -You'll need to configure this sample before it will be functional. Edit -app.yaml and replace the text INSERT APPLICATION NAME HERE with the application -identifier you registered. - -Second, obtain a token for the Chrome Web Store license server. Check the -license server documentation for instructions on how to do this. Edit main.py -and replace the following three configuration lines with your own information: - - 'oauth_token': 'INSERT OAUTH TOKEN HERE', - 'oauth_token_secret': 'INSERT OAUTH TOKEN SECRET HERE', - 'app_id': 'INSERT APPLICATION ID HERE', - -Then deploy your application to App Engine, and you will be able to log in -with OpenID and check the license status of your account. \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/app.yaml b/chrome/common/extensions/docs/examples/apps/hello-python/app.yaml deleted file mode 100644 index 14eca124..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/app.yaml +++ /dev/null
@@ -1,16 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -application: INSERT APPLICATION NAME HERE -version: 1 -runtime: python -api_version: 1 - -handlers: -- url: /favicon.ico - static_files: favicon.ico - upload: favicon.ico - -- url: .* - script: main.py
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/favicon.ico b/chrome/common/extensions/docs/examples/apps/hello-python/favicon.ico deleted file mode 100644 index 8e5f1b5..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/favicon.ico +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/httplib2/__init__.py b/chrome/common/extensions/docs/examples/apps/hello-python/httplib2/__init__.py deleted file mode 100644 index 3cebcb3..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/httplib2/__init__.py +++ /dev/null
@@ -1,1202 +0,0 @@ -from __future__ import generators -""" -httplib2 - -A caching http interface that supports ETags and gzip -to conserve bandwidth. - -Requires Python 2.3 or later - -Changelog: -2007-08-18, Rick: Modified so it's able to use a socks proxy if needed. - -""" - -__author__ = "Joe Gregorio (joe@bitworking.org)" -__copyright__ = "Copyright 2006, Joe Gregorio" -__contributors__ = ["Thomas Broyer (t.broyer@ltgt.net)", - "James Antill", - "Xavier Verges Farrero", - "Jonathan Feinberg", - "Blair Zajac", - "Sam Ruby", - "Louis Nyffenegger"] -__license__ = "MIT" -__version__ = "$Rev$" - -import re -import sys -import email -import email.Utils -import email.Message -import email.FeedParser -import StringIO -import gzip -import zlib -import httplib -import urlparse -import base64 -import os -import copy -import calendar -import time -import random -# remove depracated warning in python2.6 -try: - from hashlib import sha1 as _sha, md5 as _md5 -except ImportError: - import sha - import md5 - _sha = sha.new - _md5 = md5.new -import hmac -from gettext import gettext as _ -import socket - -try: - import socks -except ImportError: - socks = None - -# Build the appropriate socket wrapper for ssl -try: - import ssl # python 2.6 - _ssl_wrap_socket = ssl.wrap_socket -except ImportError: - def _ssl_wrap_socket(sock, key_file, cert_file): - ssl_sock = socket.ssl(sock, key_file, cert_file) - return httplib.FakeSocket(sock, ssl_sock) - - -if sys.version_info >= (2,3): - from iri2uri import iri2uri -else: - def iri2uri(uri): - return uri - -def has_timeout(timeout): # python 2.6 - if hasattr(socket, '_GLOBAL_DEFAULT_TIMEOUT'): - return (timeout is not None and timeout is not socket._GLOBAL_DEFAULT_TIMEOUT) - return (timeout is not None) - -__all__ = ['Http', 'Response', 'ProxyInfo', 'HttpLib2Error', - 'RedirectMissingLocation', 'RedirectLimit', 'FailedToDecompressContent', - 'UnimplementedDigestAuthOptionError', 'UnimplementedHmacDigestAuthOptionError', - 'debuglevel'] - - -# The httplib debug level, set to a non-zero value to get debug output -debuglevel = 0 - - -# Python 2.3 support -if sys.version_info < (2,4): - def sorted(seq): - seq.sort() - return seq - -# Python 2.3 support -def HTTPResponse__getheaders(self): - """Return list of (header, value) tuples.""" - if self.msg is None: - raise httplib.ResponseNotReady() - return self.msg.items() - -if not hasattr(httplib.HTTPResponse, 'getheaders'): - httplib.HTTPResponse.getheaders = HTTPResponse__getheaders - -# All exceptions raised here derive from HttpLib2Error -class HttpLib2Error(Exception): pass - -# Some exceptions can be caught and optionally -# be turned back into responses. -class HttpLib2ErrorWithResponse(HttpLib2Error): - def __init__(self, desc, response, content): - self.response = response - self.content = content - HttpLib2Error.__init__(self, desc) - -class RedirectMissingLocation(HttpLib2ErrorWithResponse): pass -class RedirectLimit(HttpLib2ErrorWithResponse): pass -class FailedToDecompressContent(HttpLib2ErrorWithResponse): pass -class UnimplementedDigestAuthOptionError(HttpLib2ErrorWithResponse): pass -class UnimplementedHmacDigestAuthOptionError(HttpLib2ErrorWithResponse): pass - -class RelativeURIError(HttpLib2Error): pass -class ServerNotFoundError(HttpLib2Error): pass - -# Open Items: -# ----------- -# Proxy support - -# Are we removing the cached content too soon on PUT (only delete on 200 Maybe?) - -# Pluggable cache storage (supports storing the cache in -# flat files by default. We need a plug-in architecture -# that can support Berkeley DB and Squid) - -# == Known Issues == -# Does not handle a resource that uses conneg and Last-Modified but no ETag as a cache validator. -# Does not handle Cache-Control: max-stale -# Does not use Age: headers when calculating cache freshness. - - -# The number of redirections to follow before giving up. -# Note that only GET redirects are automatically followed. -# Will also honor 301 requests by saving that info and never -# requesting that URI again. -DEFAULT_MAX_REDIRECTS = 5 - -# Which headers are hop-by-hop headers by default -HOP_BY_HOP = ['connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization', 'te', 'trailers', 'transfer-encoding', 'upgrade'] - -def _get_end2end_headers(response): - hopbyhop = list(HOP_BY_HOP) - hopbyhop.extend([x.strip() for x in response.get('connection', '').split(',')]) - return [header for header in response.keys() if header not in hopbyhop] - -URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") - -def parse_uri(uri): - """Parses a URI using the regex given in Appendix B of RFC 3986. - - (scheme, authority, path, query, fragment) = parse_uri(uri) - """ - groups = URI.match(uri).groups() - return (groups[1], groups[3], groups[4], groups[6], groups[8]) - -def urlnorm(uri): - (scheme, authority, path, query, fragment) = parse_uri(uri) - if not scheme or not authority: - raise RelativeURIError("Only absolute URIs are allowed. uri = %s" % uri) - authority = authority.lower() - scheme = scheme.lower() - if not path: - path = "/" - # Could do syntax based normalization of the URI before - # computing the digest. See Section 6.2.2 of Std 66. - request_uri = query and "?".join([path, query]) or path - scheme = scheme.lower() - defrag_uri = scheme + "://" + authority + request_uri - return scheme, authority, request_uri, defrag_uri - - -# Cache filename construction (original borrowed from Venus http://intertwingly.net/code/venus/) -re_url_scheme = re.compile(r'^\w+://') -re_slash = re.compile(r'[?/:|]+') - -def safename(filename): - """Return a filename suitable for the cache. - - Strips dangerous and common characters to create a filename we - can use to store the cache in. - """ - - try: - if re_url_scheme.match(filename): - if isinstance(filename,str): - filename = filename.decode('utf-8') - filename = filename.encode('idna') - else: - filename = filename.encode('idna') - except UnicodeError: - pass - if isinstance(filename,unicode): - filename=filename.encode('utf-8') - filemd5 = _md5(filename).hexdigest() - filename = re_url_scheme.sub("", filename) - filename = re_slash.sub(",", filename) - - # limit length of filename - if len(filename)>200: - filename=filename[:200] - return ",".join((filename, filemd5)) - -NORMALIZE_SPACE = re.compile(r'(?:\r\n)?[ \t]+') -def _normalize_headers(headers): - return dict([ (key.lower(), NORMALIZE_SPACE.sub(value, ' ').strip()) for (key, value) in headers.iteritems()]) - -def _parse_cache_control(headers): - retval = {} - if headers.has_key('cache-control'): - parts = headers['cache-control'].split(',') - parts_with_args = [tuple([x.strip().lower() for x in part.split("=", 1)]) for part in parts if -1 != part.find("=")] - parts_wo_args = [(name.strip().lower(), 1) for name in parts if -1 == name.find("=")] - retval = dict(parts_with_args + parts_wo_args) - return retval - -# Whether to use a strict mode to parse WWW-Authenticate headers -# Might lead to bad results in case of ill-formed header value, -# so disabled by default, falling back to relaxed parsing. -# Set to true to turn on, usefull for testing servers. -USE_WWW_AUTH_STRICT_PARSING = 0 - -# In regex below: -# [^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+ matches a "token" as defined by HTTP -# "(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?" matches a "quoted-string" as defined by HTTP, when LWS have already been replaced by a single space -# Actually, as an auth-param value can be either a token or a quoted-string, they are combined in a single pattern which matches both: -# \"?((?<=\")(?:[^\0-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x08\x0A-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"? -WWW_AUTH_STRICT = re.compile(r"^(?:\s*(?:,\s*)?([^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+)\s*=\s*\"?((?<=\")(?:[^\0-\x08\x0A-\x1f\x7f-\xff\\\"]|\\[\0-\x7f])*?(?=\")|(?<!\")[^\0-\x1f\x7f-\xff()<>@,;:\\\"/[\]?={} \t]+(?!\"))\"?)(.*)$") -WWW_AUTH_RELAXED = re.compile(r"^(?:\s*(?:,\s*)?([^ \t\r\n=]+)\s*=\s*\"?((?<=\")(?:[^\\\"]|\\.)*?(?=\")|(?<!\")[^ \t\r\n,]+(?!\"))\"?)(.*)$") -UNQUOTE_PAIRS = re.compile(r'\\(.)') -def _parse_www_authenticate(headers, headername='www-authenticate'): - """Returns a dictionary of dictionaries, one dict - per auth_scheme.""" - retval = {} - if headers.has_key(headername): - authenticate = headers[headername].strip() - www_auth = USE_WWW_AUTH_STRICT_PARSING and WWW_AUTH_STRICT or WWW_AUTH_RELAXED - while authenticate: - # Break off the scheme at the beginning of the line - if headername == 'authentication-info': - (auth_scheme, the_rest) = ('digest', authenticate) - else: - (auth_scheme, the_rest) = authenticate.split(" ", 1) - # Now loop over all the key value pairs that come after the scheme, - # being careful not to roll into the next scheme - match = www_auth.search(the_rest) - auth_params = {} - while match: - if match and len(match.groups()) == 3: - (key, value, the_rest) = match.groups() - auth_params[key.lower()] = UNQUOTE_PAIRS.sub(r'\1', value) # '\\'.join([x.replace('\\', '') for x in value.split('\\\\')]) - match = www_auth.search(the_rest) - retval[auth_scheme.lower()] = auth_params - authenticate = the_rest.strip() - return retval - - -def _entry_disposition(response_headers, request_headers): - """Determine freshness from the Date, Expires and Cache-Control headers. - - We don't handle the following: - - 1. Cache-Control: max-stale - 2. Age: headers are not used in the calculations. - - Not that this algorithm is simpler than you might think - because we are operating as a private (non-shared) cache. - This lets us ignore 's-maxage'. We can also ignore - 'proxy-invalidate' since we aren't a proxy. - We will never return a stale document as - fresh as a design decision, and thus the non-implementation - of 'max-stale'. This also lets us safely ignore 'must-revalidate' - since we operate as if every server has sent 'must-revalidate'. - Since we are private we get to ignore both 'public' and - 'private' parameters. We also ignore 'no-transform' since - we don't do any transformations. - The 'no-store' parameter is handled at a higher level. - So the only Cache-Control parameters we look at are: - - no-cache - only-if-cached - max-age - min-fresh - """ - - retval = "STALE" - cc = _parse_cache_control(request_headers) - cc_response = _parse_cache_control(response_headers) - - if request_headers.has_key('pragma') and request_headers['pragma'].lower().find('no-cache') != -1: - retval = "TRANSPARENT" - if 'cache-control' not in request_headers: - request_headers['cache-control'] = 'no-cache' - elif cc.has_key('no-cache'): - retval = "TRANSPARENT" - elif cc_response.has_key('no-cache'): - retval = "STALE" - elif cc.has_key('only-if-cached'): - retval = "FRESH" - elif response_headers.has_key('date'): - date = calendar.timegm(email.Utils.parsedate_tz(response_headers['date'])) - now = time.time() - current_age = max(0, now - date) - if cc_response.has_key('max-age'): - try: - freshness_lifetime = int(cc_response['max-age']) - except ValueError: - freshness_lifetime = 0 - elif response_headers.has_key('expires'): - expires = email.Utils.parsedate_tz(response_headers['expires']) - if None == expires: - freshness_lifetime = 0 - else: - freshness_lifetime = max(0, calendar.timegm(expires) - date) - else: - freshness_lifetime = 0 - if cc.has_key('max-age'): - try: - freshness_lifetime = int(cc['max-age']) - except ValueError: - freshness_lifetime = 0 - if cc.has_key('min-fresh'): - try: - min_fresh = int(cc['min-fresh']) - except ValueError: - min_fresh = 0 - current_age += min_fresh - if freshness_lifetime > current_age: - retval = "FRESH" - return retval - -def _decompressContent(response, new_content): - content = new_content - try: - encoding = response.get('content-encoding', None) - if encoding in ['gzip', 'deflate']: - if encoding == 'gzip': - content = gzip.GzipFile(fileobj=StringIO.StringIO(new_content)).read() - if encoding == 'deflate': - content = zlib.decompress(content) - response['content-length'] = str(len(content)) - # Record the historical presence of the encoding in a way the won't interfere. - response['-content-encoding'] = response['content-encoding'] - del response['content-encoding'] - except IOError: - content = "" - raise FailedToDecompressContent(_("Content purported to be compressed with %s but failed to decompress.") % response.get('content-encoding'), response, content) - return content - -def _updateCache(request_headers, response_headers, content, cache, cachekey): - if cachekey: - cc = _parse_cache_control(request_headers) - cc_response = _parse_cache_control(response_headers) - if cc.has_key('no-store') or cc_response.has_key('no-store'): - cache.delete(cachekey) - else: - info = email.Message.Message() - for key, value in response_headers.iteritems(): - if key not in ['status','content-encoding','transfer-encoding']: - info[key] = value - - # Add annotations to the cache to indicate what headers - # are variant for this request. - vary = response_headers.get('vary', None) - if vary: - vary_headers = vary.lower().replace(' ', '').split(',') - for header in vary_headers: - key = '-varied-%s' % header - try: - info[key] = request_headers[header] - except KeyError: - pass - - status = response_headers.status - if status == 304: - status = 200 - - status_header = 'status: %d\r\n' % response_headers.status - - header_str = info.as_string() - - header_str = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", header_str) - text = "".join([status_header, header_str, content]) - - cache.set(cachekey, text) - -def _cnonce(): - dig = _md5("%s:%s" % (time.ctime(), ["0123456789"[random.randrange(0, 9)] for i in range(20)])).hexdigest() - return dig[:16] - -def _wsse_username_token(cnonce, iso_now, password): - return base64.b64encode(_sha("%s%s%s" % (cnonce, iso_now, password)).digest()).strip() - - -# For credentials we need two things, first -# a pool of credential to try (not necesarily tied to BAsic, Digest, etc.) -# Then we also need a list of URIs that have already demanded authentication -# That list is tricky since sub-URIs can take the same auth, or the -# auth scheme may change as you descend the tree. -# So we also need each Auth instance to be able to tell us -# how close to the 'top' it is. - -class Authentication(object): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - self.path = path - self.host = host - self.credentials = credentials - self.http = http - - def depth(self, request_uri): - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - return request_uri[len(self.path):].count("/") - - def inscope(self, host, request_uri): - # XXX Should we normalize the request_uri? - (scheme, authority, path, query, fragment) = parse_uri(request_uri) - return (host == self.host) and path.startswith(self.path) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header. Over-rise this in sub-classes.""" - pass - - def response(self, response, content): - """Gives us a chance to update with new nonces - or such returned from the last authorized response. - Over-rise this in sub-classes if necessary. - - Return TRUE is the request is to be retried, for - example Digest may return stale=true. - """ - return False - - - -class BasicAuthentication(Authentication): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'Basic ' + base64.b64encode("%s:%s" % self.credentials).strip() - - -class DigestAuthentication(Authentication): - """Only do qop='auth' and MD5, since that - is all Apache currently implements""" - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - self.challenge = challenge['digest'] - qop = self.challenge.get('qop', 'auth') - self.challenge['qop'] = ('auth' in [x.strip() for x in qop.split()]) and 'auth' or None - if self.challenge['qop'] is None: - raise UnimplementedDigestAuthOptionError( _("Unsupported value for qop: %s." % qop)) - self.challenge['algorithm'] = self.challenge.get('algorithm', 'MD5').upper() - if self.challenge['algorithm'] != 'MD5': - raise UnimplementedDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm'])) - self.A1 = "".join([self.credentials[0], ":", self.challenge['realm'], ":", self.credentials[1]]) - self.challenge['nc'] = 1 - - def request(self, method, request_uri, headers, content, cnonce = None): - """Modify the request headers""" - H = lambda x: _md5(x).hexdigest() - KD = lambda s, d: H("%s:%s" % (s, d)) - A2 = "".join([method, ":", request_uri]) - self.challenge['cnonce'] = cnonce or _cnonce() - request_digest = '"%s"' % KD(H(self.A1), "%s:%s:%s:%s:%s" % (self.challenge['nonce'], - '%08x' % self.challenge['nc'], - self.challenge['cnonce'], - self.challenge['qop'], H(A2) - )) - headers['Authorization'] = 'Digest username="%s", realm="%s", nonce="%s", uri="%s", algorithm=%s, response=%s, qop=%s, nc=%08x, cnonce="%s"' % ( - self.credentials[0], - self.challenge['realm'], - self.challenge['nonce'], - request_uri, - self.challenge['algorithm'], - request_digest, - self.challenge['qop'], - self.challenge['nc'], - self.challenge['cnonce'], - ) - self.challenge['nc'] += 1 - - def response(self, response, content): - if not response.has_key('authentication-info'): - challenge = _parse_www_authenticate(response, 'www-authenticate').get('digest', {}) - if 'true' == challenge.get('stale'): - self.challenge['nonce'] = challenge['nonce'] - self.challenge['nc'] = 1 - return True - else: - updated_challenge = _parse_www_authenticate(response, 'authentication-info').get('digest', {}) - - if updated_challenge.has_key('nextnonce'): - self.challenge['nonce'] = updated_challenge['nextnonce'] - self.challenge['nc'] = 1 - return False - - -class HmacDigestAuthentication(Authentication): - """Adapted from Robert Sayre's code and DigestAuthentication above.""" - __author__ = "Thomas Broyer (t.broyer@ltgt.net)" - - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - self.challenge = challenge['hmacdigest'] - # TODO: self.challenge['domain'] - self.challenge['reason'] = self.challenge.get('reason', 'unauthorized') - if self.challenge['reason'] not in ['unauthorized', 'integrity']: - self.challenge['reason'] = 'unauthorized' - self.challenge['salt'] = self.challenge.get('salt', '') - if not self.challenge.get('snonce'): - raise UnimplementedHmacDigestAuthOptionError( _("The challenge doesn't contain a server nonce, or this one is empty.")) - self.challenge['algorithm'] = self.challenge.get('algorithm', 'HMAC-SHA-1') - if self.challenge['algorithm'] not in ['HMAC-SHA-1', 'HMAC-MD5']: - raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for algorithm: %s." % self.challenge['algorithm'])) - self.challenge['pw-algorithm'] = self.challenge.get('pw-algorithm', 'SHA-1') - if self.challenge['pw-algorithm'] not in ['SHA-1', 'MD5']: - raise UnimplementedHmacDigestAuthOptionError( _("Unsupported value for pw-algorithm: %s." % self.challenge['pw-algorithm'])) - if self.challenge['algorithm'] == 'HMAC-MD5': - self.hashmod = _md5 - else: - self.hashmod = _sha - if self.challenge['pw-algorithm'] == 'MD5': - self.pwhashmod = _md5 - else: - self.pwhashmod = _sha - self.key = "".join([self.credentials[0], ":", - self.pwhashmod.new("".join([self.credentials[1], self.challenge['salt']])).hexdigest().lower(), - ":", self.challenge['realm'] - ]) - self.key = self.pwhashmod.new(self.key).hexdigest().lower() - - def request(self, method, request_uri, headers, content): - """Modify the request headers""" - keys = _get_end2end_headers(headers) - keylist = "".join(["%s " % k for k in keys]) - headers_val = "".join([headers[k] for k in keys]) - created = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()) - cnonce = _cnonce() - request_digest = "%s:%s:%s:%s:%s" % (method, request_uri, cnonce, self.challenge['snonce'], headers_val) - request_digest = hmac.new(self.key, request_digest, self.hashmod).hexdigest().lower() - headers['Authorization'] = 'HMACDigest username="%s", realm="%s", snonce="%s", cnonce="%s", uri="%s", created="%s", response="%s", headers="%s"' % ( - self.credentials[0], - self.challenge['realm'], - self.challenge['snonce'], - cnonce, - request_uri, - created, - request_digest, - keylist, - ) - - def response(self, response, content): - challenge = _parse_www_authenticate(response, 'www-authenticate').get('hmacdigest', {}) - if challenge.get('reason') in ['integrity', 'stale']: - return True - return False - - -class WsseAuthentication(Authentication): - """This is thinly tested and should not be relied upon. - At this time there isn't any third party server to test against. - Blogger and TypePad implemented this algorithm at one point - but Blogger has since switched to Basic over HTTPS and - TypePad has implemented it wrong, by never issuing a 401 - challenge but instead requiring your client to telepathically know that - their endpoint is expecting WSSE profile="UsernameToken".""" - def __init__(self, credentials, host, request_uri, headers, response, content, http): - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['Authorization'] = 'WSSE profile="UsernameToken"' - iso_now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - cnonce = _cnonce() - password_digest = _wsse_username_token(cnonce, iso_now, self.credentials[1]) - headers['X-WSSE'] = 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"' % ( - self.credentials[0], - password_digest, - cnonce, - iso_now) - -class GoogleLoginAuthentication(Authentication): - def __init__(self, credentials, host, request_uri, headers, response, content, http): - from urllib import urlencode - Authentication.__init__(self, credentials, host, request_uri, headers, response, content, http) - challenge = _parse_www_authenticate(response, 'www-authenticate') - service = challenge['googlelogin'].get('service', 'xapi') - # Bloggger actually returns the service in the challenge - # For the rest we guess based on the URI - if service == 'xapi' and request_uri.find("calendar") > 0: - service = "cl" - # No point in guessing Base or Spreadsheet - #elif request_uri.find("spreadsheets") > 0: - # service = "wise" - - auth = dict(Email=credentials[0], Passwd=credentials[1], service=service, source=headers['user-agent']) - resp, content = self.http.request("https://www.google.com/accounts/ClientLogin", method="POST", body=urlencode(auth), headers={'Content-Type': 'application/x-www-form-urlencoded'}) - lines = content.split('\n') - d = dict([tuple(line.split("=", 1)) for line in lines if line]) - if resp.status == 403: - self.Auth = "" - else: - self.Auth = d['Auth'] - - def request(self, method, request_uri, headers, content): - """Modify the request headers to add the appropriate - Authorization header.""" - headers['authorization'] = 'GoogleLogin Auth=' + self.Auth - - -AUTH_SCHEME_CLASSES = { - "basic": BasicAuthentication, - "wsse": WsseAuthentication, - "digest": DigestAuthentication, - "hmacdigest": HmacDigestAuthentication, - "googlelogin": GoogleLoginAuthentication -} - -AUTH_SCHEME_ORDER = ["hmacdigest", "googlelogin", "digest", "wsse", "basic"] - -class FileCache(object): - """Uses a local directory as a store for cached files. - Not really safe to use if multiple threads or processes are going to - be running on the same cache. - """ - def __init__(self, cache, safe=safename): # use safe=lambda x: md5.new(x).hexdigest() for the old behavior - self.cache = cache - self.safe = safe - if not os.path.exists(cache): - os.makedirs(self.cache) - - def get(self, key): - retval = None - cacheFullPath = os.path.join(self.cache, self.safe(key)) - try: - f = file(cacheFullPath, "rb") - retval = f.read() - f.close() - except IOError: - pass - return retval - - def set(self, key, value): - cacheFullPath = os.path.join(self.cache, self.safe(key)) - f = file(cacheFullPath, "wb") - f.write(value) - f.close() - - def delete(self, key): - cacheFullPath = os.path.join(self.cache, self.safe(key)) - if os.path.exists(cacheFullPath): - os.remove(cacheFullPath) - -class Credentials(object): - def __init__(self): - self.credentials = [] - - def add(self, name, password, domain=""): - self.credentials.append((domain.lower(), name, password)) - - def clear(self): - self.credentials = [] - - def iter(self, domain): - for (cdomain, name, password) in self.credentials: - if cdomain == "" or domain == cdomain: - yield (name, password) - -class KeyCerts(Credentials): - """Identical to Credentials except that - name/password are mapped to key/cert.""" - pass - - -class ProxyInfo(object): - """Collect information required to use a proxy.""" - def __init__(self, proxy_type, proxy_host, proxy_port, proxy_rdns=None, proxy_user=None, proxy_pass=None): - """The parameter proxy_type must be set to one of socks.PROXY_TYPE_XXX - constants. For example: - -p = ProxyInfo(proxy_type=socks.PROXY_TYPE_HTTP, proxy_host='localhost', proxy_port=8000) - """ - self.proxy_type, self.proxy_host, self.proxy_port, self.proxy_rdns, self.proxy_user, self.proxy_pass = proxy_type, proxy_host, proxy_port, proxy_rdns, proxy_user, proxy_pass - - def astuple(self): - return (self.proxy_type, self.proxy_host, self.proxy_port, self.proxy_rdns, - self.proxy_user, self.proxy_pass) - - def isgood(self): - return socks and (self.proxy_host != None) and (self.proxy_port != None) - - -class HTTPConnectionWithTimeout(httplib.HTTPConnection): - """HTTPConnection subclass that supports timeouts""" - - def __init__(self, host, port=None, strict=None, timeout=None, proxy_info=None): - httplib.HTTPConnection.__init__(self, host, port, strict) - self.timeout = timeout - self.proxy_info = proxy_info - - def connect(self): - """Connect to the host and port specified in __init__.""" - # Mostly verbatim from httplib.py. - msg = "getaddrinfo returns an empty list" - for res in socket.getaddrinfo(self.host, self.port, 0, - socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - if self.proxy_info and self.proxy_info.isgood(): - self.sock = socks.socksocket(af, socktype, proto) - self.sock.setproxy(*self.proxy_info.astuple()) - else: - self.sock = socket.socket(af, socktype, proto) - # Different from httplib: support timeouts. - if has_timeout(self.timeout): - self.sock.settimeout(self.timeout) - # End of difference from httplib. - if self.debuglevel > 0: - print "connect: (%s, %s)" % (self.host, self.port) - - self.sock.connect(sa) - except socket.error, msg: - if self.debuglevel > 0: - print 'connect fail:', (self.host, self.port) - if self.sock: - self.sock.close() - self.sock = None - continue - break - if not self.sock: - raise socket.error, msg - -class HTTPSConnectionWithTimeout(httplib.HTTPSConnection): - "This class allows communication via SSL." - - def __init__(self, host, port=None, key_file=None, cert_file=None, - strict=None, timeout=None, proxy_info=None): - httplib.HTTPSConnection.__init__(self, host, port=port, key_file=key_file, - cert_file=cert_file, strict=strict) - self.timeout = timeout - self.proxy_info = proxy_info - - def connect(self): - "Connect to a host on a given (SSL) port." - - if self.proxy_info and self.proxy_info.isgood(): - sock = socks.socksocket(socket.AF_INET, socket.SOCK_STREAM) - sock.setproxy(*self.proxy_info.astuple()) - else: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - if has_timeout(self.timeout): - sock.settimeout(self.timeout) - sock.connect((self.host, self.port)) - self.sock =_ssl_wrap_socket(sock, self.key_file, self.cert_file) - - - -class Http(object): - """An HTTP client that handles: -- all methods -- caching -- ETags -- compression, -- HTTPS -- Basic -- Digest -- WSSE - -and more. - """ - def __init__(self, cache=None, timeout=None, proxy_info=None): - """The value of proxy_info is a ProxyInfo instance. - -If 'cache' is a string then it is used as a directory name -for a disk cache. Otherwise it must be an object that supports -the same interface as FileCache.""" - self.proxy_info = proxy_info - # Map domain name to an httplib connection - self.connections = {} - # The location of the cache, for now a directory - # where cached responses are held. - if cache and isinstance(cache, str): - self.cache = FileCache(cache) - else: - self.cache = cache - - # Name/password - self.credentials = Credentials() - - # Key/cert - self.certificates = KeyCerts() - - # authorization objects - self.authorizations = [] - - # If set to False then no redirects are followed, even safe ones. - self.follow_redirects = True - - # Which HTTP methods do we apply optimistic concurrency to, i.e. - # which methods get an "if-match:" etag header added to them. - self.optimistic_concurrency_methods = ["PUT"] - - # If 'follow_redirects' is True, and this is set to True then - # all redirecs are followed, including unsafe ones. - self.follow_all_redirects = False - - self.ignore_etag = False - - self.force_exception_to_status_code = False - - self.timeout = timeout - - def _auth_from_challenge(self, host, request_uri, headers, response, content): - """A generator that creates Authorization objects - that can be applied to requests. - """ - challenges = _parse_www_authenticate(response, 'www-authenticate') - for cred in self.credentials.iter(host): - for scheme in AUTH_SCHEME_ORDER: - if challenges.has_key(scheme): - yield AUTH_SCHEME_CLASSES[scheme](cred, host, request_uri, headers, response, content, self) - - def add_credentials(self, name, password, domain=""): - """Add a name and password that will be used - any time a request requires authentication.""" - self.credentials.add(name, password, domain) - - def add_certificate(self, key, cert, domain): - """Add a key and cert that will be used - any time a request requires authentication.""" - self.certificates.add(key, cert, domain) - - def clear_credentials(self): - """Remove all the names and passwords - that are used for authentication""" - self.credentials.clear() - self.authorizations = [] - - def _conn_request(self, conn, request_uri, method, body, headers): - for i in range(2): - try: - conn.request(method, request_uri, body, headers) - except socket.gaierror: - conn.close() - raise ServerNotFoundError("Unable to find the server at %s" % conn.host) - except (socket.error, httplib.HTTPException): - # Just because the server closed the connection doesn't apparently mean - # that the server didn't send a response. - pass - try: - response = conn.getresponse() - except (socket.error, httplib.HTTPException): - if i == 0: - conn.close() - conn.connect() - continue - else: - raise - else: - content = "" - if method == "HEAD": - response.close() - else: - content = response.read() - response = Response(response) - if method != "HEAD": - content = _decompressContent(response, content) - break - return (response, content) - - - def _request(self, conn, host, absolute_uri, request_uri, method, body, headers, redirections, cachekey): - """Do the actual request using the connection object - and also follow one level of redirects if necessary""" - - auths = [(auth.depth(request_uri), auth) for auth in self.authorizations if auth.inscope(host, request_uri)] - auth = auths and sorted(auths)[0][1] or None - if auth: - auth.request(method, request_uri, headers, body) - - (response, content) = self._conn_request(conn, request_uri, method, body, headers) - - if auth: - if auth.response(response, body): - auth.request(method, request_uri, headers, body) - (response, content) = self._conn_request(conn, request_uri, method, body, headers ) - response._stale_digest = 1 - - if response.status == 401: - for authorization in self._auth_from_challenge(host, request_uri, headers, response, content): - authorization.request(method, request_uri, headers, body) - (response, content) = self._conn_request(conn, request_uri, method, body, headers, ) - if response.status != 401: - self.authorizations.append(authorization) - authorization.response(response, body) - break - - if (self.follow_all_redirects or (method in ["GET", "HEAD"]) or response.status == 303): - if self.follow_redirects and response.status in [300, 301, 302, 303, 307]: - # Pick out the location header and basically start from the beginning - # remembering first to strip the ETag header and decrement our 'depth' - if redirections: - if not response.has_key('location') and response.status != 300: - raise RedirectMissingLocation( _("Redirected but the response is missing a Location: header."), response, content) - # Fix-up relative redirects (which violate an RFC 2616 MUST) - if response.has_key('location'): - location = response['location'] - (scheme, authority, path, query, fragment) = parse_uri(location) - if authority == None: - response['location'] = urlparse.urljoin(absolute_uri, location) - if response.status == 301 and method in ["GET", "HEAD"]: - response['-x-permanent-redirect-url'] = response['location'] - if not response.has_key('content-location'): - response['content-location'] = absolute_uri - _updateCache(headers, response, content, self.cache, cachekey) - if headers.has_key('if-none-match'): - del headers['if-none-match'] - if headers.has_key('if-modified-since'): - del headers['if-modified-since'] - if response.has_key('location'): - location = response['location'] - old_response = copy.deepcopy(response) - if not old_response.has_key('content-location'): - old_response['content-location'] = absolute_uri - redirect_method = ((response.status == 303) and (method not in ["GET", "HEAD"])) and "GET" or method - (response, content) = self.request(location, redirect_method, body=body, headers = headers, redirections = redirections - 1) - response.previous = old_response - else: - raise RedirectLimit( _("Redirected more times than rediection_limit allows."), response, content) - elif response.status in [200, 203] and method == "GET": - # Don't cache 206's since we aren't going to handle byte range requests - if not response.has_key('content-location'): - response['content-location'] = absolute_uri - _updateCache(headers, response, content, self.cache, cachekey) - - return (response, content) - - def _normalize_headers(self, headers): - return _normalize_headers(headers) - -# Need to catch and rebrand some exceptions -# Then need to optionally turn all exceptions into status codes -# including all socket.* and httplib.* exceptions. - - - def request(self, uri, method="GET", body=None, headers=None, redirections=DEFAULT_MAX_REDIRECTS, connection_type=None): - """ Performs a single HTTP request. -The 'uri' is the URI of the HTTP resource and can begin -with either 'http' or 'https'. The value of 'uri' must be an absolute URI. - -The 'method' is the HTTP method to perform, such as GET, POST, DELETE, etc. -There is no restriction on the methods allowed. - -The 'body' is the entity body to be sent with the request. It is a string -object. - -Any extra headers that are to be sent with the request should be provided in the -'headers' dictionary. - -The maximum number of redirect to follow before raising an -exception is 'redirections. The default is 5. - -The return value is a tuple of (response, content), the first -being and instance of the 'Response' class, the second being -a string that contains the response entity body. - """ - try: - if headers is None: - headers = {} - else: - headers = self._normalize_headers(headers) - - if not headers.has_key('user-agent'): - headers['user-agent'] = "Python-httplib2/%s" % __version__ - - uri = iri2uri(uri) - - (scheme, authority, request_uri, defrag_uri) = urlnorm(uri) - domain_port = authority.split(":")[0:2] - if len(domain_port) == 2 and domain_port[1] == '443' and scheme == 'http': - scheme = 'https' - authority = domain_port[0] - - conn_key = scheme+":"+authority - if conn_key in self.connections: - conn = self.connections[conn_key] - else: - if not connection_type: - connection_type = (scheme == 'https') and HTTPSConnectionWithTimeout or HTTPConnectionWithTimeout - certs = list(self.certificates.iter(authority)) - if scheme == 'https' and certs: - conn = self.connections[conn_key] = connection_type(authority, key_file=certs[0][0], - cert_file=certs[0][1], timeout=self.timeout, proxy_info=self.proxy_info) - else: - conn = self.connections[conn_key] = connection_type(authority, timeout=self.timeout, proxy_info=self.proxy_info) - conn.set_debuglevel(debuglevel) - - if method in ["GET", "HEAD"] and 'range' not in headers and 'accept-encoding' not in headers: - headers['accept-encoding'] = 'gzip, deflate' - - info = email.Message.Message() - cached_value = None - if self.cache: - cachekey = defrag_uri - cached_value = self.cache.get(cachekey) - if cached_value: - # info = email.message_from_string(cached_value) - # - # Need to replace the line above with the kludge below - # to fix the non-existent bug not fixed in this - # bug report: http://mail.python.org/pipermail/python-bugs-list/2005-September/030289.html - try: - info, content = cached_value.split('\r\n\r\n', 1) - feedparser = email.FeedParser.FeedParser() - feedparser.feed(info) - info = feedparser.close() - feedparser._parse = None - except IndexError: - self.cache.delete(cachekey) - cachekey = None - cached_value = None - else: - cachekey = None - - if method in self.optimistic_concurrency_methods and self.cache and info.has_key('etag') and not self.ignore_etag and 'if-match' not in headers: - # http://www.w3.org/1999/04/Editing/ - headers['if-match'] = info['etag'] - - if method not in ["GET", "HEAD"] and self.cache and cachekey: - # RFC 2616 Section 13.10 - self.cache.delete(cachekey) - - # Check the vary header in the cache to see if this request - # matches what varies in the cache. - if method in ['GET', 'HEAD'] and 'vary' in info: - vary = info['vary'] - vary_headers = vary.lower().replace(' ', '').split(',') - for header in vary_headers: - key = '-varied-%s' % header - value = info[key] - if headers.get(header, '') != value: - cached_value = None - break - - if cached_value and method in ["GET", "HEAD"] and self.cache and 'range' not in headers: - if info.has_key('-x-permanent-redirect-url'): - # Should cached permanent redirects be counted in our redirection count? For now, yes. - (response, new_content) = self.request(info['-x-permanent-redirect-url'], "GET", headers = headers, redirections = redirections - 1) - response.previous = Response(info) - response.previous.fromcache = True - else: - # Determine our course of action: - # Is the cached entry fresh or stale? - # Has the client requested a non-cached response? - # - # There seems to be three possible answers: - # 1. [FRESH] Return the cache entry w/o doing a GET - # 2. [STALE] Do the GET (but add in cache validators if available) - # 3. [TRANSPARENT] Do a GET w/o any cache validators (Cache-Control: no-cache) on the request - entry_disposition = _entry_disposition(info, headers) - - if entry_disposition == "FRESH": - if not cached_value: - info['status'] = '504' - content = "" - response = Response(info) - if cached_value: - response.fromcache = True - return (response, content) - - if entry_disposition == "STALE": - if info.has_key('etag') and not self.ignore_etag and not 'if-none-match' in headers: - headers['if-none-match'] = info['etag'] - if info.has_key('last-modified') and not 'last-modified' in headers: - headers['if-modified-since'] = info['last-modified'] - elif entry_disposition == "TRANSPARENT": - pass - - (response, new_content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) - - if response.status == 304 and method == "GET": - # Rewrite the cache entry with the new end-to-end headers - # Take all headers that are in response - # and overwrite their values in info. - # unless they are hop-by-hop, or are listed in the connection header. - - for key in _get_end2end_headers(response): - info[key] = response[key] - merged_response = Response(info) - if hasattr(response, "_stale_digest"): - merged_response._stale_digest = response._stale_digest - _updateCache(headers, merged_response, content, self.cache, cachekey) - response = merged_response - response.status = 200 - response.fromcache = True - - elif response.status == 200: - content = new_content - else: - self.cache.delete(cachekey) - content = new_content - else: - cc = _parse_cache_control(headers) - if cc.has_key('only-if-cached'): - info['status'] = '504' - response = Response(info) - content = "" - else: - (response, content) = self._request(conn, authority, uri, request_uri, method, body, headers, redirections, cachekey) - except Exception, e: - if self.force_exception_to_status_code: - if isinstance(e, HttpLib2ErrorWithResponse): - response = e.response - content = e.content - response.status = 500 - response.reason = str(e) - elif isinstance(e, socket.timeout): - content = "Request Timeout" - response = Response( { - "content-type": "text/plain", - "status": "408", - "content-length": len(content) - }) - response.reason = "Request Timeout" - else: - content = str(e) - response = Response( { - "content-type": "text/plain", - "status": "400", - "content-length": len(content) - }) - response.reason = "Bad Request" - else: - raise - - - return (response, content) - - - -class Response(dict): - """An object more like email.Message than httplib.HTTPResponse.""" - - """Is this response from our local cache""" - fromcache = False - - """HTTP protocol version used by server. 10 for HTTP/1.0, 11 for HTTP/1.1. """ - version = 11 - - "Status code returned by server. " - status = 200 - - """Reason phrase returned by server.""" - reason = "Ok" - - previous = None - - def __init__(self, info): - # info is either an email.Message or - # an httplib.HTTPResponse object. - if isinstance(info, httplib.HTTPResponse): - for key, value in info.getheaders(): - self[key.lower()] = value - self.status = info.status - self['status'] = str(self.status) - self.reason = info.reason - self.version = info.version - elif isinstance(info, email.Message.Message): - for key, value in info.items(): - self[key] = value - self.status = int(self['status']) - else: - for key, value in info.iteritems(): - self[key] = value - self.status = int(self.get('status', self.status)) - - - def __getattr__(self, name): - if name == 'dict': - return self - else: - raise AttributeError, name
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/httplib2/iri2uri.py b/chrome/common/extensions/docs/examples/apps/hello-python/httplib2/iri2uri.py deleted file mode 100644 index 70667ed..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/httplib2/iri2uri.py +++ /dev/null
@@ -1,110 +0,0 @@ -""" -iri2uri - -Converts an IRI to a URI. - -""" -__author__ = "Joe Gregorio (joe@bitworking.org)" -__copyright__ = "Copyright 2006, Joe Gregorio" -__contributors__ = [] -__version__ = "1.0.0" -__license__ = "MIT" -__history__ = """ -""" - -import urlparse - - -# Convert an IRI to a URI following the rules in RFC 3987 -# -# The characters we need to enocde and escape are defined in the spec: -# -# iprivate = %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD -# ucschar = %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF -# / %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD -# / %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD -# / %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD -# / %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD -# / %xD0000-DFFFD / %xE1000-EFFFD - -escape_range = [ - (0xA0, 0xD7FF ), - (0xE000, 0xF8FF ), - (0xF900, 0xFDCF ), - (0xFDF0, 0xFFEF), - (0x10000, 0x1FFFD ), - (0x20000, 0x2FFFD ), - (0x30000, 0x3FFFD), - (0x40000, 0x4FFFD ), - (0x50000, 0x5FFFD ), - (0x60000, 0x6FFFD), - (0x70000, 0x7FFFD ), - (0x80000, 0x8FFFD ), - (0x90000, 0x9FFFD), - (0xA0000, 0xAFFFD ), - (0xB0000, 0xBFFFD ), - (0xC0000, 0xCFFFD), - (0xD0000, 0xDFFFD ), - (0xE1000, 0xEFFFD), - (0xF0000, 0xFFFFD ), - (0x100000, 0x10FFFD) -] - -def encode(c): - retval = c - i = ord(c) - for low, high in escape_range: - if i < low: - break - if i >= low and i <= high: - retval = "".join(["%%%2X" % ord(o) for o in c.encode('utf-8')]) - break - return retval - - -def iri2uri(uri): - """Convert an IRI to a URI. Note that IRIs must be - passed in a unicode strings. That is, do not utf-8 encode - the IRI before passing it into the function.""" - if isinstance(uri ,unicode): - (scheme, authority, path, query, fragment) = urlparse.urlsplit(uri) - authority = authority.encode('idna') - # For each character in 'ucschar' or 'iprivate' - # 1. encode as utf-8 - # 2. then %-encode each octet of that utf-8 - uri = urlparse.urlunsplit((scheme, authority, path, query, fragment)) - uri = "".join([encode(c) for c in uri]) - return uri - -if __name__ == "__main__": - import unittest - - class Test(unittest.TestCase): - - def test_uris(self): - """Test that URIs are invariant under the transformation.""" - invariant = [ - u"ftp://ftp.is.co.za/rfc/rfc1808.txt", - u"http://www.ietf.org/rfc/rfc2396.txt", - u"ldap://[2001:db8::7]/c=GB?objectClass?one", - u"mailto:John.Doe@example.com", - u"news:comp.infosystems.www.servers.unix", - u"tel:+1-816-555-1212", - u"telnet://192.0.2.16:80/", - u"urn:oasis:names:specification:docbook:dtd:xml:4.1.2" ] - for uri in invariant: - self.assertEqual(uri, iri2uri(uri)) - - def test_iri(self): - """ Test that the right type of escaping is done for each part of the URI.""" - self.assertEqual("http://xn--o3h.com/%E2%98%84", iri2uri(u"http://\N{COMET}.com/\N{COMET}")) - self.assertEqual("http://bitworking.org/?fred=%E2%98%84", iri2uri(u"http://bitworking.org/?fred=\N{COMET}")) - self.assertEqual("http://bitworking.org/#%E2%98%84", iri2uri(u"http://bitworking.org/#\N{COMET}")) - self.assertEqual("#%E2%98%84", iri2uri(u"#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}")) - self.assertEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}"))) - self.assertNotEqual("/fred?bar=%E2%98%9A#%E2%98%84", iri2uri(u"/fred?bar=\N{BLACK LEFT POINTING INDEX}#\N{COMET}".encode('utf-8'))) - - unittest.main() - -
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/index.yaml b/chrome/common/extensions/docs/examples/apps/hello-python/index.yaml deleted file mode 100644 index da8f7f3..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/index.yaml +++ /dev/null
@@ -1,15 +0,0 @@ -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -indexes: - -# AUTOGENERATED - -# This index.yaml is automatically updated whenever the dev_appserver -# detects that a new type of query is run. If you want to manage the -# index.yaml file manually, remove the above marker line (the line -# saying "# AUTOGENERATED"). If you want to manage some indexes -# manually, move them above the marker line. The index.yaml file is -# automatically uploaded to the admin console when you next deploy -# your application using appcfg.py.
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/main.py b/chrome/common/extensions/docs/examples/apps/hello-python/main.py deleted file mode 100755 index 48a8d90..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/main.py +++ /dev/null
@@ -1,154 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -from google.appengine.ext import webapp -from google.appengine.ext.webapp import util -from google.appengine.api import users -from google.appengine.api import urlfetch -from google.appengine.ext.webapp import template -from google.appengine.api.urlfetch import DownloadError -import oauth2 -import urllib -import logging -import os -import time -import json - -# Configuration - -CONFIG = { - 'oauth_consumer_key': 'anonymous', - 'oauth_consumer_secret': 'anonymous', - 'license_server': 'https://www.googleapis.com', - 'license_path': '%(server)s/chromewebstore/v1/licenses/%(appid)s/%(userid)s', - 'oauth_token': 'INSERT OAUTH TOKEN HERE', - 'oauth_token_secret': 'INSERT OAUTH TOKEN SECRET HERE', - 'app_id': 'INSERT APPLICATION ID HERE', -} - -# Check to see if the server has been deployed. In the dev server, this -# env variable will start with 'Development', in production, it will start with -# 'Google App Engine' -IS_PRODUCTION = os.environ['SERVER_SOFTWARE'].startswith('Google App Engine') - -# Valid access levels that may be returned by the license server. -VALID_ACCESS_LEVELS = ['FREE_TRIAL', 'FULL'] - - -def fetch_license_data(userid): - """Fetches the license for a given user by making an OAuth signed request - to the license server. - - Args: - userid OpenID of the user you are checking access for. - - Returns: - The server's response as text. - """ - url = CONFIG['license_path'] % { - 'server': CONFIG['license_server'], - 'appid': CONFIG['app_id'], - 'userid': urllib.quote_plus(userid), - } - - oauth_token = oauth2.Token(**{ - 'key': CONFIG['oauth_token'], - 'secret': CONFIG['oauth_token_secret'] - }) - - oauth_consumer = oauth2.Consumer(**{ - 'key': CONFIG['oauth_consumer_key'], - 'secret': CONFIG['oauth_consumer_secret'] - }) - - logging.debug('Requesting %s' % url) - client = oauth2.Client(oauth_consumer, oauth_token) - resp, content = client.request(url, 'GET') - logging.debug('Got response code %s, content %s' % (resp, content)) - return content - - -def parse_license_data(userid): - """Returns the license for a given user as a structured object. - - Args: - userid: The OpenID of the user to check. - - Returns: - An object with the following parameters: - error: True if something went wrong, False otherwise. - message: A descriptive message if error is True. - access: One of 'NO', 'FREE_TRIAL', or 'FULL' depending on the access. - """ - license = {'error': False, 'message': '', 'access': 'NO'} - try: - response_text = fetch_license_data(userid) - try: - logging.debug('Attempting to JSON parse: %s' % response_text) - response = json.loads(response_text) - logging.debug('Got license server response: %s' % response) - except ValueError: - logging.exception('Could not parse response as JSON: %s' % response_text) - license['error'] = True - license['message'] = 'Could not parse the license server response' - except DownloadError: - logging.exception('Could not fetch license data') - license['error'] = True - license['message'] = 'Could not fetch license data' - - if 'error' in response: - license['error'] = True - license['message'] = response['error']['message'] - elif (response['result'] == 'YES' - and response['accessLevel'] in VALID_ACCESS_LEVELS): - license['access'] = response['accessLevel'] - - return license - - -class MainHandler(webapp.RequestHandler): - """Request handler class.""" - def get(self): - """Handler for GET requests.""" - user = users.get_current_user() - if user: - if IS_PRODUCTION: - # We should use federated_identity in production, since the license - # server requires an OpenID - userid = user.federated_identity() - else: - # On the dev server, we won't have access to federated_identity, so - # just use a default OpenID which will never return YES. - # If you want to test different response values on the development - # server, just change this default value (e.g. append '-yes' or - # '-trial'). - userid = ('https://www.google.com/accounts/o8/id?' - 'id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') - license_data = parse_license_data(userid) - template_data = { - 'license': license_data, - 'user_name': user.nickname(), - 'user_id': userid, - 'user_logout': users.create_logout_url(self.request.uri), - } - else: - # Force the OpenID login endpoint to be for Google accounts only, since - # the license server doesn't support any other type of OpenID provider. - login_url = users.create_login_url(dest_url='/', - federated_identity='google.com/accounts/o8/id') - template_data = { - 'user_login': login_url, - } - - # Render a simple template - path = os.path.join(os.path.dirname(__file__), 'templates', 'index.html') - self.response.out.write(template.render(path, template_data)) - - -if __name__ == '__main__': - application = webapp.WSGIApplication([ - ('/', MainHandler), - ], debug=False) - util.run_wsgi_app(application)
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/__init__.py b/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/__init__.py deleted file mode 100644 index 65c3f07..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/__init__.py +++ /dev/null
@@ -1,758 +0,0 @@ -""" -The MIT License - -Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import urllib -import time -import random -import urlparse -import hmac -import binascii -import httplib2 - -try: - from urlparse import parse_qs, parse_qsl -except ImportError: - from cgi import parse_qs, parse_qsl - - -VERSION = '1.0' # Hi Blaine! -HTTP_METHOD = 'GET' -SIGNATURE_METHOD = 'PLAINTEXT' - - -class Error(RuntimeError): - """Generic exception class.""" - - def __init__(self, message='OAuth error occurred.'): - self._message = message - - @property - def message(self): - """A hack to get around the deprecation errors in 2.6.""" - return self._message - - def __str__(self): - return self._message - - -class MissingSignature(Error): - pass - - -def build_authenticate_header(realm=''): - """Optional WWW-Authenticate header (401 error)""" - return {'WWW-Authenticate': 'OAuth realm="%s"' % realm} - - -def build_xoauth_string(url, consumer, token=None): - """Build an XOAUTH string for use in SMTP/IMPA authentication.""" - request = Request.from_consumer_and_token(consumer, token, - "GET", url) - - signing_method = SignatureMethod_HMAC_SHA1() - request.sign_request(signing_method, consumer, token) - - params = [] - for k, v in sorted(request.iteritems()): - if v is not None: - params.append('%s="%s"' % (k, escape(v))) - - return "%s %s %s" % ("GET", url, ','.join(params)) - - -def escape(s): - """Escape a URL including any /.""" - return urllib.quote(s, safe='~') - - -def generate_timestamp(): - """Get seconds since epoch (UTC).""" - return int(time.time()) - - -def generate_nonce(length=8): - """Generate pseudorandom number.""" - return ''.join([str(random.randint(0, 9)) for i in range(length)]) - - -def generate_verifier(length=8): - """Generate pseudorandom number.""" - return ''.join([str(random.randint(0, 9)) for i in range(length)]) - - -class Consumer(object): - """A consumer of OAuth-protected services. - - The OAuth consumer is a "third-party" service that wants to access - protected resources from an OAuth service provider on behalf of an end - user. It's kind of the OAuth client. - - Usually a consumer must be registered with the service provider by the - developer of the consumer software. As part of that process, the service - provider gives the consumer a *key* and a *secret* with which the consumer - software can identify itself to the service. The consumer will include its - key in each request to identify itself, but will use its secret only when - signing requests, to prove that the request is from that particular - registered consumer. - - Once registered, the consumer can then use its consumer credentials to ask - the service provider for a request token, kicking off the OAuth - authorization process. - """ - - key = None - secret = None - - def __init__(self, key, secret): - self.key = key - self.secret = secret - - if self.key is None or self.secret is None: - raise ValueError("Key and secret must be set.") - - def __str__(self): - data = {'oauth_consumer_key': self.key, - 'oauth_consumer_secret': self.secret} - - return urllib.urlencode(data) - - -class Token(object): - """An OAuth credential used to request authorization or a protected - resource. - - Tokens in OAuth comprise a *key* and a *secret*. The key is included in - requests to identify the token being used, but the secret is used only in - the signature, to prove that the requester is who the server gave the - token to. - - When first negotiating the authorization, the consumer asks for a *request - token* that the live user authorizes with the service provider. The - consumer then exchanges the request token for an *access token* that can - be used to access protected resources. - """ - - key = None - secret = None - callback = None - callback_confirmed = None - verifier = None - - def __init__(self, key, secret): - self.key = key - self.secret = secret - - if self.key is None or self.secret is None: - raise ValueError("Key and secret must be set.") - - def set_callback(self, callback): - self.callback = callback - self.callback_confirmed = 'true' - - def set_verifier(self, verifier=None): - if verifier is not None: - self.verifier = verifier - else: - self.verifier = generate_verifier() - - def get_callback_url(self): - if self.callback and self.verifier: - # Append the oauth_verifier. - parts = urlparse.urlparse(self.callback) - scheme, netloc, path, params, query, fragment = parts[:6] - if query: - query = '%s&oauth_verifier=%s' % (query, self.verifier) - else: - query = 'oauth_verifier=%s' % self.verifier - return urlparse.urlunparse((scheme, netloc, path, params, - query, fragment)) - return self.callback - - def to_string(self): - """Returns this token as a plain string, suitable for storage. - - The resulting string includes the token's secret, so you should never - send or store this string where a third party can read it. - """ - - data = { - 'oauth_token': self.key, - 'oauth_token_secret': self.secret, - } - - if self.callback_confirmed is not None: - data['oauth_callback_confirmed'] = self.callback_confirmed - return urllib.urlencode(data) - - @staticmethod - def from_string(s): - """Deserializes a token from a string like one returned by - `to_string()`.""" - - if not len(s): - raise ValueError("Invalid parameter string.") - - params = parse_qs(s, keep_blank_values=False) - if not len(params): - raise ValueError("Invalid parameter string.") - - try: - key = params['oauth_token'][0] - except Exception: - raise ValueError("'oauth_token' not found in OAuth request.") - - try: - secret = params['oauth_token_secret'][0] - except Exception: - raise ValueError("'oauth_token_secret' not found in " - "OAuth request.") - - token = Token(key, secret) - try: - token.callback_confirmed = params['oauth_callback_confirmed'][0] - except KeyError: - pass # 1.0, no callback confirmed. - return token - - def __str__(self): - return self.to_string() - - -def setter(attr): - name = attr.__name__ - - def getter(self): - try: - return self.__dict__[name] - except KeyError: - raise AttributeError(name) - - def deleter(self): - del self.__dict__[name] - - return property(getter, attr, deleter) - - -class Request(dict): - - """The parameters and information for an HTTP request, suitable for - authorizing with OAuth credentials. - - When a consumer wants to access a service's protected resources, it does - so using a signed HTTP request identifying itself (the consumer) with its - key, and providing an access token authorized by the end user to access - those resources. - - """ - - version = VERSION - - def __init__(self, method=HTTP_METHOD, url=None, parameters=None): - self.method = method - self.url = url - if parameters is not None: - self.update(parameters) - - @setter - def url(self, value): - self.__dict__['url'] = value - if value is not None: - scheme, netloc, path, params, query, fragment = urlparse.urlparse(value) - - # Exclude default port numbers. - if scheme == 'http' and netloc[-3:] == ':80': - netloc = netloc[:-3] - elif scheme == 'https' and netloc[-4:] == ':443': - netloc = netloc[:-4] - if scheme not in ('http', 'https'): - raise ValueError("Unsupported URL %s (%s)." % (value, scheme)) - - # Normalized URL excludes params, query, and fragment. - self.normalized_url = urlparse.urlunparse((scheme, netloc, path, None, None, None)) - else: - self.normalized_url = None - self.__dict__['url'] = None - - @setter - def method(self, value): - self.__dict__['method'] = value.upper() - - def _get_timestamp_nonce(self): - return self['oauth_timestamp'], self['oauth_nonce'] - - def get_nonoauth_parameters(self): - """Get any non-OAuth parameters.""" - return dict([(k, v) for k, v in self.iteritems() - if not k.startswith('oauth_')]) - - def to_header(self, realm=''): - """Serialize as a header for an HTTPAuth request.""" - oauth_params = ((k, v) for k, v in self.items() - if k.startswith('oauth_')) - stringy_params = ((k, escape(str(v))) for k, v in oauth_params) - header_params = ('%s="%s"' % (k, v) for k, v in stringy_params) - params_header = ', '.join(header_params) - - auth_header = 'OAuth realm="%s"' % realm - if params_header: - auth_header = "%s, %s" % (auth_header, params_header) - - return {'Authorization': auth_header} - - def to_postdata(self): - """Serialize as post data for a POST request.""" - # tell urlencode to deal with sequence values and map them correctly - # to resulting querystring. for example self["k"] = ["v1", "v2"] will - # result in 'k=v1&k=v2' and not k=%5B%27v1%27%2C+%27v2%27%5D - return urllib.urlencode(self, True).replace('+', '%20') - - def to_url(self): - """Serialize as a URL for a GET request.""" - base_url = urlparse.urlparse(self.url) - try: - query = base_url.query - except AttributeError: - # must be python <2.5 - query = base_url[4] - query = parse_qs(query) - for k, v in self.items(): - query.setdefault(k, []).append(v) - - try: - scheme = base_url.scheme - netloc = base_url.netloc - path = base_url.path - params = base_url.params - fragment = base_url.fragment - except AttributeError: - # must be python <2.5 - scheme = base_url[0] - netloc = base_url[1] - path = base_url[2] - params = base_url[3] - fragment = base_url[5] - - url = (scheme, netloc, path, params, - urllib.urlencode(query, True), fragment) - return urlparse.urlunparse(url) - - def get_parameter(self, parameter): - ret = self.get(parameter) - if ret is None: - raise Error('Parameter not found: %s' % parameter) - - return ret - - def get_normalized_parameters(self): - """Return a string that contains the parameters that must be signed.""" - items = [] - for key, value in self.iteritems(): - if key == 'oauth_signature': - continue - # 1.0a/9.1.1 states that kvp must be sorted by key, then by value, - # so we unpack sequence values into multiple items for sorting. - if hasattr(value, '__iter__'): - items.extend((key, item) for item in value) - else: - items.append((key, value)) - - # Include any query string parameters from the provided URL - query = urlparse.urlparse(self.url)[4] - - url_items = self._split_url_string(query).items() - non_oauth_url_items = list([(k, v) for k, v in url_items if not k.startswith('oauth_')]) - items.extend(non_oauth_url_items) - - encoded_str = urllib.urlencode(sorted(items)) - # Encode signature parameters per Oauth Core 1.0 protocol - # spec draft 7, section 3.6 - # (http://tools.ietf.org/html/draft-hammer-oauth-07#section-3.6) - # Spaces must be encoded with "%20" instead of "+" - return encoded_str.replace('+', '%20').replace('%7E', '~') - - def sign_request(self, signature_method, consumer, token): - """Set the signature parameter to the result of sign.""" - - if 'oauth_consumer_key' not in self: - self['oauth_consumer_key'] = consumer.key - - if token and 'oauth_token' not in self: - self['oauth_token'] = token.key - - self['oauth_signature_method'] = signature_method.name - self['oauth_signature'] = signature_method.sign(self, consumer, token) - - @classmethod - def make_timestamp(cls): - """Get seconds since epoch (UTC).""" - return str(int(time.time())) - - @classmethod - def make_nonce(cls): - """Generate pseudorandom number.""" - return str(random.randint(0, 100000000)) - - @classmethod - def from_request(cls, http_method, http_url, headers=None, parameters=None, - query_string=None): - """Combines multiple parameter sources.""" - if parameters is None: - parameters = {} - - # Headers - if headers and 'Authorization' in headers: - auth_header = headers['Authorization'] - # Check that the authorization header is OAuth. - if auth_header[:6] == 'OAuth ': - auth_header = auth_header[6:] - try: - # Get the parameters from the header. - header_params = cls._split_header(auth_header) - parameters.update(header_params) - except: - raise Error('Unable to parse OAuth parameters from ' - 'Authorization header.') - - # GET or POST query string. - if query_string: - query_params = cls._split_url_string(query_string) - parameters.update(query_params) - - # URL parameters. - param_str = urlparse.urlparse(http_url)[4] # query - url_params = cls._split_url_string(param_str) - parameters.update(url_params) - - if parameters: - return cls(http_method, http_url, parameters) - - return None - - @classmethod - def from_consumer_and_token(cls, consumer, token=None, - http_method=HTTP_METHOD, http_url=None, parameters=None): - if not parameters: - parameters = {} - - defaults = { - 'oauth_consumer_key': consumer.key, - 'oauth_timestamp': cls.make_timestamp(), - 'oauth_nonce': cls.make_nonce(), - 'oauth_version': cls.version, - } - - defaults.update(parameters) - parameters = defaults - - if token: - parameters['oauth_token'] = token.key - if token.verifier: - parameters['oauth_verifier'] = token.verifier - - return Request(http_method, http_url, parameters) - - @classmethod - def from_token_and_callback(cls, token, callback=None, - http_method=HTTP_METHOD, http_url=None, parameters=None): - - if not parameters: - parameters = {} - - parameters['oauth_token'] = token.key - - if callback: - parameters['oauth_callback'] = callback - - return cls(http_method, http_url, parameters) - - @staticmethod - def _split_header(header): - """Turn Authorization: header into parameters.""" - params = {} - parts = header.split(',') - for param in parts: - # Ignore realm parameter. - if param.find('realm') > -1: - continue - # Remove whitespace. - param = param.strip() - # Split key-value. - param_parts = param.split('=', 1) - # Remove quotes and unescape the value. - params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\"')) - return params - - @staticmethod - def _split_url_string(param_str): - """Turn URL string into parameters.""" - parameters = parse_qs(param_str, keep_blank_values=False) - for k, v in parameters.iteritems(): - parameters[k] = urllib.unquote(v[0]) - return parameters - - -class Client(httplib2.Http): - """OAuthClient is a worker to attempt to execute a request.""" - - def __init__(self, consumer, token=None, cache=None, timeout=None, - proxy_info=None): - - if consumer is not None and not isinstance(consumer, Consumer): - raise ValueError("Invalid consumer.") - - if token is not None and not isinstance(token, Token): - raise ValueError("Invalid token.") - - self.consumer = consumer - self.token = token - self.method = SignatureMethod_HMAC_SHA1() - - httplib2.Http.__init__(self, cache=cache, timeout=timeout, - proxy_info=proxy_info) - - def set_signature_method(self, method): - if not isinstance(method, SignatureMethod): - raise ValueError("Invalid signature method.") - - self.method = method - - def request(self, uri, method="GET", body=None, headers=None, - redirections=httplib2.DEFAULT_MAX_REDIRECTS, connection_type=None): - DEFAULT_CONTENT_TYPE = 'application/x-www-form-urlencoded' - - if not isinstance(headers, dict): - headers = {} - - is_multipart = method == 'POST' and headers.get('Content-Type', - DEFAULT_CONTENT_TYPE) != DEFAULT_CONTENT_TYPE - - if body and method == "POST" and not is_multipart: - parameters = dict(parse_qsl(body)) - else: - parameters = None - - req = Request.from_consumer_and_token(self.consumer, - token=self.token, http_method=method, http_url=uri, - parameters=parameters) - - req.sign_request(self.method, self.consumer, self.token) - - if method == "POST": - headers['Content-Type'] = headers.get('Content-Type', - DEFAULT_CONTENT_TYPE) - if is_multipart: - headers.update(req.to_header()) - else: - body = req.to_postdata() - elif method == "GET": - uri = req.to_url() - else: - headers.update(req.to_header()) - - return httplib2.Http.request(self, uri, method=method, body=body, - headers=headers, redirections=redirections, - connection_type=connection_type) - - -class Server(object): - """A skeletal implementation of a service provider, providing protected - resources to requests from authorized consumers. - - This class implements the logic to check requests for authorization. You - can use it with your web server or web framework to protect certain - resources with OAuth. - """ - - timestamp_threshold = 300 # In seconds, five minutes. - version = VERSION - signature_methods = None - - def __init__(self, signature_methods=None): - self.signature_methods = signature_methods or {} - - def add_signature_method(self, signature_method): - self.signature_methods[signature_method.name] = signature_method - return self.signature_methods - - def verify_request(self, request, consumer, token): - """Verifies an api call and checks all the parameters.""" - - version = self._get_version(request) - self._check_signature(request, consumer, token) - parameters = request.get_nonoauth_parameters() - return parameters - - def build_authenticate_header(self, realm=''): - """Optional support for the authenticate header.""" - return {'WWW-Authenticate': 'OAuth realm="%s"' % realm} - - def _get_version(self, request): - """Verify the correct version request for this server.""" - try: - version = request.get_parameter('oauth_version') - except: - version = VERSION - - if version and version != self.version: - raise Error('OAuth version %s not supported.' % str(version)) - - return version - - def _get_signature_method(self, request): - """Figure out the signature with some defaults.""" - try: - signature_method = request.get_parameter('oauth_signature_method') - except: - signature_method = SIGNATURE_METHOD - - try: - # Get the signature method object. - signature_method = self.signature_methods[signature_method] - except: - signature_method_names = ', '.join(self.signature_methods.keys()) - raise Error('Signature method %s not supported try one of the following: %s' % (signature_method, signature_method_names)) - - return signature_method - - def _get_verifier(self, request): - return request.get_parameter('oauth_verifier') - - def _check_signature(self, request, consumer, token): - timestamp, nonce = request._get_timestamp_nonce() - self._check_timestamp(timestamp) - signature_method = self._get_signature_method(request) - - try: - signature = request.get_parameter('oauth_signature') - except: - raise MissingSignature('Missing oauth_signature.') - - # Validate the signature. - valid = signature_method.check(request, consumer, token, signature) - - if not valid: - key, base = signature_method.signing_base(request, consumer, token) - - raise Error('Invalid signature. Expected signature base ' - 'string: %s' % base) - - built = signature_method.sign(request, consumer, token) - - def _check_timestamp(self, timestamp): - """Verify that timestamp is recentish.""" - timestamp = int(timestamp) - now = int(time.time()) - lapsed = now - timestamp - if lapsed > self.timestamp_threshold: - raise Error('Expired timestamp: given %d and now %s has a ' - 'greater difference than threshold %d' % (timestamp, now, - self.timestamp_threshold)) - - -class SignatureMethod(object): - """A way of signing requests. - - The OAuth protocol lets consumers and service providers pick a way to sign - requests. This interface shows the methods expected by the other `oauth` - modules for signing requests. Subclass it and implement its methods to - provide a new way to sign requests. - """ - - def signing_base(self, request, consumer, token): - """Calculates the string that needs to be signed. - - This method returns a 2-tuple containing the starting key for the - signing and the message to be signed. The latter may be used in error - messages to help clients debug their software. - - """ - raise NotImplementedError - - def sign(self, request, consumer, token): - """Returns the signature for the given request, based on the consumer - and token also provided. - - You should use your implementation of `signing_base()` to build the - message to sign. Otherwise it may be less useful for debugging. - - """ - raise NotImplementedError - - def check(self, request, consumer, token, signature): - """Returns whether the given signature is the correct signature for - the given consumer and token signing the given request.""" - built = self.sign(request, consumer, token) - return built == signature - - -class SignatureMethod_HMAC_SHA1(SignatureMethod): - name = 'HMAC-SHA1' - - def signing_base(self, request, consumer, token): - if request.normalized_url is None: - raise ValueError("Base URL for request is not set.") - - sig = ( - escape(request.method), - escape(request.normalized_url), - escape(request.get_normalized_parameters()), - ) - - key = '%s&' % escape(consumer.secret) - if token: - key += escape(token.secret) - raw = '&'.join(sig) - return key, raw - - def sign(self, request, consumer, token): - """Builds the base signature string.""" - key, raw = self.signing_base(request, consumer, token) - - # HMAC object. - try: - from hashlib import sha1 as sha - except ImportError: - import sha # Deprecated - - hashed = hmac.new(key, raw, sha) - - # Calculate the digest base 64. - return binascii.b2a_base64(hashed.digest())[:-1] - - -class SignatureMethod_PLAINTEXT(SignatureMethod): - - name = 'PLAINTEXT' - - def signing_base(self, request, consumer, token): - """Concatenates the consumer key and secret with the token's - secret.""" - sig = '%s&' % escape(consumer.secret) - if token: - sig = sig + escape(token.secret) - return sig, sig - - def sign(self, request, consumer, token): - key, raw = self.signing_base(request, consumer, token) - return raw
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/__init__.py b/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/__init__.py deleted file mode 100644 index 2ae2839..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/__init__.py +++ /dev/null
@@ -1 +0,0 @@ -pass
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/imap.py b/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/imap.py deleted file mode 100644 index 68b7cd8..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/imap.py +++ /dev/null
@@ -1,40 +0,0 @@ -""" -The MIT License - -Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import oauth2 -import imaplib - - -class IMAP4_SSL(imaplib.IMAP4_SSL): - """IMAP wrapper for imaplib.IMAP4_SSL that implements XOAUTH.""" - - def authenticate(self, url, consumer, token): - if consumer is not None and not isinstance(consumer, oauth2.Consumer): - raise ValueError("Invalid consumer.") - - if token is not None and not isinstance(token, oauth2.Token): - raise ValueError("Invalid token.") - - imaplib.IMAP4_SSL.authenticate(self, 'XOAUTH', - lambda x: oauth2.build_xoauth_string(url, consumer, token))
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/smtp.py b/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/smtp.py deleted file mode 100644 index 3e7bf0b0..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/oauth2/clients/smtp.py +++ /dev/null
@@ -1,41 +0,0 @@ -""" -The MIT License - -Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import oauth2 -import smtplib -import base64 - - -class SMTP(smtplib.SMTP): - """SMTP wrapper for smtplib.SMTP that implements XOAUTH.""" - - def authenticate(self, url, consumer, token): - if consumer is not None and not isinstance(consumer, oauth2.Consumer): - raise ValueError("Invalid consumer.") - - if token is not None and not isinstance(token, oauth2.Token): - raise ValueError("Invalid token.") - - self.docmd('AUTH', 'XOAUTH %s' % \ - base64.b64encode(oauth2.build_xoauth_string(url, consumer, token)))
diff --git a/chrome/common/extensions/docs/examples/apps/hello-python/templates/index.html b/chrome/common/extensions/docs/examples/apps/hello-python/templates/index.html deleted file mode 100644 index 0602513..0000000 --- a/chrome/common/extensions/docs/examples/apps/hello-python/templates/index.html +++ /dev/null
@@ -1,57 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2009 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. ---> -<html> - <head> - <style> - body { font: 14px Arial; } - .credentials { text-align: right; } - p { padding: 100px 0; text-align: center; font-size: 24px; } - p strong { - display: inline-block; padding: 4px; border: 2px dotted #999; - border-radius: 10px; margin: 0 5px; - } - .noaccess strong { color: #900; border-color: #900; } - .fullaccess strong { color: #090; border-color: #090; } - .trialaccess strong { color: #009; border-color: #009; } - </style> - </head> - <body> - <div class="credentials"> - {% if user_login %} - <a href="{{user_login}}">Sign in</a> - {% else %} - <strong>{{user_id}}</strong> | <a href="{{user_logout}}">Sign out</a> - {% endif %} - </div> - {% if not license %} - <p class="notsignedin"> - You are <strong>not signed in</strong> to this app. - </p> - {% else %} - {% if license.error %} - <p><strong>There was an error loading the response:</strong>{{license.message}}</p> - {% else %} - {% ifequal license.access "NO" %} - <p class="noaccess"> - You have <strong>no access</strong> to extra features in this app. - </p> - {% endifequal %} - {% ifequal license.access "FREE_TRIAL" %} - <p class="trialaccess"> - You are currently enrolled in a <strong>free trial</strong> of this app. - </p> - {% endifequal %} - {% ifequal license.access "FULL" %} - <p class="fullaccess"> - You have <strong>full access</strong> to the features of this app. - </p> - {% endifequal %} - {% endif %} - {% endif %} - - </body> -</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/extensions/app_launcher/browser_action_icon.png b/chrome/common/extensions/docs/examples/extensions/app_launcher/browser_action_icon.png deleted file mode 100644 index e4b0f389..0000000 --- a/chrome/common/extensions/docs/examples/extensions/app_launcher/browser_action_icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/app_launcher/icon.png b/chrome/common/extensions/docs/examples/extensions/app_launcher/icon.png deleted file mode 100644 index a7e8b2b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/app_launcher/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/app_launcher/manifest.json b/chrome/common/extensions/docs/examples/extensions/app_launcher/manifest.json deleted file mode 100644 index 78e0c924..0000000 --- a/chrome/common/extensions/docs/examples/extensions/app_launcher/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "App Launcher", - "description": "Get access to your apps in a browser action", - "version": "0.7.3", - "permissions": ["management"], - "browser_action": { - "default_icon": "browser_action_icon.png", - "default_title": "App Launcher", - "default_popup": "popup.html" - }, - "icons": { - "48": "icon.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.css b/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.css deleted file mode 100644 index c42fc36..0000000 --- a/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.css +++ /dev/null
@@ -1,53 +0,0 @@ -/* Copyright (c) 2010 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. */ - -html { - overflow-x: hidden; -} - -body { - font-family: Helvetica, Arial, sans-serif; -} - -#search_container { - text-align: center; -} - -#search { - width: 85%; -} - -.app { - width: 100%; - margin-top: 7px; - margin-bottom: 7px; - margin-left: 2px; - margin-right: 20px; - white-space: nowrap; -} - -.app img { - vertical-align: middle; - height: 38px; - width: 38px; -} - -.app_title { - vertical-align: middle; - margin-left: 5px; -} - -.app:hover { - background-color: rgb(250,250,250); - cursor:pointer; - outline: 1px dotted rgb(100,100,200); -} - -.app_selected,.app_selected:hover { - background-color: rgb(230,230,230); -} - -#appstore_link { - display: none; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.html b/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.html deleted file mode 100644 index 77a9fb6..0000000 --- a/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!doctype html> -<!-- - * Copyright (c) 2010 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. ---> -<html> -<head> -<link rel="stylesheet" type="text/css" href="popup.css"> -<script src="popup.js"></script> -</head> -<body> - -<div id="spacer_dummy"></div> -<div id="outer"> - -<div id="appstore_link"> - <p>No apps installed.</p><p> - <button>Go get some</button></p> -</div> - -<div id="search_container"> - <input id="search" type="text" placeholder="type to search" spellcheck="false"> -</div> - -<div id="apps"></div> - -</div> - -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.js b/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.js deleted file mode 100644 index 788228c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/app_launcher/popup.js +++ /dev/null
@@ -1,213 +0,0 @@ -// Copyright (c) 2011 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. - -function $(id) { - return document.getElementById(id); -} - -// Returns the largest size icon, or a default icon, for the given |app|. -function getIconURL(app) { - if (!app.icons || app.icons.length == 0) { - return chrome.extension.getURL('icon.png'); - } - var largest = {size:0}; - for (var i = 0; i < app.icons.length; i++) { - var icon = app.icons[i]; - if (icon.size > largest.size) { - largest = icon; - } - } - return largest.url; -} - -function launchApp(id) { - chrome.management.launchApp(id); - window.close(); // Only needed on OSX because of crbug.com/63594 -} - -// Adds DOM nodes for |app| into |appsDiv|. -function addApp(appsDiv, app, selected) { - var div = document.createElement('div'); - div.className = 'app' + (selected ? ' app_selected' : ''); - - div.onclick = function() { - launchApp(app.id); - }; - - var img = document.createElement('img'); - img.src = getIconURL(app); - div.appendChild(img); - - var title = document.createElement('span'); - title.className = 'app_title'; - title.innerText = app.name; - div.appendChild(title); - - appsDiv.appendChild(div); -} - -// The list of all apps & extensions. -var completeList = []; - -// A filtered list of apps we actually want to show. -var appList = []; - -// The index of an app in |appList| that should be highlighted. -var selectedIndex = 0; - -function reloadAppDisplay() { - var appsDiv = $('apps'); - - // Empty the current content. - appsDiv.innerHTML = ''; - - for (var i = 0; i < appList.length; i++) { - var item = appList[i]; - addApp(appsDiv, item, i == selectedIndex); - } -} - -// Puts only enabled apps from completeList into appList. -function rebuildAppList(filter) { - selectedIndex = 0; - appList = []; - for (var i = 0; i < completeList.length; i++){ - var item = completeList[i]; - // Skip extensions and disabled apps. - if (!item.isApp || !item.enabled) { - continue; - } - if (filter && item.name.toLowerCase().search(filter) < 0) { - continue; - } - appList.push(item); - } -} - -// In order to keep the popup bubble from shrinking as your search narrows the -// list of apps shown, we set an explicit width on the outermost div. -var didSetExplicitWidth = false; - -function adjustWidthIfNeeded(filter) { - if (filter.length > 0 && !didSetExplicitWidth) { - // Set an explicit width, correcting for any scroll bar present. - var outer = $('outer'); - var correction = window.innerWidth - document.documentElement.clientWidth; - var width = outer.offsetWidth; - $('spacer_dummy').style.width = width + correction + 'px'; - didSetExplicitWidth = true; - } -} - -// Shows the list of apps based on the search box contents. -function onSearchInput() { - var filter = $('search').value; - adjustWidthIfNeeded(filter); - rebuildAppList(filter); - reloadAppDisplay(); -} - -function compare(a, b) { - return (a > b) ? 1 : (a == b ? 0 : -1); -} - -function compareByName(app1, app2) { - return compare(app1.name.toLowerCase(), app2.name.toLowerCase()); -} - -// Changes the selected app in the list. -function changeSelection(newIndex) { - if (newIndex >= 0 && newIndex <= appList.length - 1) { - selectedIndex = newIndex; - reloadAppDisplay(); - - var selected = document.getElementsByClassName('app_selected')[0]; - var rect = selected.getBoundingClientRect(); - if (newIndex == 0) { - window.scrollTo(0, 0); - } else if (newIndex == appList.length - 1) { - window.scrollTo(0, document.height); - } else if (rect.top < 0) { - window.scrollBy(0, rect.top); - } else if (rect.bottom > innerHeight) { - window.scrollBy(0, rect.bottom - innerHeight); - } - } -} - -var keys = { - ENTER : 13, - ESCAPE : 27, - END : 35, - HOME : 36, - LEFT : 37, - UP : 38, - RIGHT : 39, - DOWN : 40 -}; - -// Set up a key event handler that handles moving the selected app up/down, -// hitting enter to launch the selected app, as well as auto-focusing the -// search box as soon as you start typing. -window.onkeydown = function(event) { - switch (event.keyCode) { - case keys.DOWN: - changeSelection(selectedIndex + 1); - break; - case keys.UP: - changeSelection(selectedIndex - 1); - break; - case keys.HOME: - changeSelection(0); - break; - case keys.END: - changeSelection(appList.length - 1); - break; - case keys.ENTER: - var app = appList[selectedIndex]; - if (app) { - launchApp(app.id); - } - break; - default: - // Focus the search box and return true so you can just start typing even - // when the search box isn't focused. - $('search').focus(); - return true; - } - return false; -}; - - -// Initalize the popup window. -document.addEventListener('DOMContentLoaded', function () { - chrome.management.getAll(function(info) { - var appCount = 0; - for (var i = 0; i < info.length; i++) { - if (info[i].isApp) { - appCount++; - } - } - if (appCount == 0) { - $('search').style.display = 'none'; - $('appstore_link').style.display = ''; - return; - } - completeList = info.sort(compareByName); - onSearchInput(); - }); - - $('search').addEventListener('input', onSearchInput); - - // Opens the webstore in a new tab. - document.querySelector('#appstore_link button').addEventListener('click', - function () { - chrome.tabs.create({ - 'url':'https://chrome.google.com/webstore', - 'selected':true - }); - window.close(); - }); -}); -
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/active_issues.js b/chrome/common/extensions/docs/examples/extensions/buildbot/active_issues.js deleted file mode 100644 index f85f32f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/active_issues.js +++ /dev/null
@@ -1,54 +0,0 @@ -// Copyright 2013 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. - -(function(){ - -window.buildbot = window.buildbot || {}; - -buildbot.ActiveIssues = function() { - this.issues_ = {}; - this.eventCallback_ = null; -}; - -buildbot.ActiveIssues.prototype = { - forEach: function(callback) { - for (var key in this.issues_) - callback(this.issues_[key]); - }, - - getIssue: function(number) { - return this.issues_[number]; - }, - - updateIssue: function(issue) { - var eventType = this.issues_.hasOwnProperty(issue.issue) ? - "issueUpdated" : "issueAdded"; - this.issues_[issue.issue] = issue; - this.postEvent_({event: eventType, issue: issue.issue}); - }, - - removeIssue: function(issue) { - delete this.issues_[issue.issue]; - this.postEvent_({event: "issueRemoved", issue: issue.issue}); - }, - - setEventCallback: function(callback) { - this.eventCallback_ = callback; - }, - - postEvent_: function(obj) { - if (this.eventCallback_) - this.eventCallback_(obj); - } -}; - -buildbot.getActiveIssues = function() { - var background = chrome.extension.getBackgroundPage(); - if (!background.buildbot.hasOwnProperty("activeIssues")) - background.buildbot.activeIssues = new buildbot.ActiveIssues; - - return background.buildbot.activeIssues; -}; - -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/bg.js b/chrome/common/extensions/docs/examples/extensions/buildbot/bg.js deleted file mode 100644 index 8324e03a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/bg.js +++ /dev/null
@@ -1,274 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// TODO(wittman): Convert this extension to event pages once they work with -// the notifications API. Currently it's not possible to restore the -// Notification object when event pages get reloaded. See -// http://crbug.com/165276. - -(function() { - -var statusURL = "http://chromium-status.appspot.com/current?format=raw"; -var statusHistoryURL = - "http://chromium-status.appspot.com/allstatus?limit=20&format=json"; -var pollFrequencyInMs = 30000; -var tryPollFrequencyInMs = 30000; - -var prefs = new buildbot.PrefStore; - -function updateBadgeOnErrorStatus() { - chrome.browserAction.setBadgeText({text:"?"}); - chrome.browserAction.setBadgeBackgroundColor({color:[0,0,255,255]}); -} - -var lastNotification = null; -function notifyStatusChange(treeState, status) { - if (lastNotification) - lastNotification.close(); - - lastNotification = new Notification("Tree is " + treeState, { - icon: chrome.extension.getURL("icon.png"), - body: status - }); -} - -// The type parameter should be "open", "closed", or "throttled". -function getLastStatusTime(callback, type) { - buildbot.requestURL(statusHistoryURL, "text", function(text) { - var entries = JSON.parse(text); - - for (var i = 0; i < entries.length; i++) { - if (entries[i].general_state == type) { - callback(new Date(entries[i].date + " UTC")); - return; - } - } - }, updateBadgeOnErrorStatus); -} - -function updateTimeBadge(timeDeltaInMs) { - var secondsSinceChangeEvent = Math.round(timeDeltaInMs / 1000); - var minutesSinceChangeEvent = Math.round(secondsSinceChangeEvent / 60); - var hoursSinceChangeEvent = Math.round(minutesSinceChangeEvent / 60); - var daysSinceChangeEvent = Math.round(hoursSinceChangeEvent / 24); - - var text; - if (secondsSinceChangeEvent < 60) { - text = "<1m"; - } else if (minutesSinceChangeEvent < 57.5) { - if (minutesSinceChangeEvent < 30) { - text = minutesSinceChangeEvent + "m"; - } else { - text = Math.round(minutesSinceChangeEvent / 5) * 5 + "m"; - } - } else if (minutesSinceChangeEvent < 5 * 60) { - var halfHours = Math.round(minutesSinceChangeEvent / 30); - text = Math.floor(halfHours / 2) + (halfHours % 2 ? ".5" : "") + "h"; - } else if (hoursSinceChangeEvent < 23.5) { - text = hoursSinceChangeEvent + "h"; - } else { - text = daysSinceChangeEvent + "d"; - } - - chrome.browserAction.setBadgeText({text: text}); -} - -var lastState; -var lastChangeTime; -function updateStatus(status) { - var badgeState = { - open: {color: [0,255,0,255], defaultText: "\u2022"}, - closed: {color: [255,0,0,255], defaultText: "\u00D7"}, - throttled: {color: [255,255,0,255], defaultText: "!"} - }; - - chrome.browserAction.setTitle({title:status}); - var treeState = (/open/i).exec(status) ? "open" : - (/throttled/i).exec(status) ? "throttled" : "closed"; - - if (lastState && lastState != treeState) { - prefs.getUseNotifications(function(useNotifications) { - if (useNotifications) - notifyStatusChange(treeState, status); - }); - } - - chrome.browserAction.setBadgeBackgroundColor( - {color: badgeState[treeState].color}); - - if (lastChangeTime === undefined) { - chrome.browserAction.setBadgeText( - {text: badgeState[treeState].defaultText}); - lastState = treeState; - getLastStatusTime(function(time) { - lastChangeTime = time; - updateTimeBadge(Date.now() - lastChangeTime); - }, treeState); - } else { - if (treeState != lastState) { - lastState = treeState; - // The change event will occur 1/2 the polling frequency before we - // are aware of it, on average. - lastChangeTime = Date.now() - pollFrequencyInMs / 2; - } - updateTimeBadge(Date.now() - lastChangeTime); - } -} - -function requestStatus() { - buildbot.requestURL(statusURL, - "text", - updateStatus, - updateBadgeOnErrorStatus); - setTimeout(requestStatus, pollFrequencyInMs); -} - -// Record of the last defunct build number we're aware of on each builder. If -// the build number is less than or equal to this number, the buildbot -// information is not available and a request will return a 404. -var lastDefunctTryJob = {}; - -function fetchTryJobResults(fullPatchset, builder, buildnumber, completed) { - var tryJobURL = - "http://build.chromium.org/p/tryserver.chromium/json/builders/" + - builder + "/builds/" + buildnumber; - - if (lastDefunctTryJob.hasOwnProperty(builder) && - buildnumber <= lastDefunctTryJob[builder]) { - completed(); - return; - } - - buildbot.requestURL(tryJobURL, "json", function(tryJobResult) { - if (!fullPatchset.full_try_job_results) - fullPatchset.full_try_job_results = {}; - - var key = builder + "-" + buildnumber; - fullPatchset.full_try_job_results[key] = tryJobResult; - - completed(); - }, function(errorStatus) { - if (errorStatus == 404) { - lastDefunctTryJob[builder] = - Math.max(lastDefunctTryJob[builder] || 0, buildnumber); - } - completed(); - }); -} - -// Enums corresponding to how much state has been loaded for an issue. -var PATCHES_COMPLETE = 0; -var TRY_JOBS_COMPLETE = 1; - -function fetchPatches(issue, updatedCallback) { - // Notify updated once after receiving all patchsets, and a second time after - // receiving all try job results. - var patchsetsRetrieved = 0; - var tryJobResultsOutstanding = 0; - issue.patchsets.forEach(function(patchset) { - var patchURL = "https://codereview.chromium.org/api/" + issue.issue + - "/" + patchset; - - buildbot.requestURL(patchURL, "json", function(patch) { - if (!issue.full_patchsets) - issue.full_patchsets = {}; - - issue.full_patchsets[patch.patchset] = patch; - - // TODO(wittman): Revise to reduce load on the try servers. Repeatedly - // loading old try results increases the size of the working set of try - // jobs on the try servers, causing them to become disk-bound. - // patch.try_job_results.forEach(function(results) { - // if (results.buildnumber) { - // tryJobResultsOutstanding++; - - // fetchTryJobResults(patch, results.builder, results.buildnumber, - // function() { - // if (--tryJobResultsOutstanding == 0) - // updatedCallback(TRY_JOBS_COMPLETE); - // }); - // } - // }); - - if (++patchsetsRetrieved == issue.patchsets.length) { - updatedCallback(PATCHES_COMPLETE); - // TODO(wittman): Remove once we revise the try job fetching code. - updatedCallback(TRY_JOBS_COMPLETE); - } - }); - }); -} - -function updateTryStatus(status) { - var seen = {}; - var activeIssues = buildbot.getActiveIssues(); - status.results.forEach(function(result) { - var issueURL = "https://codereview.chromium.org/api/" + result.issue; - - buildbot.requestURL(issueURL, "json", function(issue) { - fetchPatches(issue, function(state) { - // If the issue already exists, wait until all the issue state has - // loaded before updating the issue so we don't lose try job information - // from the display. - if (activeIssues.getIssue(issue.issue)) { - if (state == TRY_JOBS_COMPLETE) - activeIssues.updateIssue(issue); - } else { - activeIssues.updateIssue(issue); - } - }); - }); - - seen[result.issue] = true; - }); - - activeIssues.forEach(function(issue) { - if (!seen[issue.issue]) - activeIssues.removeIssue(issue); - }); -} - -function fetchTryStatus(username) { - if (!username) - return; - - var url = "https://codereview.chromium.org/search" + - // commit=2 is CLs with commit bit set, commit=3 is CLs with commit - // bit cleared, commit=1 is either. - "?closed=3&commit=1&limit=100&order=-modified&format=json&owner=" + - username.trim(); - buildbot.requestURL(url, "json", updateTryStatus); -} - -function requestTryStatus() { - var searchBaseURL = "https://codereview.chromium.org/search"; - - prefs.getTryJobUsername(function(username) { - if (username == null) { - var usernameScrapingURL = "https://codereview.chromium.org/search"; - // Try scraping username from Rietveld if unset. - buildbot.requestURL(usernameScrapingURL, "text", function(text) { - var match = /([^<>\s]+@\S+)\s+\(.+\)/.exec(text); - if (match) { - username = match[1]; - prefs.setTryJobUsername(username); - fetchTryStatus(username); - } - }); - } else { - fetchTryStatus(username); - } - - setTimeout(requestTryStatus, tryPollFrequencyInMs); - }); -} - -function main() { - requestStatus(); - requestTryStatus(); -} - -main(); - -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/chromium.png b/chrome/common/extensions/docs/examples/extensions/buildbot/chromium.png deleted file mode 100644 index 0847b263..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/chromium.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/icon.png b/chrome/common/extensions/docs/examples/extensions/buildbot/icon.png deleted file mode 100644 index c644a85..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/manifest.json b/chrome/common/extensions/docs/examples/extensions/buildbot/manifest.json deleted file mode 100644 index 0d86bcb..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/manifest.json +++ /dev/null
@@ -1,31 +0,0 @@ -{ - "name": "Chromium Buildbot Monitor", - "version": "0.9.0", - "description": "Displays the status of the Chromium buildbot in the toolbar. Click to see more detailed status in a popup.", - "icons": { "128": "icon.png" }, - "background": { - "scripts": ["utils.js", - "prefs.js", - "try_status.js", - "active_issues.js", - "bg.js"] - }, - "permissions": [ - "notifications", - "storage", - "http://build.chromium.org/", - "http://chromium-status.appspot.com/", - "https://codereview.chromium.org/" - ], - "browser_action": { - "default_title": "", - "default_icon": "chromium.png", - "default_popup": "popup.html" - }, - "options_page": "options.html", - "options_ui": { - "chrome_style": true, - "page": "options.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/options.html b/chrome/common/extensions/docs/examples/extensions/buildbot/options.html deleted file mode 100644 index e045aa6..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/options.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!doctype html> -<html> -<head> - <title>Chromium Buildbot Monitor Options</title> - <style> - body { - padding: 10px; - } - </style> -</head> -<body> - <label> - Use desktop notifications: - <input id="notifications" type="checkbox"> - </label> - <br> - <label> - Username for try job monitoring: - <input id="try-job-username" type="text"> - </label> - <script src='prefs.js'></script> - <script src='options.js'></script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/options.js b/chrome/common/extensions/docs/examples/extensions/buildbot/options.js deleted file mode 100644 index 78c2994..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/options.js +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(function() { - -window.buildbot = window.buildbot || {}; - -var prefs = new buildbot.PrefStore; - -// Initialize the checkbox checked state from the saved preference. -function main() { - var checkbox = document.getElementById('notifications'); - prefs.getUseNotifications(function(useNotifications) { - checkbox.checked = useNotifications; - checkbox.addEventListener( - 'click', - function() {prefs.setUseNotifications(checkbox.checked);}); - }); - - var textbox = document.getElementById('try-job-username'); - prefs.getTryJobUsername(function(tryJobUsername) { - textbox.value = tryJobUsername; - textbox.addEventListener( - 'change', - function() {prefs.setTryJobUsername(textbox.value);}); - }); -} - -main(); - -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/popup.css b/chrome/common/extensions/docs/examples/extensions/buildbot/popup.css deleted file mode 100644 index a6f597e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/popup.css +++ /dev/null
@@ -1,93 +0,0 @@ -/** - * Copyright 2013 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. - */ - -body { - font-family: sans-serif; - font-size: 0.8em; - overflow: hidden; -} - -a { - text-decoration: underline; - color: #444; -} - -a:hover { - color: black; - cursor: pointer; -} - -.status-label { - text-align: right; - font-size: 12px; - font-weight: bold; - min-width: 85px; - padding: 0px; -} - -.trunk-status-cell { - padding: 0px; -} - -.trunk-status-cell > iframe { - height: 10px; - border: none; -} - -[data-issue] + .trunk-status-row > td, -.closer-status-row + .other-status-row > td { - padding-top: 5px; -} - -div.issue-status { - display: table; - border-spacing: 1px 1px; - width: 284px; - margin: 1px 0px 1px 9px; -} - -.issue-status-build { - display: table-cell; - width: 1px; - height: 10px; -} - -/* build statuses */ -.success { - color: #FFFFFF; - background-color: #8fdf5f; - border-color: #4F8530; -} - -.failure { - color: #FFFFFF; - background-color: #e98080; - border-color: #A77272; -} - -.warnings { - color: #FFFFFF; - background-color: #ffc343; - border-color: #C29D46; -} - -.never { - color: #FFFFFF; - background-color: #f0f0e0; - border-color: #A77272; -} - -.exception, .retry { - color: #FFFFFF; - background-color: #e0b0ff; - border-color: #ACA0B3; -} - -.running { - color: #666666; - background-color: #fffc6c; - border-color: #C5C56D; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/popup.html b/chrome/common/extensions/docs/examples/extensions/buildbot/popup.html deleted file mode 100644 index d9366f57..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/popup.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Chromium Buildbot Monitor Popup</title> - <link href="popup.css" rel="stylesheet" type="text/css" /> - </head> - <body> - <table id="status-table"></table> - <script src='utils.js'></script> - <script src='try_status.js'></script> - <script src='active_issues.js'></script> - <script src='popup.js'></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/popup.js b/chrome/common/extensions/docs/examples/extensions/buildbot/popup.js deleted file mode 100644 index 1fb4b04..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/popup.js +++ /dev/null
@@ -1,301 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -(function(){ - -var lkgrURL = 'http://chromium-status.appspot.com/lkgr'; - -// Interval at which to reload the non-CL bot status. -var botStatusRefreshIntervalInMs = 60 * 1000; -// Interval at which to check for LKGR updates. -var lkgrRefreshIntervalInMs = 60 * 1000; - -function getClassForTryJobResult(result) { - // Some win bots seem to report a null result while building. - if (result === null) - result = buildbot.RUNNING; - - switch (parseInt(result)) { - case buildbot.RUNNING: - return "running"; - - case buildbot.SUCCESS: - return "success"; - - case buildbot.WARNINGS: - return "warnings"; - - case buildbot.FAILURE: - return "failure"; - - case buildbot.SKIPPED: - return "skipped"; - - case buildbot.EXCEPTION: - return "exception"; - - case buildbot.RETRY: - return "retry"; - - case buildbot.NOT_STARTED: - default: - return "never"; - } -} - -// Remove try jobs that have been supplanted by newer runs. -function filterOldTryJobs(tryJobs) { - var latest = {}; - tryJobs.forEach(function(tryJob) { - if (!latest[tryJob.builder] || - latest[tryJob.builder].buildnumber < tryJob.buildnumber) - latest[tryJob.builder] = tryJob; - }); - - var result = []; - tryJobs.forEach(function(tryJob) { - if (tryJob.buildnumber == latest[tryJob.builder].buildnumber) - result.push(tryJob); - }); - - return result; -} - -function createTryJobAnchorTitle(tryJob, fullTryJob) { - var title = tryJob.builder; - - if (!fullTryJob) - return title; - - var stepText = []; - if (fullTryJob.currentStep) - stepText.push("running " + fullTryJob.currentStep.name); - - if (fullTryJob.results == buildbot.FAILURE && fullTryJob.text) { - stepText.push(fullTryJob.text.join(" ")); - } else { - // Sometimes a step can fail without setting the try job text. Look - // through all the steps to identify if this is the case. - var text = []; - fullTryJob.steps.forEach(function(step) { - if (step.results[0] == buildbot.FAILURE) - text.push(step.results[1][0]); - }); - - if (text.length > 0) { - text.unshift("failure"); - stepText.push(text.join(" ")); - } - } - - if (stepText.length > 0) - title += ": " + stepText.join("; "); - - return title; -} - -function createPatchsetStatusElement(patchset) { - var table = document.createElement("div"); - table.className = "issue-status"; - - var tryJobs = filterOldTryJobs(patchset.try_job_results); - tryJobs.forEach(function(tryJob) { - var key = tryJob.builder + "-" + tryJob.buildnumber; - var fullTryJob = patchset.full_try_job_results && - patchset.full_try_job_results[key]; - - var tryJobAnchor = document.createElement("a"); - tryJobAnchor.textContent = " "; - tryJobAnchor.title = createTryJobAnchorTitle(tryJob, fullTryJob); - tryJobAnchor.className = "issue-status-build " + - getClassForTryJobResult(tryJob.result); - tryJobAnchor.target = "_blank"; - tryJobAnchor.href = tryJob.url; - table.appendChild(tryJobAnchor); - }); - - return table; -} - -function getLastFullPatchsetWithTryJobs(issue) { - var index = issue.patchsets.length - 1; - var fullPatchsets = issue.full_patchsets; - while (index >= 0 && - (!fullPatchsets || - !fullPatchsets[issue.patchsets[index]] || - !fullPatchsets[issue.patchsets[index]].try_job_results || - fullPatchsets[issue.patchsets[index]].try_job_results.length == 0)) { - index--; - } - - return index >= 0 ? fullPatchsets[issue.patchsets[index]] : null; -} - -function createTryStatusRow(issue) { - var table = document.getElementById("status-table"); - - // Order by decreasing issue number. - var position = - document.getElementsByClassName("trunk-status-row")[0].rowIndex; - while (position > 0 && - parseInt(issue.issue) > - parseInt(table.rows[position - 1].getAttribute("data-issue"))) { - position--; - } - - var row = table.insertRow(position); - row.setAttribute("data-issue", issue.issue); - - return row; -} - -function updateIssueDisplay(issue) { - var codereviewBaseURL = "https://codereview.chromium.org"; - - var lastFullPatchset = getLastFullPatchsetWithTryJobs(issue); - - var row = document.querySelector("*[data-issue='" + issue.issue + "']"); - if (!lastFullPatchset) { - if (row) - row.parentNode.removeChild(row); - return; - } - - if (!row) - row = createTryStatusRow(issue); - - var label = row.childNodes[0] || row.insertCell(-1); - var status = row.childNodes[1] || row.insertCell(-1); - - label.className = "status-label"; - var clAnchor = label.childNodes[0] || - label.appendChild(document.createElement("a")); - clAnchor.textContent = "CL " + issue.issue; - clAnchor.href = codereviewBaseURL + "/" + issue.issue; - clAnchor.title = issue.subject; - if (lastFullPatchset && lastFullPatchset.message) - clAnchor.title += " | " + lastFullPatchset.message; - clAnchor.target = "_blank"; - - var statusElement = createPatchsetStatusElement(lastFullPatchset); - if (status.childElementCount < 1) - status.appendChild(statusElement); - else - status.replaceChild(statusElement, status.firstChild); -} - -function removeIssueDisplay(issueNumber) { - var row = document.querySelector("*[data-issue='" + issueNumber + "']"); - row.parentNode.removeChild(row); -} - -function addTryStatusRows() { - buildbot.getActiveIssues().forEach(updateIssueDisplay); -} - -function updateLKGR(lkgr) { - var link = document.getElementById('link_lkgr'); - link.textContent = 'LKGR (' + lkgr + ')'; -} - -function addBotStatusRow(bot, className) { - var table = document.getElementById("status-table"); - - var baseURL = "http://build.chromium.org/p/chromium" + - (bot.id != "" ? "." + bot.id : ""); - var consoleURL = baseURL + "/console"; - var statusURL = baseURL + "/horizontal_one_box_per_builder"; - - var row = table.insertRow(-1); - row.className = "trunk-status-row " + className; - var label = row.insertCell(-1); - label.className = "status-label"; - var labelAnchor = document.createElement("a"); - labelAnchor.href = consoleURL; - labelAnchor.target = "_blank"; - labelAnchor.id = "link_" + bot.id; - labelAnchor.textContent = bot.label; - label.appendChild(labelAnchor); - - var status = row.insertCell(-1); - status.className = "trunk-status-cell"; - var statusIframe = document.createElement("iframe"); - statusIframe.scrolling = "no"; - statusIframe.src = statusURL; - status.appendChild(statusIframe); -} - -function addBotStatusRows() { - var closerBots = [ - {id: "", label: "Chromium"}, - {id: "win", label: "Win"}, - {id: "mac", label: "Mac"}, - {id: "linux", label: "Linux"}, - {id: "chromiumos", label: "ChromiumOS"}, - {id: "chrome", label: "Official"}, - {id: "memory", label: "Memory"} - ]; - - var otherBots = [ - {id: "lkgr", label: "LKGR"}, - {id: "perf", label: "Perf"}, - {id: "memory.fyi", label: "Memory FYI"}, - {id: "gpu", label: "GPU"}, - {id: "gpu.fyi", label: "GPU FYI"} - ]; - - closerBots.forEach(function(bot) { - addBotStatusRow(bot, "closer-status-row"); - }); - - otherBots.forEach(function(bot) { - addBotStatusRow(bot, "other-status-row"); - }); -} - -function fillStatusTable() { - addBotStatusRows(); - addTryStatusRows(); -} - -function main() { - buildbot.requestURL(lkgrURL, "text", updateLKGR); - fillStatusTable(); - - buildbot.getActiveIssues().setEventCallback(function(request) { - // NOTE(wittman): It doesn't appear that we can reliably detect closing of - // the popup and remove the event callback, so ensure the popup window is - // displayed before processing the event. - if (!chrome.extension.getViews({type: "popup"})) - return; - - switch (request.event) { - case "issueUpdated": - case "issueAdded": - updateIssueDisplay(buildbot.getActiveIssues().getIssue(request.issue)); - break; - - case "issueRemoved": - removeIssueDisplay(request.issue); - break; - } - }); - - setInterval(function() { - buildbot.requestURL(lkgrURL, "text", updateLKGR); - }, lkgrRefreshIntervalInMs); - - setInterval(function() { - var botStatusElements = - document.getElementsByClassName("trunk-status-iframe"); - for (var i = 0; i < botStatusElements.length; i++) - // Force a reload of the iframe in a way that doesn't cause cross-domain - // policy violations. - botStatusElements.item(i).src = botStatusElements.item(i).src; - }, botStatusRefreshIntervalInMs); -} - -main(); - -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/prefs.js b/chrome/common/extensions/docs/examples/extensions/buildbot/prefs.js deleted file mode 100644 index 3071be3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/prefs.js +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright (c) 2013 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. - -(function() { - -window.buildbot = window.buildbot || {}; - -buildbot.PrefStore = function() { - this.defaults_ = {prefs: {use_notifications: false, - try_job_username: null}}; -}; - -buildbot.PrefStore.prototype = { - get_: function(key, callback) { - chrome.storage.sync.get(this.defaults_, - function (storage) { - callback(storage.prefs[key]); - }); - }, - - set_: function(key, value) { - chrome.storage.sync.get(this.defaults_, - function (storage) { - storage.prefs[key] = value; - chrome.storage.sync.set(storage); - }); - }, - - getUseNotifications: function(callback) { - this.get_("use_notifications", callback); - }, - - setUseNotifications: function(use_notifications) { - this.set_("use_notifications", use_notifications); - }, - - getTryJobUsername: function(callback) { - this.get_("try_job_username", callback); - }, - - setTryJobUsername: function(try_job_username) { - this.set_("try_job_username", try_job_username); - } -}; - -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/try_status.js b/chrome/common/extensions/docs/examples/extensions/buildbot/try_status.js deleted file mode 100644 index 1641580..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/try_status.js +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright (c) 2013 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. - -(function() { - -window.buildbot = window.buildbot || {}; - -buildbot.RUNNING = -1; -buildbot.SUCCESS = 0; -buildbot.WARNINGS = 1; -buildbot.FAILURE = 2; -buildbot.SKIPPED = 3; -buildbot.EXCEPTION = 4; -buildbot.RETRY = 5; -buildbot.NOT_STARTED = 6; - -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/buildbot/utils.js b/chrome/common/extensions/docs/examples/extensions/buildbot/utils.js deleted file mode 100644 index ace9ed594..0000000 --- a/chrome/common/extensions/docs/examples/extensions/buildbot/utils.js +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright (c) 2013 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. - -(function() { - -window.buildbot = window.buildbot || {}; - -buildbot.requestURL = - function(url, responseType, callback, opt_errorStatusCallback) { - var xhr = new XMLHttpRequest(); - if (responseType == "json") - // WebKit doesn't handle xhr.responseType = "json" as of Chrome 25. - xhr.responseType = "text"; - else - xhr.responseType = responseType; - - xhr.onreadystatechange = function(state) { - if (xhr.readyState == 4) { - if (xhr.status == 200) { - var response = - responseType == "json" ? JSON.parse(xhr.response) : xhr.response; - callback(response); - } else { - if (opt_errorStatusCallback) - opt_errorStatusCallback(xhr.status); - } - } - }; - - xhr.onerror = function(error) { - console.log("xhr error:", error); - }; - - xhr.open("GET", url, true); - xhr.send(); -}; - -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ar/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ar/messages.json deleted file mode 100644 index 3fd46a01..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ar/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u062a\u062f\u0639\u0645\u0647\u0627 Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u064a\u0645\u0643\u0646\u0643 \u0628\u0633\u0631\u0639\u0629 \u0627\u0644\u062a\u0639\u0631\u0641 \u0639\u0644\u0649 \u0627\u0644\u0648\u0642\u062a \u0627\u0644\u0645\u062a\u0628\u0642\u064a \u0644\u0643 \u0625\u0644\u0649 \u0623\u0646 \u064a\u062d\u064a\u0646 \u0645\u0648\u0639\u062f \u0627\u062c\u062a\u0645\u0627\u0639\u0643 \u0627\u0644\u062a\u0627\u0644\u064a \u0645\u0646 \u0623\u064a \u062a\u0642\u0648\u064a\u0645 \u0645\u0646 \u062a\u0642\u0627\u0648\u064a\u0645\u0643. \u0627\u0646\u0642\u0631 \u0639\u0644\u0649 \u0627\u0644\u0632\u0631 \u0644\u064a\u062a\u0645 \u0646\u0642\u0644\u0643 \u0625\u0644\u0649 \u0627\u0644\u062a\u0642\u0648\u064a\u0645."},"direction":{"message":"rtl"},"notitle":{"message":"(\u0644\u064a\u0633 \u0647\u0646\u0627\u0643 \u0623\u064a \u0639\u0646\u0648\u0627\u0646)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 \u062f\u0642\u064a\u0642\u0629","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 \u0633\u0627\u0639\u0629","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 \u064a\u0648\u0645","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u062f\u0639\u0645 \u0645\u062a\u0639\u062f\u062f \u0644\u0644\u062a\u0642\u0648\u064a\u0645"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u062a\u0645 \u062d\u0641\u0638 \u0627\u0644\u0625\u0639\u062f\u0627\u062f\u0627\u062a."},"status_saving":{"message":"\u062c\u0627\u0631\u0650 \u0627\u0644\u062d\u0641\u0638..."},"multicalendartooltip":{"message":"\u0627\u0644\u0631\u062c\u0627\u0621 \u062a\u062d\u062f\u064a\u062f \u0627\u0644\u0645\u0631\u0628\u0639 \u0644\u062a\u0645\u0643\u064a\u0646 \u0627\u0644\u062f\u0639\u0645 \u0627\u0644\u0645\u062a\u0639\u062f\u062f \u0644\u0644\u062a\u0642\u0648\u064a\u0645."},"imagetooltip":{"message":"\u062a\u0642\u0648\u064a\u0645 Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/bg/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/bg/messages.json deleted file mode 100644 index e7dc1a6..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/bg/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (by Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u0412\u0438\u0436\u0442\u0435 \u0431\u044a\u0440\u0437\u043e \u043a\u043e\u043b\u043a\u043e \u0432\u0440\u0435\u043c\u0435 \u0432\u0438 \u043e\u0441\u0442\u0430\u0432\u0430 \u0434\u043e \u0441\u043b\u0435\u0434\u0432\u0430\u0449\u0430\u0442\u0430 \u0432\u0438 \u0441\u0440\u0435\u0449\u0430 \u043e\u0442 \u0432\u0441\u0435\u043a\u0438 \u0441\u0432\u043e\u0439 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440. \u041a\u043b\u0438\u043a\u043d\u0435\u0442\u0435 \u0432\u044a\u0440\u0445\u0443 \u0431\u0443\u0442\u043e\u043d\u0430, \u0437\u0430 \u0434\u0430 \u0433\u043e \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0435."},"direction":{"message":"ltr"},"notitle":{"message":"(\u0411\u0435\u0437 \u0437\u0430\u0433\u043b\u0430\u0432\u0438\u0435)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 \u043c","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 \u0447","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 \u0434","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u041f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430 \u043d\u0430 \u043d\u044f\u043a\u043e\u043b\u043a\u043e \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0430"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u0442\u0435 \u0441\u0430 \u0437\u0430\u043f\u0430\u0437\u0435\u043d\u0438."},"status_saving":{"message":"\u0417\u0430\u043f\u0430\u0437\u0432\u0430 \u0441\u0435...."},"multicalendartooltip":{"message":"\u041c\u043e\u043b\u044f, \u043f\u043e\u0441\u0442\u0430\u0432\u0435\u0442\u0435 \u043e\u0442\u043c\u0435\u0442\u043a\u0430 \u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0447\u0435\u0442\u043e, \u0437\u0430 \u0434\u0430 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u0442\u0435 \u043f\u043e\u0434\u0434\u0440\u044a\u0436\u043a\u0430\u0442\u0430 \u043d\u0430 \u043d\u044f\u043a\u043e\u043b\u043a\u043e \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0430"},"imagetooltip":{"message":"Google \u041a\u0430\u043b\u0435\u043d\u0434\u0430\u0440"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ca/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ca/messages.json deleted file mode 100644 index b0ab0c6..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ca/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (de Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Comproveu r\u00e0pidament el temps que falta per a la propera reuni\u00f3 a qualsevol dels vostres calendaris. Feu clic al bot\u00f3 per anar-hi."},"direction":{"message":"ltr"},"notitle":{"message":"(Sense t\u00edtol)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 dies","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Compatibilitat amb m\u00faltiples calendaris"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"S'ha desat la configuraci\u00f3."},"status_saving":{"message":"S'est\u00e0 desant..."},"multicalendartooltip":{"message":"Activeu la casella per activar la compatibilitat amb m\u00faltiples calendaris"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/cs/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/cs/messages.json deleted file mode 100644 index 6e31a42..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/cs/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Kontrola Kalend\u00e1\u0159e Google (od spole\u010dnosti Google)"},"title":{"message":"Kontrola Kalend\u00e1\u0159e Google"},"description":{"message":"Umo\u017e\u0148uje rychle zobrazit \u010das, kter\u00fd zb\u00fdv\u00e1 do dal\u0161\u00ed sch\u016fzky napl\u00e1novan\u00e9 v kter\u00e9mkoli z va\u0161ich kalend\u00e1\u0159\u016f. Kliknut\u00edm na tla\u010d\u00edtko p\u0159ejdete do kalend\u00e1\u0159e."},"direction":{"message":"ltr"},"notitle":{"message":"(Bez n\u00e1zvu)"},"optionstitle":{"message":"Kontrola Kalend\u00e1\u0159e Google"},"minutes":{"message":"$1 min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Podpora n\u011bkolika kalend\u00e1\u0159\u016f"},"extensionname":{"message":"Kontrola Kalend\u00e1\u0159e Google"},"status_saved":{"message":"Nastaven\u00ed byla ulo\u017eena."},"status_saving":{"message":"Ukl\u00e1d\u00e1n\u00ed...."},"multicalendartooltip":{"message":"Za\u0161krtnut\u00edm pol\u00ed\u010dka pros\u00edm povolte podporu v\u00edce kalend\u00e1\u0159\u016f"},"imagetooltip":{"message":"Kalend\u00e1\u0159 Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/da/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/da/messages.json deleted file mode 100644 index 209b6d9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/da/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (fra Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Tjek hurtigt hvor lang tid der er til n\u00e6ste m\u00f8de i en af dine kalendre. Klik p\u00e5 knappen for at \u00e5bne din kalender."},"direction":{"message":"ltr"},"notitle":{"message":"(Ingen titel)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 t","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Support til flere kalendere"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Indstillingerne er gemt."},"status_saving":{"message":"Gemmer..."},"multicalendartooltip":{"message":"S\u00e6t kryds i feltet for at aktivere support til flere kalendere"},"imagetooltip":{"message":"Google Kalender"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/de/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/de/messages.json deleted file mode 100644 index 3892f397..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/de/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Werfen Sie schnell einen Blick auf die verbleibende Zeit bis zum n\u00e4chsten Termin in einem Ihrer Kalender. Klicken Sie zum \u00d6ffnen Ihres Kalenders auf die Schaltfl\u00e4che."},"direction":{"message":"ltr"},"notitle":{"message":"(Kein Titel)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 Min.","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 Std.","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 Tage","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Unterst\u00fctzung mehrerer Kalender"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Einstellungen gespeichert"},"status_saving":{"message":"Speichern...."},"multicalendartooltip":{"message":"Aktivieren Sie das Kontrollk\u00e4stchen, um die Unterst\u00fctzung mehrerer Kalender einzuschalten."},"imagetooltip":{"message":"Google Kalender"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/el/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/el/messages.json deleted file mode 100644 index 9cd461d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/el/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u03b1\u03c0\u03cc \u03c4\u03b7\u03bd Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u0394\u03b5\u03af\u03c4\u03b5 \u03b3\u03c1\u03ae\u03b3\u03bf\u03c1\u03b1 \u03c0\u03cc\u03c4\u03b5 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b7 \u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03b7 \u03c3\u03c5\u03bd\u03ac\u03bd\u03c4\u03b7\u03c3\u03ae \u03c3\u03b1\u03c2 \u03b1\u03c0\u03cc \u03bf\u03c0\u03bf\u03b9\u03bf\u03b4\u03ae\u03c0\u03bf\u03c4\u03b5 \u03b1\u03c0\u03cc \u03c4\u03b1 \u03b7\u03bc\u03b5\u03c1\u03bf\u03bb\u03cc\u03b3\u03b9\u03ac \u03c3\u03b1\u03c2. \u039a\u03ac\u03bd\u03c4\u03b5 \u03ba\u03bb\u03b9\u03ba \u03c3\u03c4\u03bf \u03ba\u03bf\u03c5\u03bc\u03c0\u03af \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03bc\u03b5\u03c4\u03b1\u03c6\u03b5\u03c1\u03b8\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03bf \u03b7\u03bc\u03b5\u03c1\u03bf\u03bb\u03cc\u03b3\u03b9\u03cc \u03c3\u03b1\u03c2."},"direction":{"message":"ltr"},"notitle":{"message":"(\u03a7\u03c9\u03c1\u03af\u03c2 \u03c4\u03af\u03c4\u03bb\u03bf)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1\u03bb","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1\u03c9","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1\u03b7","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u03a5\u03c0\u03bf\u03c3\u03c4\u03ae\u03c1\u03b9\u03be\u03b7 \u03c0\u03bf\u03bb\u03bb\u03ce\u03bd \u03b7\u03bc\u03b5\u03c1\u03bf\u03bb\u03bf\u03b3\u03af\u03c9\u03bd"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u039f\u03b9 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c4\u03b7\u03ba\u03b1\u03bd."},"status_saving":{"message":"\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7...."},"multicalendartooltip":{"message":"\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf \u03c0\u03bb\u03b1\u03af\u03c3\u03b9\u03bf \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03c5\u03c0\u03bf\u03c3\u03c4\u03ae\u03c1\u03b9\u03be\u03b7 \u03c0\u03bf\u03bb\u03bb\u03ce\u03bd \u03b7\u03bc\u03b5\u03c1\u03bf\u03bb\u03bf\u03b3\u03af\u03c9\u03bd"},"imagetooltip":{"message":"\u0397\u03bc\u03b5\u03c1\u03bf\u03bb\u03cc\u03b3\u03b9\u03bf Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/en/messages.json deleted file mode 100644 index 2b19e00..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/en/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (by Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Quickly see the time until your next meeting from any of your calendars. Click on the button to be taken to your calendar."},"direction":{"message":"ltr"},"notitle":{"message":"(No Title)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Multi Calendar Support"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Settings Saved."},"status_saving":{"message":"Saving...."},"multicalendartooltip":{"message":"Please check the box to enable multiple calendar support"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/en_GB/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/en_GB/messages.json deleted file mode 100644 index 87ef60e9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/en_GB/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (by Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Quickly see the time until your next meeting from any of your calendars. Click the button to be taken to your calendar."},"direction":{"message":"ltr"},"notitle":{"message":"(No Title)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Multi-Calendar Support"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Settings Saved."},"status_saving":{"message":"Saving...."},"multicalendartooltip":{"message":"Please tick the box to enable multiple calendar support"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/es/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/es/messages.json deleted file mode 100644 index 03d60100..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/es/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (de Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Consulta r\u00e1pidamente cu\u00e1nto tiempo falta para tu pr\u00f3xima reuni\u00f3n en cualquiera de tus calendarios. Haz clic en el bot\u00f3n para acceder al calendario."},"direction":{"message":"ltr"},"notitle":{"message":"(Sin t\u00edtulo)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Compatibilidad con varios calendarios"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Se ha guardado la configuraci\u00f3n."},"status_saving":{"message":"Guardando...."},"multicalendartooltip":{"message":"Selecciona la casilla para habilitar la compatibilidad con varios calendarios"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/es_419/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/es_419/messages.json deleted file mode 100644 index e7b2536a2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/es_419/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (de Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"F\u00edjate r\u00e1pidamente cu\u00e1nto tiempo falta para tu pr\u00f3xima reuni\u00f3n en alguno de tus calendarios. Haz clic en el bot\u00f3n para que te lleve hasta tu calendario."},"direction":{"message":"ltr"},"notitle":{"message":"(Sin t\u00edtulo)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1\u00a0m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1\u00a0h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Ayuda de Multi Calendar"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Configuraciones guardadas"},"status_saving":{"message":"Guardando...."},"multicalendartooltip":{"message":"Marca el casillero para habilitar la ayuda del calendario m\u00faltiple."},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/et/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/et/messages.json deleted file mode 100644 index 5828ccd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/et/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Vaadake kiiresti oma j\u00e4rgmise koosolekuni j\u00e4\u00e4nud aega \u00fcksk\u00f5ik millisest oma kalendrist. Kalendrisse minekuks kl\u00f5psake nupul."},"direction":{"message":"ltr"},"notitle":{"message":"(Pealkiri puudub)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 p\u00e4ev(a)","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Multi-Calendari tugi"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Seaded salvestatud."},"status_saving":{"message":"Salvestamine ..."},"multicalendartooltip":{"message":"Mitme kalendri toe lubamiseks m\u00e4rkige ruut"},"imagetooltip":{"message":"Google'i kalender"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fi/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fi/messages.json deleted file mode 100644 index ddc2088..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fi/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (Googlen tekem\u00e4)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"N\u00e4et nopeasti ajan seuraavaan tapaamiseesi mist\u00e4 tahansa kalenteristasi. Siirryt kalenteriin napsauttamalla painiketta."},"direction":{"message":"ltr"},"notitle":{"message":"(Ei nime\u00e4)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 t","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 pv","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Useiden kalentereiden tuki"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Asetukset tallennettu."},"status_saving":{"message":"Tallennetaan..."},"multicalendartooltip":{"message":"Ota useiden kalentereiden tuki k\u00e4ytt\u00f6\u00f6n valitsemalla valintaruutu"},"imagetooltip":{"message":"Google-kalenteri"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fil/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fil/messages.json deleted file mode 100644 index 16cdeba..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fil/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (mula sa Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Mabilisang tingnan ang oras hanggang sa iyong susunod na pagpupulong mula sa alinman sa iyong mga kalendaryo. Mag-click sa pindutan upang mapunta sa iyong kalendaryo."},"direction":{"message":"ltr"},"notitle":{"message":"(Walang Pamagat)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1o","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1a","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Suporta sa Maramihang Kalendaryo"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Na-save ang Mga Setting."},"status_saving":{"message":"Sine-save...."},"multicalendartooltip":{"message":"Pakilagyan ng check ang kahon upang paganahin ang suporta sa maramihang kalendaryo"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fr/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fr/messages.json deleted file mode 100644 index f8e413af..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/fr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google\u00a0Calendar Checker (par Google)"},"title":{"message":"Google\u00a0Calendar Checker"},"description":{"message":"V\u00e9rifiez rapidement dans vos agendas le temps qu'il vous reste avant votre prochaine r\u00e9union. Cliquez sur le bouton pour ouvrir l'agenda correspondant."},"direction":{"message":"ltr"},"notitle":{"message":"(Sans titre)"},"optionstitle":{"message":"Google\u00a0Calendar Checker"},"minutes":{"message":"$1\u00a0mn","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1\u00a0h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1\u00a0j","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Prise en charge multi-agendas"},"extensionname":{"message":"Google\u00a0Calendar Checker"},"status_saved":{"message":"Param\u00e8tres enregistr\u00e9s"},"status_saving":{"message":"Enregistrement...."},"multicalendartooltip":{"message":"Cocher la case pour activer la prise en charge multi-agendas"},"imagetooltip":{"message":"Google\u00a0Agenda"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/he/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/he/messages.json deleted file mode 100644 index 09f1654..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/he/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u05de\u05d0\u05ea Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u05e8\u05d0\u05d4 \u05d1\u05de\u05d4\u05d9\u05e8\u05d5\u05ea \u05db\u05de\u05d4 \u05d6\u05de\u05df \u05d9\u05e9 \u05dc\u05da \u05e2\u05d3 \u05d4\u05e4\u05d2\u05d9\u05e9\u05d4 \u05d4\u05d1\u05d0\u05d4 \u05e9\u05dc\u05da \u05de\u05db\u05dc \u05dc\u05d5\u05d7 \u05e9\u05e0\u05d4 \u05e9\u05dc\u05da. \u05dc\u05d7\u05e5 \u05e2\u05dc \u05d4\u05dc\u05d7\u05e6\u05df \u05db\u05d3\u05d9 \u05dc\u05e2\u05d1\u05d5\u05e8 \u05dc\u05dc\u05d5\u05d7 \u05d4\u05e9\u05e0\u05d4 \u05e9\u05dc\u05da."},"direction":{"message":"rtl"},"notitle":{"message":"(\u05dc\u05dc\u05d0 \u05db\u05d5\u05ea\u05e8\u05ea)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1\u05d3'","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1\u05e9'","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1\u05d9'","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u05ea\u05de\u05d9\u05db\u05d4 \u05d1\u05d9\u05d5\u05de\u05e0\u05d9\u05dd \u05de\u05e8\u05d5\u05d1\u05d9\u05dd"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u05d4\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05e0\u05e9\u05de\u05e8\u05d5."},"status_saving":{"message":"\u05e9\u05d5\u05de\u05e8...."},"multicalendartooltip":{"message":"\u05e1\u05de\u05df \u05d0\u05ea \u05d4\u05ea\u05d9\u05d1\u05d4 \u05db\u05d3\u05d9 \u05dc\u05d4\u05e4\u05d5\u05da \u05d0\u05ea \u05d4\u05ea\u05de\u05d9\u05db\u05d4 \u05d1\u05d9\u05d5\u05de\u05e0\u05d9\u05dd \u05de\u05e8\u05d5\u05d1\u05d9\u05dd \u05dc\u05e4\u05e2\u05d9\u05dc\u05d4"},"imagetooltip":{"message":"\u05d9\u05d5\u05de\u05df Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hi/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hi/messages.json deleted file mode 100644 index 2b19e00..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hi/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (by Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Quickly see the time until your next meeting from any of your calendars. Click on the button to be taken to your calendar."},"direction":{"message":"ltr"},"notitle":{"message":"(No Title)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Multi Calendar Support"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Settings Saved."},"status_saving":{"message":"Saving...."},"multicalendartooltip":{"message":"Please check the box to enable multiple calendar support"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hr/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hr/messages.json deleted file mode 100644 index f2ab5e5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (od Googlea)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Brzo pogledajte koliko imate vremena do idu\u0107eg sastanka iz svih svojih kalendara. Kliknite gumb koji \u0107e vas odvesti u va\u0161 kalendar."},"direction":{"message":"ltr"},"notitle":{"message":"(Nema naslova)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Podr\u0161ka za vi\u0161e kalendara"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Postavke su spremljene."},"status_saving":{"message":"Spremanje...."},"multicalendartooltip":{"message":"Uklju\u010dite potvrdni okvir za omogu\u0107avanje podr\u0161ke za vi\u0161e kalendara"},"imagetooltip":{"message":"Google Kalendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hu/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hu/messages.json deleted file mode 100644 index 6be01dc..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/hu/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (a Google-t\u00f3l)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Gyorsan megn\u00e9zheti b\u00e1rmelyik napt\u00e1r\u00e1ban, hogy mennyi ideje van m\u00e9g a k\u00f6vetkez\u0151 tal\u00e1lkoz\u00f3ig. Kattintson a gombra a napt\u00e1r megtekint\u00e9s\u00e9hez."},"direction":{"message":"ltr"},"notitle":{"message":"(Nincs c\u00edm)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1p","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1\u00f3","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1nap","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"T\u00f6bb napt\u00e1r t\u00e1mogat\u00e1sa"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Be\u00e1ll\u00edt\u00e1sok elmentve."},"status_saving":{"message":"Ment\u00e9s..."},"multicalendartooltip":{"message":"K\u00e9rj\u00fck, jel\u00f6lje be a jel\u00f6l\u0151n\u00e9gyzetet t\u00f6bb napt\u00e1r t\u00e1mogat\u00e1s\u00e1nak enged\u00e9lyez\u00e9s\u00e9hez"},"imagetooltip":{"message":"Google Napt\u00e1r"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/id/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/id/messages.json deleted file mode 100644 index 37056ba..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/id/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Pemeriksa Google Kalender (oleh Google)"},"title":{"message":"Pemeriksa Google Kalender"},"description":{"message":"Lihat waktu dengan cepat sampai pertemuan berikutnya dari kalender apa pun. Klik tombol untuk diarahkan ke kalender Anda."},"direction":{"message":"ltr"},"notitle":{"message":"(Tanpa Judul)"},"optionstitle":{"message":"Pemeriksa Google Kalender"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1j","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Dukungan Multi-Kalender"},"extensionname":{"message":"Pemeriksa Google Kalender"},"status_saved":{"message":"Setelan Disimpan."},"status_saving":{"message":"Menyimpan..."},"multicalendartooltip":{"message":"Harap periksa kotak untuk mengaktifkan dukungan multi-kalender"},"imagetooltip":{"message":"Google Kalender"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/it/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/it/messages.json deleted file mode 100644 index 90e8daf..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/it/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (di Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Usa uno dei tuoi calendari per controllare rapidamente quanto manca alla prossima riunione. Fai clic sul pulsante per accedere al calendario."},"direction":{"message":"ltr"},"notitle":{"message":"(Nessun titolo)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 g","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Supporto di pi\u00f9 calendari"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Impostazioni salvate."},"status_saving":{"message":"Salvataggio in corso..."},"multicalendartooltip":{"message":"Seleziona la casella per attivare il supporto di pi\u00f9 calendari"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ja/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ja/messages.json deleted file mode 100644 index 30cdf0bbb..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ja/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker\uff08by Google\uff09"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u3069\u306e\u30ab\u30ec\u30f3\u30c0\u30fc\u304b\u3089\u3067\u3082\u6b21\u306e\u4f1a\u8b70\u307e\u3067\u306e\u6642\u9593\u3092\u3059\u3070\u3084\u304f\u30c1\u30a7\u30c3\u30af\u3002\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u3068\u30ab\u30ec\u30f3\u30c0\u30fc\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059\u3002"},"direction":{"message":"ltr"},"notitle":{"message":"\uff08\u30bf\u30a4\u30c8\u30eb\u306a\u3057\uff09"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u8907\u6570\u306e\u30ab\u30ec\u30f3\u30c0\u30fc\u306b\u5bfe\u5fdc"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u8a2d\u5b9a\u304c\u4fdd\u5b58\u3055\u308c\u307e\u3057\u305f\u3002"},"status_saving":{"message":"\u4fdd\u5b58\u3057\u3066\u3044\u307e\u3059..."},"multicalendartooltip":{"message":"\u8907\u6570\u306e\u30ab\u30ec\u30f3\u30c0\u30fc\u3092\u4f7f\u7528\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\u306b\u306f\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u3092\u30aa\u30f3\u306b\u3057\u3066\u304f\u3060\u3055\u3044"},"imagetooltip":{"message":"Google \u30ab\u30ec\u30f3\u30c0\u30fc"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ko/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ko/messages.json deleted file mode 100644 index 4e381a8..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ko/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google \uce98\ub9b0\ub354 \uccb4\ud06c \ub3c4\uc6b0\ubbf8(Google \uc81c\uacf5)"},"title":{"message":"Google \uce98\ub9b0\ub354 \uccb4\ud06c \ub3c4\uc6b0\ubbf8"},"description":{"message":"\uce98\ub9b0\ub354 \uc5b4\ub514\uc5d0\uc11c\ub098 \ub2e4\uc74c \ubaa8\uc784\uae4c\uc9c0 \ub0a8\uc740 \uc2dc\uac04\uc744 \uc2e0\uc18d\ud558\uac8c \uc0b4\ud3b4\ubcfc \uc218 \uc788\uc2b5\ub2c8\ub2e4. \uce98\ub9b0\ub354\ub85c \uc774\ub3d9\ud558\ub824\uba74 \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc138\uc694."},"direction":{"message":"ltr"},"notitle":{"message":"(\uc81c\ubaa9 \uc5c6\uc74c)"},"optionstitle":{"message":"Google \uce98\ub9b0\ub354 \uccb4\ud06c \ub3c4\uc6b0\ubbf8"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\uc5ec\ub7ec \uce98\ub9b0\ub354 \uc9c0\uc6d0"},"extensionname":{"message":"Google \uce98\ub9b0\ub354 \uccb4\ud06c \ub3c4\uc6b0\ubbf8"},"status_saved":{"message":"\uc124\uc815\uc744 \uc800\uc7a5\ud588\uc2b5\ub2c8\ub2e4."},"status_saving":{"message":"\uc800\uc7a5 \uc911..."},"multicalendartooltip":{"message":"\uc5ec\ub7ec \uce98\ub9b0\ub354 \uc9c0\uc6d0\uc744 \uc0ac\uc6a9\ud558\ub3c4\ub85d \uc124\uc815\ud558\ub824\uba74 \ud655\uc778\ub780\uc744 \uc120\ud0dd\ud558\uc138\uc694."},"imagetooltip":{"message":"Google \uce98\ub9b0\ub354"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/lt/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/lt/messages.json deleted file mode 100644 index aac503f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/lt/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Bet kuriame i\u0161 savo kalendori\u0173 greitai \u017ei\u016br\u0117kite, kiek laiko liko iki kito susitikimo. Jei norite patekti \u012f kalendori\u0173, spustel\u0117kite mygtuk\u0105."},"direction":{"message":"ltr"},"notitle":{"message":"(N\u0117ra pavadinimo)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 min.","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 val.","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d.","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Keli\u0173 kalendori\u0173 palaikymas"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Nustatymai i\u0161saugoti."},"status_saving":{"message":"I\u0161saugoma..."},"multicalendartooltip":{"message":"Kad \u012fgalintum\u0117te keli\u0173 kalendori\u0173 palaikym\u0105, pa\u017eym\u0117kite laukel\u012f"},"imagetooltip":{"message":"\u201eGoogle\u201c kalendorius"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/lv/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/lv/messages.json deleted file mode 100644 index be33183..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/lv/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (nodro\u0161ina Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Varat \u0101tri skat\u012bt, cik daudz laika atlicis l\u012bdz n\u0101kamajai sapulcei, izmantojot jebkuru no saviem kalend\u0101riem. Lai atv\u0113rtu kalend\u0101ru, nospiediet pogu."},"direction":{"message":"ltr"},"notitle":{"message":"(Bez nosaukuma)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1\u00a0min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1\u00a0h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1\u00a0d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Vair\u0101ku kalend\u0101ru atbalsts"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Iestat\u012bjumi ir saglab\u0101ti."},"status_saving":{"message":"Notiek saglab\u0101\u0161ana..."},"multicalendartooltip":{"message":"L\u016bdzu, atz\u012bm\u0113jiet lodzi\u0146u, lai iesp\u0113jotu vair\u0101ku kalend\u0101ru atbalstu."},"imagetooltip":{"message":"Google kalend\u0101rs"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/nb/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/nb/messages.json deleted file mode 100644 index 666df6e5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/nb/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (laget av Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Finn ut raskt hvor lenge det er til neste m\u00f8te fra alle kalendrene dine. Klikk p\u00e5 knappen for \u00e5 g\u00e5 videre til kalenderen."},"direction":{"message":"ltr"},"notitle":{"message":"(Ingen tittel)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 t","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"St\u00f8tte for flere kalendere"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Innstillinger lagret."},"status_saving":{"message":"Lagrer \u2026"},"multicalendartooltip":{"message":"Merk av i ruten for \u00e5 aktivere st\u00f8tte for flere kalendere"},"imagetooltip":{"message":"Google Kalender"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/nl/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/nl/messages.json deleted file mode 100644 index 9ffa222..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/nl/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (van Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Snel in al uw agenda's bekijken hoe lang het nog duurt voordat uw volgende vergadering begint. Klik op de knop om naar uw agenda te gaan."},"direction":{"message":"ltr"},"notitle":{"message":"(Naamloos)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 u","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Ondersteuning voor meerdere agenda's"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Instellingen zijn opgeslagen."},"status_saving":{"message":"Opslaan..."},"multicalendartooltip":{"message":"Vink het selectievakje aan om de ondersteuning voor meerdere agenda's in te schakelen"},"imagetooltip":{"message":"Google Agenda"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pl/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pl/messages.json deleted file mode 100644 index 2a3d471..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pl/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (by Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Szybko sprawd\u017a w dowolnym kalendarzu, ile masz czasu do nast\u0119pnego zebrania. Kliknij przycisk, aby przej\u015b\u0107 do kalendarza."},"direction":{"message":"ltr"},"notitle":{"message":"(Bez tytu\u0142u)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1g","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Obs\u0142uga wielu kalendarzy"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Zapisano ustawienia."},"status_saving":{"message":"Zapisywanie..."},"multicalendartooltip":{"message":"Zaznacz pole, aby w\u0142\u0105czy\u0107 obs\u0142ug\u0119 wielu kalendarzy"},"imagetooltip":{"message":"Kalendarz Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pt_BR/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pt_BR/messages.json deleted file mode 100644 index 3a79f1dd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pt_BR/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (do Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Veja rapidamente quanto tempo voc\u00ea tem at\u00e9 seu pr\u00f3ximo compromisso. Clique no bot\u00e3o para abrir sua agenda."},"direction":{"message":"ltr"},"notitle":{"message":"(Sem t\u00edtulo)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Suporte para v\u00e1rias agendas"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Configura\u00e7\u00f5es salvas."},"status_saving":{"message":"Salvando..."},"multicalendartooltip":{"message":"Marque a caixa para ativar o suporte para v\u00e1rias agendas"},"imagetooltip":{"message":"Google Agenda"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pt_PT/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pt_PT/messages.json deleted file mode 100644 index 53f249fa..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/pt_PT/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (do Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Veja rapidamente quanto tempo falta para a sua pr\u00f3xima reuni\u00e3o a partir de qualquer um dos seus calend\u00e1rios. Clique no bot\u00e3o para aceder ao calend\u00e1rio."},"direction":{"message":"ltr"},"notitle":{"message":"(Sem t\u00edtulo)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Suporte para v\u00e1rios calend\u00e1rios"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Defini\u00e7\u00f5es guardadas."},"status_saving":{"message":"A guardar..."},"multicalendartooltip":{"message":"Marque a caixa para permitir o suporte de v\u00e1rios calend\u00e1rios."},"imagetooltip":{"message":"Calend\u00e1rio Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ro/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ro/messages.json deleted file mode 100644 index 3540609..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ro/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (de la Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Vede\u0163i rapid timpul p\u00e2n\u0103 la urm\u0103toarea \u00eent\u00e2lnire, din oricare dintre calendarele dvs. Face\u0163i clic pe buton pentru a accesa calendarul."},"direction":{"message":"ltr"},"notitle":{"message":"(F\u0103r\u0103 titlu)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 z","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Asisten\u0163\u0103 pentru mai multe calendare"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Set\u0103rile au fost salvate."},"status_saving":{"message":"Se salveaz\u0103..."},"multicalendartooltip":{"message":"Bifa\u0163i caseta pentru a activa asisten\u0163a pentru mai multe calendare"},"imagetooltip":{"message":"Google Calendar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ru/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ru/messages.json deleted file mode 100644 index 34363260..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/ru/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043e \u0432 Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u0432\u0440\u0435\u043c\u044f \u0434\u043e \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0433\u043e \u043c\u0435\u0440\u043e\u043f\u0440\u0438\u044f\u0442\u0438\u044f. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0435\u0439. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044c."},"direction":{"message":"ltr"},"notitle":{"message":"(\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1\u043c.","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1\u0447.","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1\u0434.","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u041a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0435\u0439"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b."},"status_saving":{"message":"\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435...."},"multicalendartooltip":{"message":"\u041d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0444\u043b\u0430\u0436\u043e\u043a, \u0447\u0442\u043e\u0431\u044b \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u041a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0435\u0439"},"imagetooltip":{"message":"\u041a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044c Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sk/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sk/messages.json deleted file mode 100644 index 65257bf..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sk/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Kontrola Kalend\u00e1ra Google (od spolo\u010dnosti Google)"},"title":{"message":"Kontrola Kalend\u00e1ra Google"},"description":{"message":"V \u013eubovo\u013enom z va\u0161ich kalend\u00e1rov si v r\u00fdchlosti si zobrazte, ko\u013eko \u010dasu m\u00e1te do \u010fal\u0161ej sch\u00f4dzky. Kliknut\u00edm na tla\u010didlo prejdete do svojho kalend\u00e1ra."},"direction":{"message":"ltr"},"notitle":{"message":"(Bez n\u00e1zvu)"},"optionstitle":{"message":"Kontrola Kalend\u00e1ra Google"},"minutes":{"message":"$1 min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Podpora viacer\u00fdch Kalend\u00e1rov"},"extensionname":{"message":"Kontrola Kalend\u00e1ra Google"},"status_saved":{"message":"Nastavenia boli ulo\u017een\u00e9."},"status_saving":{"message":"Prebieha ukladanie...."},"multicalendartooltip":{"message":"Ak chcete povoli\u0165 podporu viacer\u00fdch kalend\u00e1rov, za\u010diarknite toto pol\u00ed\u010dko"},"imagetooltip":{"message":"Kalend\u00e1r Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sl/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sl/messages.json deleted file mode 100644 index 09a2113..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sl/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Hitro preverite, koliko je \u0161e do naslednjega sestanka v katerem koli od va\u0161ih koledarjev. Kliknite gumb, da odprete koledar."},"direction":{"message":"ltr"},"notitle":{"message":"(Brez naslova)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Podpora za ve\u010d koledarjev"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Nastavitve shranjene."},"status_saving":{"message":"Shranjevanje ..."},"multicalendartooltip":{"message":"Potrdite polje, da omogo\u010dite podporo za ve\u010d koledarjev."},"imagetooltip":{"message":"Google Koledar"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sr/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sr/messages.json deleted file mode 100644 index d55c41b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u043e\u0434 Google-\u0430)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u0411\u0440\u0437\u043e \u043f\u043e\u0433\u043b\u0435\u0434\u0430\u0458\u0442\u0435 \u043a\u043e\u043b\u0438\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0430 \u0438\u043c\u0430\u0442\u0435 \u0434\u043e \u0441\u043b\u0435\u0434\u0435\u045b\u0435\u0433 \u0441\u0430\u0441\u0442\u0430\u043d\u043a\u0430 \u0443 \u0431\u0438\u043b\u043e \u043a\u043e\u043c \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0443. \u041a\u043b\u0438\u043a\u043d\u0438\u0442\u0435 \u043d\u0430 \u0434\u0443\u0433\u043c\u0435 \u0434\u0430 \u0431\u0438\u0441\u0442\u0435 \u043e\u0442\u0432\u043e\u0440\u0438\u043b\u0438 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440."},"direction":{"message":"ltr"},"notitle":{"message":"(\u0411\u0435\u0437 \u043d\u0430\u0441\u043b\u043e\u0432\u0430)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 \u043c\u0438\u043d","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 \u0441","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 \u0434","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u041f\u043e\u0434\u0440\u0448\u043a\u0430 \u0437\u0430 \u0432\u0438\u0448\u0435 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0430"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u041f\u043e\u0434\u0435\u0448\u0430\u0432\u0430\u045a\u0430 \u0441\u0443 \u0441\u0430\u0447\u0443\u0432\u0430\u043d\u0430."},"status_saving":{"message":"\u0427\u0443\u0432\u0430\u045a\u0435...."},"multicalendartooltip":{"message":"\u041f\u043e\u0442\u0432\u0440\u0434\u0438\u0442\u0435 \u0438\u0437\u0431\u043e\u0440 \u0443 \u043f\u043e\u0459\u0443 \u0437\u0430 \u043f\u043e\u0442\u0432\u0440\u0434\u0443 \u0434\u0430 \u0431\u0438\u0441\u0442\u0435 \u043e\u043c\u043e\u0433\u0443\u045b\u0438\u043b\u0438 \u043f\u043e\u0434\u0440\u0448\u043a\u0443 \u0437\u0430 \u0432\u0438\u0448\u0435 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0430"},"imagetooltip":{"message":"Google \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sv/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sv/messages.json deleted file mode 100644 index edb0193..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/sv/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (fr\u00e5n Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Se snabbt i dina kalendrar hur l\u00e4nge det \u00e4r till n\u00e4sta m\u00f6te. Klicka p\u00e5 knappen s\u00e5 kommer du till kalendern."},"direction":{"message":"ltr"},"notitle":{"message":"(Namnl\u00f6s)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1min","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1tim","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Support f\u00f6r flera kalendrar"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Inst\u00e4llningarna har sparats."},"status_saving":{"message":"Sparar..."},"multicalendartooltip":{"message":"Aktivera support f\u00f6r flera kalendrar genom att markera rutan"},"imagetooltip":{"message":"Google Kalender"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/th/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/th/messages.json deleted file mode 100644 index c9680f1c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/th/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u0e42\u0e14\u0e22 Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u0e14\u0e39\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e21\u0e35\u0e01\u0e48\u0e2d\u0e19\u0e16\u0e36\u0e07\u0e01\u0e32\u0e23\u0e1b\u0e23\u0e30\u0e0a\u0e38\u0e21\u0e04\u0e23\u0e31\u0e49\u0e07\u0e15\u0e48\u0e2d\u0e44\u0e1b\u0e44\u0e14\u0e49\u0e08\u0e32\u0e01\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e43\u0e14\u0e46 \u0e01\u0e47\u0e44\u0e14\u0e49\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \u0e43\u0e2b\u0e49\u0e04\u0e25\u0e34\u0e01\u0e17\u0e35\u0e48\u0e1b\u0e38\u0e48\u0e21\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e44\u0e1b\u0e17\u0e35\u0e48\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13"},"direction":{"message":"ltr"},"notitle":{"message":"(\u0e44\u0e21\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u0e01\u0e32\u0e23\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e2b\u0e25\u0e32\u0e22\u0e23\u0e30\u0e1a\u0e1a"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e01\u0e32\u0e23\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e41\u0e25\u0e49\u0e27"},"status_saving":{"message":"\u0e01\u0e33\u0e25\u0e31\u0e07\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01...."},"multicalendartooltip":{"message":"\u0e42\u0e1b\u0e23\u0e14\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e0a\u0e48\u0e2d\u0e07\u0e17\u0e33\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22 \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e1b\u0e34\u0e14\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e01\u0e32\u0e23\u0e2a\u0e19\u0e31\u0e1a\u0e2a\u0e19\u0e38\u0e19\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e2b\u0e25\u0e32\u0e22\u0e23\u0e30\u0e1a\u0e1a"},"imagetooltip":{"message":"Google \u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/tr/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/tr/messages.json deleted file mode 100644 index a54371eb..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/tr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (Google'dan)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Takvimlerinizden herhangi birine bakarak bir sonraki toplant\u0131n\u0131za ne kadar zaman kald\u0131\u011f\u0131n\u0131 hemen g\u00f6r\u00fcn. Takviminizi a\u00e7mak i\u00e7in d\u00fc\u011fmeyi t\u0131klay\u0131n."},"direction":{"message":"ltr"},"notitle":{"message":"(Ba\u015fl\u0131ks\u0131z)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1s","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1g","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"Birden Fazla Takvim Deste\u011fi"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"Ayarlar Kaydedildi."},"status_saving":{"message":"Kaydediliyor..."},"multicalendartooltip":{"message":"Birden fazla takvim deste\u011fini etkinle\u015ftirmek i\u00e7in l\u00fctfen kutuyu i\u015faretleyin"},"imagetooltip":{"message":"Google Takvim"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/uk/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/uk/messages.json deleted file mode 100644 index 21c7514..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/uk/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u0432\u0456\u0434 Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u0428\u0432\u0438\u0434\u043a\u043e \u043f\u0435\u0440\u0435\u0433\u043b\u044f\u0434\u0430\u0439\u0442\u0435 \u0441\u0432\u043e\u0457 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0456, \u0449\u043e\u0431 \u0434\u0456\u0437\u043d\u0430\u0442\u0438\u0441\u044f, \u0441\u043a\u0456\u043b\u044c\u043a\u0438 \u0447\u0430\u0441\u0443 \u0437\u0430\u043b\u0438\u0448\u0438\u043b\u043e\u0441\u044f \u0434\u043e \u043d\u0430\u0441\u0442\u0443\u043f\u043d\u043e\u0457 \u0437\u0443\u0441\u0442\u0440\u0456\u0447\u0456. \u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c \u0446\u044e \u043a\u043d\u043e\u043f\u043a\u0443, \u0449\u043e\u0431 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0434\u043e \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044f."},"direction":{"message":"ltr"},"notitle":{"message":"(\u0411\u0435\u0437 \u043d\u0430\u0437\u0432\u0438)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1 \u0445\u0432.","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1 \u0433\u043e\u0434.","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1 \u0434\u043d.","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u041f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0430 \u0434\u0435\u043a\u0456\u043b\u044c\u043a\u043e\u0445 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0456\u0432"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043e."},"status_saving":{"message":"\u0417\u0431\u0435\u0440\u0456\u0433\u0430\u043d\u043d\u044f...."},"multicalendartooltip":{"message":"\u041f\u043e\u0441\u0442\u0430\u0432\u0442\u0435 \u043f\u0440\u0430\u043f\u043e\u0440\u0435\u0446\u044c, \u0449\u043e\u0431 \u0443\u0432\u0456\u043c\u043a\u043d\u0443\u0442\u0438 \u043f\u0456\u0434\u0442\u0440\u0438\u043c\u043a\u0443 \u0434\u0435\u043a\u0456\u043b\u044c\u043a\u043e\u0445 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u0456\u0432"},"imagetooltip":{"message":"\u041a\u0430\u043b\u0435\u043d\u0434\u0430\u0440 Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/vi/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/vi/messages.json deleted file mode 100644 index a54d48b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/vi/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (c\u1ee7a Google)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"Xem nhanh th\u1eddi gian tr\u01b0\u1edbc khi \u0111\u1ebfn cu\u1ed9c h\u1ecdp ti\u1ebfp theo t\u1eeb b\u1ea5t k\u1ef3 l\u1ecbch n\u00e0o c\u1ee7a b\u1ea1n. H\u00e3y nh\u1ea5p v\u00e0o n\u00fat \u0111\u1ec3 \u0111\u01b0\u1ee3c \u0111\u01b0a \u0111\u1ebfn l\u1ecbch c\u1ee7a b\u1ea1n."},"direction":{"message":"ltr"},"notitle":{"message":"(Kh\u00f4ng c\u00f3 ti\u00eau \u0111\u1ec1)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"H\u1ed7 tr\u1ee3 nhi\u1ec1u l\u1ecbch"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u0110\u00e3 l\u01b0u c\u00e0i \u0111\u1eb7t."},"status_saving":{"message":"\u0110ang l\u01b0u...."},"multicalendartooltip":{"message":"Vui l\u00f2ng ch\u1ecdn h\u1ed9p n\u00e0y \u0111\u1ec3 b\u1eadt t\u00ednh n\u0103ng h\u1ed7 tr\u1ee3 nhi\u1ec1u l\u1ecbch"},"imagetooltip":{"message":"L\u1ecbch Google"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/zh_CN/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/zh_CN/messages.json deleted file mode 100644 index 7c2ecea..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/zh_CN/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker\uff08\u7531 Google \u63d0\u4f9b\uff09"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u5feb\u901f\u67e5\u770b\u79bb\u60a8\u7684\u4efb\u610f\u65e5\u5386\u4e2d\u4e0b\u4e00\u6b21\u4f1a\u8bae\u8fd8\u6709\u591a\u957f\u65f6\u95f4\u3002\u60a8\u53ea\u9700\u70b9\u51fb\u8be5\u6309\u94ae\u5373\u53ef\u8fdb\u5165\u81ea\u5df1\u7684\u65e5\u5386\u3002"},"direction":{"message":"ltr"},"notitle":{"message":"\uff08\u65e0\u6807\u9898\uff09"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u591a\u65e5\u5386\u652f\u6301"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u8bbe\u7f6e\u5df2\u4fdd\u5b58\u3002"},"status_saving":{"message":"\u6b63\u5728\u4fdd\u5b58..."},"multicalendartooltip":{"message":"\u8bf7\u9009\u4e2d\u6b64\u6846\u4ee5\u542f\u7528\u591a\u65e5\u5386\u652f\u6301"},"imagetooltip":{"message":"Google \u65e5\u5386"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/zh_TW/messages.json b/chrome/common/extensions/docs/examples/extensions/calendar/_locales/zh_TW/messages.json deleted file mode 100644 index 5c99aba..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/_locales/zh_TW/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"name":{"message":"Google Calendar Checker (\u7531 Google \u63d0\u4f9b)"},"title":{"message":"Google Calendar Checker"},"description":{"message":"\u5f9e\u4efb\u4f55\u65e5\u66c6\u7686\u53ef\u8fc5\u901f\u67e5\u770b\u8ddd\u96e2\u4e0b\u6b21\u6703\u8b70\u9084\u5269\u4e0b\u591a\u5c11\u6642\u9593\u3002\u6309\u4e00\u4e0b\u6309\u9215\u5373\u53ef\u524d\u5f80\u60a8\u7684\u65e5\u66c6\u3002"},"direction":{"message":"ltr"},"notitle":{"message":"(\u7121\u6a19\u984c)"},"optionstitle":{"message":"Google Calendar Checker"},"minutes":{"message":"$1m","placeholders":{"1":{"content":"$1"}}},"hours":{"message":"$1h","placeholders":{"1":{"content":"$1"}}},"days":{"message":"$1d","placeholders":{"1":{"content":"$1"}}},"multicalendartext":{"message":"\u591a\u91cd\u65e5\u66c6\u652f\u63f4"},"extensionname":{"message":"Google Calendar Checker"},"status_saved":{"message":"\u8a2d\u5b9a\u5df2\u5132\u5b58\u3002"},"status_saving":{"message":"\u5132\u5b58\u4e2d...."},"multicalendartooltip":{"message":"\u8acb\u52fe\u9078\u6b64\u65b9\u584a\uff0c\u4ee5\u555f\u7528\u591a\u91cd\u65e5\u66c6\u652f\u63f4\u529f\u80fd"},"imagetooltip":{"message":"Google \u65e5\u66c6"}}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-128.png b/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-128.png deleted file mode 100644 index 78cbdcde..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-16.png b/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-16.png deleted file mode 100644 index 922ae44d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-19.png b/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-19.png deleted file mode 100644 index 0100daf..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-38.png b/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-38.png deleted file mode 100644 index 5f6e785..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-38.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-48.png b/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-48.png deleted file mode 100644 index 636ba83..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/images/icon-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/javascript/background.js b/chrome/common/extensions/docs/examples/extensions/calendar/javascript/background.js deleted file mode 100644 index fe466a4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/javascript/background.js +++ /dev/null
@@ -1,41 +0,0 @@ -/** - * Copyright (c) 2013 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. - */ - -var warningId = 'notification.warning'; - -function hideWarning(done) { - chrome.notifications.clear(warningId, function() { - if (done) done(); - }); -} - -function showWarning() { - hideWarning(function() { - chrome.notifications.create(warningId, { - iconUrl: chrome.runtime.getURL('images/icon-48.png'), - title: 'Removal required', - type: 'basic', - message: chrome.i18n.getMessage('name') + ' is obsolete ' + - 'and must be removed. A replacement Extension ' + - 'is available.', - buttons: [{ title: 'Learn More' }], - priority: 2, - }, function() {}); - }); -} - -function openWarningPage() { - chrome.tabs.create({ - url: 'chrome://extensions?options=' + chrome.runtime.id - }); -} - -chrome.browserAction.setBadgeBackgroundColor({ color: '#FF0000' }); -chrome.browserAction.setBadgeText({ text: '!' }); -chrome.browserAction.onClicked.addListener(openWarningPage); -chrome.notifications.onClicked.addListener(openWarningPage); -chrome.notifications.onButtonClicked.addListener(openWarningPage); -chrome.runtime.onInstalled.addListener(showWarning);
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/javascript/options.js b/chrome/common/extensions/docs/examples/extensions/calendar/javascript/options.js deleted file mode 100644 index a524b89..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/javascript/options.js +++ /dev/null
@@ -1,17 +0,0 @@ -/** - * Copyright (c) 2013 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. - */ - -var $ = document.getElementById.bind(document); - -var url = 'https://chrome.google.com/webstore/detail/' + - 'google-calendar-by-google/gmbgaklkmjakoegficnlkhebmhkjfich'; - -$('name').textContent = chrome.i18n.getMessage('name'); -$('link').href = url; -$('remove').onclick = function() { - chrome.management.uninstallSelf({showConfirmDialog: true}); - window.close(); -};
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/manifest.json b/chrome/common/extensions/docs/examples/extensions/calendar/manifest.json deleted file mode 100644 index 51ee7441..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/manifest.json +++ /dev/null
@@ -1,31 +0,0 @@ -{ - "name": "__MSG_name__", - "description": "__MSG_description__", - "manifest_version": 2, - "default_locale":"en", - "options_page": "views/options.html", - "options_ui": { - "page": "views/options.html", - "chrome_style": true - }, - "version": "2.0.0", - "background": { - "scripts": ["javascript/background.js"], - "persistent": false - }, - "permissions": [ - "notifications" - ], - "browser_action": { - "default_icon": { - "19": "images/icon-19.png", - "38": "images/icon-38.png" - }, - "default_title": "__MSG_title__" - }, - "icons": { - "128": "images/icon-128.png", - "48": "images/icon-48.png", - "16":"images/icon-16.png" - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/calendar/views/options.html b/chrome/common/extensions/docs/examples/extensions/calendar/views/options.html deleted file mode 100644 index 92c8d52..0000000 --- a/chrome/common/extensions/docs/examples/extensions/calendar/views/options.html +++ /dev/null
@@ -1,27 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2012 The Chromium Authors. All rights reserved. Use of this - * source code is governed by a BSD-style license that can be found in the - * LICENSE file. ---> -<html> -<body> - -<p> -<strong><span id="name"></span> is now obsolete and must be removed, as it -relies on an API which will be turned off imminently</strong>. -<a href="https://developers.google.com/google-apps/calendar/v2/developers_guide_protocol">Learn more</a>. -</p> - -<p> -Instead, we recommend the more powerful <a id="link">Google Calendar (by -Google)</a> Extension. -</p> - -<p> -<button id="remove">Remove from Chrome...</button> -</p> - -<script src="../javascript/options.js"></script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/catblock/background.js b/chrome/common/extensions/docs/examples/extensions/catblock/background.js deleted file mode 100644 index 7fdb601..0000000 --- a/chrome/common/extensions/docs/examples/extensions/catblock/background.js +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Simple extension to replace lolcat images from -// http://icanhascheezburger.com/ with loldog images instead. - -chrome.webRequest.onBeforeRequest.addListener( - function(info) { - console.log("Cat intercepted: " + info.url); - // Redirect the lolcal request to a random loldog URL. - var i = Math.round(Math.random() * loldogs.length); - return {redirectUrl: loldogs[i]}; - }, - // filters - { - urls: [ - "https://i.chzbgr.com/*" - ], - types: ["image"] - }, - // extraInfoSpec - ["blocking"]);
diff --git a/chrome/common/extensions/docs/examples/extensions/catblock/loldogs.js b/chrome/common/extensions/docs/examples/extensions/catblock/loldogs.js deleted file mode 100644 index a8013b1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/catblock/loldogs.js +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var loldogs = [ -"http://ihasahotdog.files.wordpress.com/2011/08/funny-dog-pictures-yoo-bin-warndid.jpg", -"http://ihasahotdog.files.wordpress.com/2011/08/funny-dog-pictures-it-juzz-liek-ezploded-or-sumfin.jpg", -"http://ihasahotdog.files.wordpress.com/2011/08/funny-dog-pictures-cool-story-bro-got-anymore-bacon.jpg", -"http://ihasahotdog.files.wordpress.com/2011/08/funny-dog-pictures-ohaii-iz-n-ur-livin-room-defyin-ur-gravaties.jpg", -"http://ihasahotdog.files.wordpress.com/2011/08/cue-puppy-pictures-spike-is-not-sleeping-on-duty-hes-lulling-you-into-a-false-sense-of-security.jpg", -"http://ihasahotdog.files.wordpress.com/2011/08/funny-dog-pictures-pens-too-mainstream.jpg", -"http://ihasahotdog.files.wordpress.com/2011/08/funny-dog-pictures-tyrannodoggus-rex.jpg", -"http://ihasahotdog.files.wordpress.com/2011/08/funny-dog-pictures-sniper-dog-in-position.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-i-see-wat-yur-doin-must-put-it-on-internet.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/cute-puppy-pictures-fresh-squeed.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-that-sir-is-not-my-issue.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-trippin.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-oh-gurl-diz-iz-my-jam.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-get-off-teh-lawn-we-haz-no-komment-on-teh-allejed-mailman-insident.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-sowwy-i-kin-still-feel-da-pea.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-hang-upz-ai-haz-dem.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-i-haz-a-happy-cuz-im-going-to-mai-fer-ebber-home.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-the-guitar-its-a-les-paw.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-if-you-need-me-ill-just-be-watching-the-game.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-camouflage-complete.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/cute-puppy-pictures-its-okay-i-tuck-myself-in.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-transformers-more-than-meets-the-eye.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/cute-puppy-pictures-a-long-night-of-pwnage.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/raised-in-the-woods-sos-he-knew-every-tree-killed-him-a-bear-when-he-was-only-three.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/this-be-ten-times-betteh-den-laska.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-wut-did-u-say-mai-heering-iz-spotty.jpg", -"http://ihasahotdog.files.wordpress.com/2011/07/funny-dog-pictures-albark-einstein-discusses-relativity.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-goggie-ob-teh-week-i-love-you.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-oh-lord-take-me-now-i-broke-my-chew-toy.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-i-has-a-safe.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-corgi-choir.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-goggie-ob-teh-week-snaaaaacks-i-love-snaaaaacks.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-porky-pug-bath-club-est.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-so-wuts-so-tuff-abowt.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-taek-teh-pitcher-awreddy.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-hip-um-pot-o-mush-impresshun-iz-good.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-if-it-touchez-floor-itz-mine-no-secund-rule.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-pug-life.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-readz-us-a-storee.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-green-light-red-light-green-light.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/648800e7-f305-43e8-83ed-06a5325923c8.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/cute-puppy-pictures-why-ai-always-gets-picked-last.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/cute-puppy-pictures-corgagram.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/cute-puppy-pictures-shes-got-a-chicken-to-ride-and-she-dont-care.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-caring-is-for-the-birds.jpg", -"http://ihasahotdog.files.wordpress.com/2011/06/funny-dog-pictures-goggie-ob-teh-week-pudge-is-teh-boss.jpg", -];
diff --git a/chrome/common/extensions/docs/examples/extensions/catblock/manifest.json b/chrome/common/extensions/docs/examples/extensions/catblock/manifest.json deleted file mode 100644 index e775432..0000000 --- a/chrome/common/extensions/docs/examples/extensions/catblock/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "CatBlock", - "version": "1.0", - "description": "I can't has cheezburger!", - "permissions": ["webRequest", "webRequestBlocking", - "https://i.chzbgr.com/*"], - "background": { - "scripts": ["loldogs.js", "background.js"] - }, - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/catifier/event_page.js b/chrome/common/extensions/docs/examples/extensions/catifier/event_page.js deleted file mode 100644 index 2618fdc..0000000 --- a/chrome/common/extensions/docs/examples/extensions/catifier/event_page.js +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Sample extension to replace all JPEG images (but no PNG/GIF/... images) with -// lolcat images from http://icanhascheezburger.com/ - except for images on -// Google. - -var RequestMatcher = chrome.declarativeWebRequest.RequestMatcher; -var IgnoreRules = chrome.declarativeWebRequest.IgnoreRules; -var RedirectRequest = chrome.declarativeWebRequest.RedirectRequest; - -var catImageUrl = - 'https://i.chzbgr.com/completestore/12/8/23/S__rxG9hIUK4sNuMdTIY9w2.jpg'; - -// Registers redirect rules assuming that currently no rules are registered by -// this extension, yet. -function registerRules() { - var redirectRule = { - priority: 100, - conditions: [ - // If any of these conditions is fulfilled, the actions are executed. - new RequestMatcher({ - // Both, the url and the resourceType must match. - url: {pathSuffix: '.jpg'}, - resourceType: ['image'] - }), - new RequestMatcher({ - url: {pathSuffix: '.jpeg'}, - resourceType: ['image'] - }), - ], - actions: [ - new RedirectRequest({redirectUrl: catImageUrl}) - ] - }; - - var exceptionRule = { - priority: 1000, - conditions: [ - // We use hostContains to compensate for various top-level domains. - new RequestMatcher({url: {hostContains: '.google.'}}) - ], - actions: [ - new IgnoreRules({lowerPriorityThan: 1000}) - ] - }; - - var callback = function() { - if (chrome.runtime.lastError) { - console.error('Error adding rules: ' + chrome.runtime.lastError); - } else { - console.info('Rules successfully installed'); - chrome.declarativeWebRequest.onRequest.getRules(null, - function(rules) { - console.info('Now the following rules are registered: ' + - JSON.stringify(rules, null, 2)); - }); - } - }; - - chrome.declarativeWebRequest.onRequest.addRules( - [redirectRule, exceptionRule], callback); -} - -function setup() { - // This function is also called when the extension has been updated. Because - // registered rules are persisted beyond browser restarts, we remove - // previously registered rules before registering new ones. - chrome.declarativeWebRequest.onRequest.removeRules( - null, - function() { - if (chrome.runtime.lastError) { - console.error('Error clearing rules: ' + chrome.runtime.lastError); - } else { - registerRules(); - } - }); -} - -// This is triggered when the extension is installed or updated. -chrome.runtime.onInstalled.addListener(setup);
diff --git a/chrome/common/extensions/docs/examples/extensions/catifier/manifest.json b/chrome/common/extensions/docs/examples/extensions/catifier/manifest.json deleted file mode 100644 index ba37252..0000000 --- a/chrome/common/extensions/docs/examples/extensions/catifier/manifest.json +++ /dev/null
@@ -1,12 +0,0 @@ -{ - "name": "Catifier", - "version": "1.0", - "description": "Moar cats!", - "permissions": ["declarativeWebRequest", "<all_urls>"], - "background": { - "scripts": ["event_page.js"], - "persistent": false - }, - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/chrome_search/background.js b/chrome/common/extensions/docs/examples/extensions/chrome_search/background.js deleted file mode 100644 index 1dda1e5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/chrome_search/background.js +++ /dev/null
@@ -1,171 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var currentRequest = null; - -chrome.omnibox.onInputChanged.addListener( - function(text, suggest) { - if (currentRequest != null) { - currentRequest.onreadystatechange = null; - currentRequest.abort(); - currentRequest = null; - } - - updateDefaultSuggestion(text); - if (text == '' || text == 'halp') - return; - - currentRequest = search(text, function(xml) { - var results = []; - var entries = xml.getElementsByTagName("entry"); - - for (var i = 0, entry; i < 5 && (entry = entries[i]); i++) { - var path = entry.getElementsByTagName("file")[0].getAttribute("name"); - var line = - entry.getElementsByTagName("match")[0].getAttribute("lineNumber"); - var file = path.split("/").pop(); - - var description = '<url>' + file + '</url>'; - if (/^file:/.test(text)) { - description += ' <dim>' + path + '</dim>'; - } else { - var content = entry.getElementsByTagName("content")[0].textContent; - - // There can be multiple lines. Kill all the ones except the one that - // contains the first match. We can ocassionally fail to find a single - // line that matches, so we still handle multiple lines below. - var matches = content.split(/\n/); - for (var j = 0, match; match = matches[j]; j++) { - if (match.indexOf('<b>') > -1) { - content = match; - break; - } - } - - // Replace any extraneous whitespace to make it look nicer. - content = content.replace(/[\n\t]/g, ' '); - content = content.replace(/ {2,}/g, ' '); - - // Codesearch wraps the result in <pre> tags. Remove those if they're - // still there. - content = content.replace(/<\/?pre>/g, ''); - - // Codesearch highlights the matches with 'b' tags. Replaces those - // with 'match'. - content = content.replace(/<(\/)?b>/g, '<$1match>'); - - description += ' ' + content; - } - - results.push({ - content: path + '@' + line, - description: description - }); - } - - suggest(results); - }); - } -); - -function resetDefaultSuggestion() { - chrome.omnibox.setDefaultSuggestion({ - description: '<url><match>src:</match></url> Search Chromium source' - }); -} - -resetDefaultSuggestion(); - -function updateDefaultSuggestion(text) { - var isRegex = /^re:/.test(text); - var isFile = /^file:/.test(text); - var isHalp = (text == 'halp'); - var isPlaintext = text.length && !isRegex && !isFile && !isHalp; - - var description = '<match><url>src</url></match><dim> [</dim>'; - description += - isPlaintext ? ('<match>' + text + '</match>') : 'plaintext-search'; - description += '<dim> | </dim>'; - description += isRegex ? ('<match>' + text + '</match>') : 're:regex-search'; - description += '<dim> | </dim>'; - description += isFile ? ('<match>' + text + '</match>') : 'file:filename'; - description += '<dim> | </dim>'; - description += isHalp ? '<match>halp</match>' : 'halp'; - description += '<dim> ]</dim>'; - - chrome.omnibox.setDefaultSuggestion({ - description: description - }); -} - -chrome.omnibox.onInputStarted.addListener(function() { - updateDefaultSuggestion(''); -}); - -chrome.omnibox.onInputCancelled.addListener(function() { - resetDefaultSuggestion(); -}); - -function search(query, callback) { - if (query == 'halp') - return; - - if (/^re:/.test(query)) - query = query.substring('re:'.length); - else if (/^file:/.test(query)) - query = 'file:"' + query.substring('file:'.length) + '"'; - else - query = '"' + query + '"'; - - var url = "https://code.google.com/p/chromium/codesearch#search/&type=cs&q=" + query + - "&exact_package=chromium&type=cs"; - var req = new XMLHttpRequest(); - req.open("GET", url, true); - req.setRequestHeader("GData-Version", "2"); - req.onreadystatechange = function() { - if (req.readyState == 4) { - callback(req.responseXML); - } - } - req.send(null); - return req; -} - -function getUrl(path, line) { - var url = "https://code.google.com/p/chromium/codesearch#" + path - "&sq=package:chromium"; - if (line) - url += "&l=" + line; - return url; -} - -function getEntryUrl(entry) { - return getUrl( - entry.getElementsByTagName("file")[0].getAttribute("name"), - entry.getElementsByTagName("match")[0].getAttribute("lineNumber")); - return url; -} - -function navigate(url) { - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - chrome.tabs.update(tabs[0].id, {url: url}); - }); -} - -chrome.omnibox.onInputEntered.addListener(function(text) { - // TODO(aa): We need a way to pass arbitrary data through. Maybe that is just - // URL? - if (/@\d+\b/.test(text)) { - var chunks = text.split('@'); - var path = chunks[0]; - var line = chunks[1]; - navigate(getUrl(path, line)); - } else if (text == 'halp') { - // TODO(aa) - } else { - navigate("https://code.google.com/p/chromium/codesearch#search/&type=cs" + - "&q=" + text + - "&exact_package=chromium&type=cs"); - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/chrome_search/manifest.json b/chrome/common/extensions/docs/examples/extensions/chrome_search/manifest.json deleted file mode 100644 index 771783b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/chrome_search/manifest.json +++ /dev/null
@@ -1,13 +0,0 @@ -{ - "background": { - "scripts": ["background.js"] - }, - "description": "Add support to the omnibox to search the Chromium source code.", - "name": "Chromium Search", - "omnibox": { "keyword" : "src" }, - "permissions": [ "http://www.google.com/" ], - "version": "6.1", - "minimum_chrome_version": "9", - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/background.js b/chrome/common/extensions/docs/examples/extensions/constant_context/background.js deleted file mode 100644 index 6a5460d9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/background.js +++ /dev/null
@@ -1,21 +0,0 @@ -// 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. - -// Create a rule that will show the page action when the conditions are met. -const kMatchRule = { - // Declare the rule conditions. - conditions: [new chrome.declarativeContent.PageStateMatcher({ - pageUrl: {hostEquals: 'developer.chrome.com'}, - })], - // Shows the page action when the condition is met. - actions: [new chrome.declarativeContent.ShowPageAction()] -} - -// Register the runtime.onInstalled event listener. -chrome.runtime.onInstalled.addListener(function() { - // Overrride the rules to replace them with kMatchRule. - chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { - chrome.declarativeContent.onPageChanged.addRules([kMatchRule]); - }); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/content_script.js b/chrome/common/extensions/docs/examples/extensions/constant_context/content_script.js deleted file mode 100644 index 91cc428..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/content_script.js +++ /dev/null
@@ -1,19 +0,0 @@ -// 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. - -chrome.storage.local.get(['words'], function(object) { - let regExp = new RegExp('\\b(' + object.words.join('|') + ')\\b'); - const kSets = [ - {selectors: 'p, span', color: '#f7d68f'}, - {selectors: 'li, td', color: '#89b1ed'}, - {selectors: 'h1, h2, h3, th', color: '#8ae2a0'} - ]; - for (let set of kSets) { - let elements = Array.from(document.querySelectorAll(set.selectors)); - for (let element of elements) { - if (regExp.test(element.innerText)) - element.style.backgroundColor = set.color; - } - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc128.png b/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc128.png deleted file mode 100644 index e135104..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc16.png b/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc16.png deleted file mode 100644 index 4fb1eb35..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc32.png b/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc32.png deleted file mode 100644 index 340103ee..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc48.png b/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc48.png deleted file mode 100644 index 5d06080e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/images/cc48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/manifest.json b/chrome/common/extensions/docs/examples/extensions/constant_context/manifest.json deleted file mode 100644 index ebccaa5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/manifest.json +++ /dev/null
@@ -1,37 +0,0 @@ -{ - "name": "Constant Context", - "description" : "Highlights elements with keywords on developer.chrome", - "version": "1.0", - "page_action": { - "default_icon": { - "16": "images/cc16.png", - "32": "images/cc32.png" - }, - "default_popup": "popup.html" - }, - "icons": { - "16": "images/cc16.png", - "48": "images/cc48.png", - "32": "images/cc32.png", - "128": "images/cc128.png" - }, - "permissions": [ - "https://developer.chrome.com/*", - "storage", - "declarativeContent" - ], - "manifest_version": 2, - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "web_accessible_resources": ["style.css"], - "content_scripts": [ - { - "all_frames": true, - "js": ["content_script.js"], - "matches": ["https://developer.chrome.com/*"], - "run_at": "document_idle" - } - ] -}
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/popup.html b/chrome/common/extensions/docs/examples/extensions/constant_context/popup.html deleted file mode 100644 index 9481b48..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/popup.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Constant Context</title> - <style> - body { - min-width: 300px; - font-size: 15px; - } - input { - margin: 5px; - outline: none; - } - </style> - </head> - - <body> - <h2>Constant Context</h2> - <p>Highlights context around words.</p> - <ul id="displayWords"></ul> - <form id="form"> - <input type="text" name="word" id="userWords"> - <br> - <input type='submit' value='Submit' id='wordSubmit'> - <button id="clearList">Clear</button> - </form> - </body> - <script src="popup.js"></script> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/constant_context/popup.js b/chrome/common/extensions/docs/examples/extensions/constant_context/popup.js deleted file mode 100644 index ba4881c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/constant_context/popup.js +++ /dev/null
@@ -1,35 +0,0 @@ -// 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. - -function displayWords() { - chrome.storage.local.get(['words'], function(object) { - let pageList = document.getElementById('displayWords'); - if (object.words) { - searchWords = object.words - for (var i = 0; i < searchWords.length; i++){ - let listItem = document.createElement('li'); - listItem.innerText = searchWords[i] - pageList.appendChild(listItem); - } - } - }); -} - -displayWords(); - -document.getElementById('wordSubmit').onclick = function() { - let userWords = document.getElementById('userWords').value.trim(); - chrome.storage.local.get(['words'], function(object) { - let newWords = object.words || []; - newWords.push(userWords); - chrome.storage.local.set({words: newWords}); - }) - chrome.tabs.executeScript(null, { - file: 'content_script.js' - }); -} - -document.getElementById('clearList').onclick = function() { - chrome.storage.local.clear(); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/background.js b/chrome/common/extensions/docs/examples/extensions/download_images/background.js deleted file mode 100644 index 5d660788..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/background.js +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -// Declare extension default properties -let downloadsArray = []; -let initialState = { - 'savedImages': downloadsArray, - 'thumbnails': false, - 'saveImages': true -}; - -// Set extension setting on installation -chrome.runtime.onInstalled.addListener(function() { - chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { - chrome.declarativeContent.onPageChanged.addRules([{ - conditions: [ - new chrome.declarativeContent.PageStateMatcher({ - pageUrl: { hostEquals: 'developer.chrome.com', schemes: ['https'] }, - css: ['img'] - }) - ], - actions: [ new chrome.declarativeContent.ShowPageAction() ] - }]); - }); - chrome.storage.local.set(initialState); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image128.png b/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image128.png deleted file mode 100644 index 77e5f82..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image16.png b/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image16.png deleted file mode 100644 index 6df385d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image32.png b/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image32.png deleted file mode 100644 index d6a9bf3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image48.png b/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image48.png deleted file mode 100644 index c4bcded3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/images/download_image48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/manifest.json b/chrome/common/extensions/docs/examples/extensions/download_images/manifest.json deleted file mode 100644 index 58fd910b1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/manifest.json +++ /dev/null
@@ -1,32 +0,0 @@ -{ - "name": "Download Images", - "description" : "Displays all webpage images and allows user to download", - "version": "1.0", - "manifest_version": 2, - "page_action": { - "default_popup": "popup.html", - "default_icon": { - "16": "/images/download_image16.png", - "32": "/images/download_image32.png", - "48": "/images/download_image48.png", - "128": "/images/download_image128.png" - } - }, - "icons": { - "16": "/images/download_image16.png", - "32": "/images/download_image32.png", - "48": "/images/download_image48.png", - "128": "/images/download_image128.png" - }, - "permissions": [ - "downloads", - "storage", - "activeTab", - "declarativeContent" - ], - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "options_page": "options.html" -}
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/options.html b/chrome/common/extensions/docs/examples/extensions/download_images/options.html deleted file mode 100644 index 40b9474..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/options.html +++ /dev/null
@@ -1,40 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Options: Download Images</title> - <style> - #options_div { - margin: 30px; - } - #saved_images { - display: flex; - align-items: center; - justify-content: center; - } - - img { - max-width: 100%; - max-height: 100%; - } - - .square { - height: 175px; - width: 175px; - margin: 10px; - } - </style> - </head> - <body> - <div id="options_div"> - <input type="checkbox" id="thumbnails"> Display Images as Thumbnails - <br /> - <br /> - <input type="checkbox" id="save_images"> Save Downloaded Images - <br /> - <br /> - <button id="delete_button">Delete Saved Images</button> - </div> - <div id="savedImages"></div> - <script src="options.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/options.js b/chrome/common/extensions/docs/examples/extensions/download_images/options.js deleted file mode 100644 index c35e9b9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/options.js +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2018 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. - -'use strict' - -// Selects saveImagesOption checkbox element -let saveImagesOption = document.getElementById('save_images'); -// Selects thumbnailOption checkbox element -let thumbnailOption = document.getElementById('thumbnails'); - -function setCheckbox(data, checkbox) { - checkbox.checked = data; -}; - -// Gets thumbnails and saveImages value from storage -chrome.storage.local.get(['saveImages', 'thumbnails'], function(data) { - setCheckbox(data.saveImages, saveImagesOption); - saveImagesOption.checked = data.saveImages === true; - setCheckbox(data.thumbnails, thumbnailOption); -}); - -// Saves users prefrences -function storeOption(optionName, optionValue) { - let data = {}; - data[optionName] = optionValue; - chrome.storage.local.set(data); -}; - -saveImagesOption.onchange = function() { - storeOption('saveImages', saveImagesOption.checked); -}; - -thumbnailOption.onchange = function() { - storeOption('thumbnails', thumbnailOption.checked); -}; - -let savedImages = document.getElementById('savedImages'); - -let deleteButton = document.getElementById('delete_button'); - -deleteButton.onclick = function() { - let blankArray = []; - chrome.storage.local.set({'savedImages': blankArray}); - location.reload(); -}; -// Gets saved downloaded images from storage -chrome.storage.local.get('savedImages', function(element) { - let pageImages = element.savedImages; - pageImages.forEach(function(image) { - // Create div element and give it class of square - let newDiv = document.createElement('div'); - newDiv.className = 'square'; - // Create image element - let newImage = document.createElement('img'); - // let lineBreak = document.createElement('br'); - // Image source is equal to saved download image - newImage.src = image; - newImage.addEventListener('click', function() { - chrome.downloads.download({url: newImage.src}); - }); - // Append all elements to options page - newDiv.appendChild(newImage); - savedImages.appendChild(newDiv); - }); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/popup.html b/chrome/common/extensions/docs/examples/extensions/download_images/popup.html deleted file mode 100644 index dd10122..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/popup.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Download Images</title> - <style> - body { - min-width: 300px; - font-size: 15px; - } - input { - margin: 5px; - outline: none; - } - img { - max-width: 100%; - max-height: 100%; - } - .square { - height: 175px; - width: 175px; - margin: 10px; - } - </style> - </head> - <body> - <h1>Click image to download.</h1> - <button id="options_button">Options</button> - <br> - <div id="image_div"></div> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/download_images/popup.js b/chrome/common/extensions/docs/examples/extensions/download_images/popup.js deleted file mode 100644 index 81cc647..0000000 --- a/chrome/common/extensions/docs/examples/extensions/download_images/popup.js +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2018 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. - -'use strict' - -// Script code to inject on page -// Selects images then returns array of their currentSrc -const scriptCode = - `(function() { - let images = document.querySelectorAll('img'); - let srcArray = - Array.from(images).map(function(image) { - return image.currentSrc; - }); - return srcArray - })();`; - - -// Declare add image function to save downloaded images -function addImage(url) { - chrome.storage.local.get('savedImages', function(result) { - // Check if storage has exsisting arrays - // If array found, blank array is replaced with found array - // If no array, we add to created blank array - let downloadsArray = result.savedImages || []; - // Images are added - downloadsArray.push(url); - // Chrome stores the new array with the new image - chrome.storage.local.set({'savedImages': downloadsArray}, function() { - if (chrome.runtime.lastError) { - console.log(chrome.runtime.lastError); - } else { - console.log('Image saved successfully'); - }; - }); - }); -}; - -// Grabs the imageDiv from the popup -let imageDiv = document.getElementById('image_div'); -function setUp(array) { - chrome.storage.local.get( - ['saveImages', 'thumbnails'], function(config) { - for (let src of array) { - let newImage = document.createElement('img'); - let lineBreak = document.createElement('br'); - newImage.src = src; - console.log(newImage) - // Add an onclick event listener - newImage.addEventListener('click', function() { - // Downloads and image when it is clicked on - chrome.downloads.download({url: newImage.src}); - // Checks if extension is set to store images - if (config.saveImages === true) { - // If true, call addImage function - addImage(newImage.src); - }; - }); - // Checks extension thumbnail settings - if (config.thumbnails === true) { - // If on, popup displays images as thumnails - let newDiv = document.createElement('div'); - newDiv.className = 'square'; - newDiv.appendChild(newImage); - imageDiv.appendChild(newDiv); - } else { - // If off, images are displayed at full size - imageDiv.appendChild(newImage); - }; - imageDiv.appendChild(lineBreak); - }; - }); -}; - -// Runs script when popup is opened -chrome.tabs.executeScript({code: scriptCode}, function(result) { - setUp(result[0]); -}); - -let optionsButton = document.getElementById('options_button'); - -optionsButton.onclick = function() { - chrome.tabs.create({ url: "options.html" }); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/email_this_page/background.js b/chrome/common/extensions/docs/examples/extensions/email_this_page/background.js deleted file mode 100644 index a16ef80..0000000 --- a/chrome/common/extensions/docs/examples/extensions/email_this_page/background.js +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function customMailtoUrl() { - if (window.localStorage == null) - return ""; - if (window.localStorage.customMailtoUrl == null) - return ""; - return window.localStorage.customMailtoUrl; -} - -function executeMailto(tab_id, subject, body, selection) { - var default_handler = customMailtoUrl().length == 0; - - var action_url = "mailto:?" - if (subject.length > 0) - action_url += "subject=" + encodeURIComponent(subject) + "&"; - - if (body.length > 0) { - action_url += "body=" + encodeURIComponent(body); - - // Append the current selection to the end of the text message. - if (selection.length > 0) { - action_url += encodeURIComponent("\n\n") + - encodeURIComponent(selection); - } - } - - if (!default_handler) { - // Custom URL's (such as opening mailto in Gmail tab) should have a - // separate tab to avoid clobbering the page you are on. - var custom_url = customMailtoUrl(); - action_url = custom_url.replace("%s", encodeURIComponent(action_url)); - console.log('Custom url: ' + action_url); - chrome.tabs.create({ url: action_url }); - } else { - // Plain vanilla mailto links open up in the same tab to prevent - // blank tabs being left behind. - console.log('Action url: ' + action_url); - chrome.tabs.update(tab_id, { url: action_url }); - } -} - -chrome.runtime.onConnect.addListener(function(port) { - var tab = port.sender.tab; - - // This will get called by the content script we execute in - // the tab as a result of the user pressing the browser action. - port.onMessage.addListener(function(info) { - var max_length = 1024; - if (info.selection.length > max_length) - info.selection = info.selection.substring(0, max_length); - executeMailto(tab.id, info.title, tab.url, info.selection); - }); -}); - -// Called when the user clicks on the browser action icon. -chrome.browserAction.onClicked.addListener(function(tab) { - // We can only inject scripts to find the title on pages loaded with http - // and https so for all other pages, we don't ask for the title. - if (tab.url.indexOf("http:") != 0 && - tab.url.indexOf("https:") != 0) { - executeMailto(tab.id, "", tab.url, ""); - } else { - chrome.tabs.executeScript(null, {file: "content_script.js"}); - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/email_this_page/content_script.js b/chrome/common/extensions/docs/examples/extensions/email_this_page/content_script.js deleted file mode 100644 index 08744ef..0000000 --- a/chrome/common/extensions/docs/examples/extensions/email_this_page/content_script.js +++ /dev/null
@@ -1,10 +0,0 @@ -// Copyright (c) 2009 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. - -var additionalInfo = { - "title": document.title, - "selection": window.getSelection().toString() -}; - -chrome.runtime.connect().postMessage(additionalInfo);
diff --git a/chrome/common/extensions/docs/examples/extensions/email_this_page/email_16x16.png b/chrome/common/extensions/docs/examples/extensions/email_this_page/email_16x16.png deleted file mode 100644 index 5ab1a150..0000000 --- a/chrome/common/extensions/docs/examples/extensions/email_this_page/email_16x16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/email_this_page/mail_128x128.png b/chrome/common/extensions/docs/examples/extensions/email_this_page/mail_128x128.png deleted file mode 100644 index 835df38..0000000 --- a/chrome/common/extensions/docs/examples/extensions/email_this_page/mail_128x128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/email_this_page/manifest.json b/chrome/common/extensions/docs/examples/extensions/email_this_page/manifest.json deleted file mode 100644 index 3801b87..0000000 --- a/chrome/common/extensions/docs/examples/extensions/email_this_page/manifest.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name": "Email this page (by Google)", - "description": "This extension adds an email button to the toolbar which allows you to email the page link using your default mail client or Gmail.", - "version": "1.2.6", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "icons": { "128": "mail_128x128.png" }, - "options_page": "options.html", - "permissions": [ - "tabs", "http://*/*", "https://*/*" - ], - "browser_action": { - "default_title": "Email this page", - "default_icon": "email_16x16.png" - }, - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/email_this_page/options.html b/chrome/common/extensions/docs/examples/extensions/email_this_page/options.html deleted file mode 100644 index a27f7ebc..0000000 --- a/chrome/common/extensions/docs/examples/extensions/email_this_page/options.html +++ /dev/null
@@ -1,44 +0,0 @@ -<!DOCTYPE> -<!-- - * Copyright (c) 2012 The Chromium Authors. All rights reserved. Use of this - * source code is governed by a BSD-style license that can be found in the - * LICENSE file. ---> -<html> -<head> - <title>Options for the Send as Email extension</title> -<style> -#providerSelection { - font-family: Helvetica, Arial, sans-serif; - font-size: 10pt; -} -</style> -<script src="options.js"></script> -</head> -<body> -<table class="simple"> -<tr> - <td rowspan="2" valign="top" align="center" width="80"> - <img src="mail_128x128.png" width="64" height="64" /> - </td> - <td height="22"></td> -</tr> -<tr> - <td valign="center"> - <div id="providerSelection"> - <strong>Select provider to use when emailing a web page address:</strong> - <br /><br /> - <label> - <input id="default" type="radio" name="mailto" value="mailto" checked> - Your default mail handler<br> - </label> - - <label> - <input id="gmail" type="radio" name="mailto" value="gmail">Gmail<br> - </label> - </div> - </td> -</tr> -</table> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/email_this_page/options.js b/chrome/common/extensions/docs/examples/extensions/email_this_page/options.js deleted file mode 100644 index 2c682a4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/email_this_page/options.js +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var gmail = "https://mail.google.com/mail/?extsrc=mailto&url=%s"; - -function toggle(radioButton) { - if (window.localStorage == null) { - alert('Local storage is required for changing providers'); - return; - } - if (document.getElementById('gmail').checked) { - window.localStorage.customMailtoUrl = gmail; - } else { - window.localStorage.customMailtoUrl = ""; - } -} - -function main() { - if (window.localStorage == null) { - alert("LocalStorage must be enabled for changing options."); - document.getElementById('default').disabled = true; - document.getElementById('gmail').disabled = true; - return; - } - - // Default handler is checked. If we've chosen another provider, we must - // change the checkmark. - if (window.localStorage.customMailtoUrl == gmail) - document.getElementById('gmail').checked = true; -} - -document.addEventListener('DOMContentLoaded', function () { - main(); - document.querySelector('#default').addEventListener('click', toggle); - document.querySelector('#gmail').addEventListener('click', toggle); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/fx/bg.js b/chrome/common/extensions/docs/examples/extensions/fx/bg.js deleted file mode 100644 index 3f3814ba..0000000 --- a/chrome/common/extensions/docs/examples/extensions/fx/bg.js +++ /dev/null
@@ -1,431 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* - * Background page for Chrome Sounds extension. - * This tracks various events from Chrome and plays sounds. - */ - -// Map of hostname suffixes or URLs without query params to sounds. -// Yeah OK, some of these are a little cliche... -var urlSounds = { - "http://www.google.ca/": "canadian-hello.mp3", - "chrome://histograms/": "time-passing.mp3", - "chrome://memory/": "transform!.mp3", - "chrome://crash/": "sadtrombone.mp3", - "chrome://extensions/": "beepboop.mp3", - "http://www.google.com.au/": "didgeridoo.mp3", - "http://www.google.com.my/": "my_subway.mp3", - "http://www.google.com/appserve/fiberrfi/": "dialup.mp3", - "lively.com": "cricket.mp3", - "http://www.google.co.uk/": "mind_the_gap.mp3", - "http://news.google.com/": "news.mp3", - "http://www.bing.com/": "sonar.mp3", -}; - -// Map of query parameter words to sounds. -// More easy cliches... -var searchSounds = { - "scotland": "bagpipe.mp3", - "seattle": "rain.mp3", -}; - -// Map of tab numbers to notes on a scale. -var tabNoteSounds = { - "tab0": "mando-1.mp3", - "tab1": "mando-2.mp3", - "tab2": "mando-3.mp3", - "tab3": "mando-4.mp3", - "tab4": "mando-5.mp3", - "tab5": "mando-6.mp3", - "tab6": "mando-7.mp3", -}; - -// Map of sounds that play in a continuous loop while an event is happening -// in the content area (e.g. "keypress" while start and keep looping while -// the user keeps typing). -var contentSounds = { - "keypress": "typewriter-1.mp3", - "resize": "harp-transition-2.mp3", - "scroll": "shepard.mp3" -}; - -// Map of events to their default sounds -var eventSounds = { - "tabCreated": "conga1.mp3", - "tabMoved": "bell-transition.mp3", - "tabRemoved": "smash-glass-1.mp3", - "tabSelectionChanged": "click.mp3", - "tabAttached": "whoosh-15.mp3", - "tabDetached": "sword-shrill.mp3", - "tabNavigated": "click.mp3", - "windowCreated": "bell-small.mp3", - "windowFocusChanged": "click.mp3", - "bookmarkCreated": "bubble-drop.mp3", - "bookmarkMoved": "thud.mp3", - "bookmarkRemoved": "explosion-6.mp3", - "windowCreatedIncognito": "weird-wind1.mp3", - "startup": "whoosh-19.mp3" -}; - -var soundLists = [urlSounds, searchSounds, eventSounds, tabNoteSounds, - contentSounds]; - -var sounds = {}; - -// Map of event names to extension events. -// Events intentionally skipped: -// chrome.windows.onRemoved - can't suppress the tab removed that comes first -var events = { - "tabCreated": chrome.tabs.onCreated, - "tabMoved": chrome.tabs.onMoved, - "tabRemoved": chrome.tabs.onRemoved, - "tabSelectionChanged": chrome.tabs.onSelectionChanged, - "tabAttached": chrome.tabs.onAttached, - "tabDetached": chrome.tabs.onDetached, - "tabNavigated": chrome.tabs.onUpdated, - "windowCreated": chrome.windows.onCreated, - "windowFocusChanged": chrome.windows.onFocusChanged, - "bookmarkCreated": chrome.bookmarks.onCreated, - "bookmarkMoved": chrome.bookmarks.onMoved, - "bookmarkRemoved": chrome.bookmarks.onRemoved -}; - -// Map of event name to a validation function that is should return true if -// the default sound should be played for this event. -var eventValidator = { - "tabCreated": tabCreated, - "tabNavigated": tabNavigated, - "tabRemoved": tabRemoved, - "tabSelectionChanged": tabSelectionChanged, - "windowCreated": windowCreated, - "windowFocusChanged": windowFocusChanged, -}; - -var started = false; - -function shouldPlay(id) { - // Ignore all events until the startup sound has finished. - if (id != "startup" && !started) - return false; - var val = localStorage.getItem(id); - if (val && val != "enabled") { - console.log(id + " disabled"); - return false; - } - return true; -} - -function didPlay(id) { - if (!localStorage.getItem(id)) - localStorage.setItem(id, "enabled"); -} - -function playSound(id, loop) { - if (!shouldPlay(id)) - return; - - var sound = sounds[id]; - console.log("playsound: " + id); - if (sound && sound.src) { - if (!sound.paused) { - if (sound.currentTime < 0.2) { - console.log("ignoring fast replay: " + id + "/" + sound.currentTime); - return; - } - sound.pause(); - sound.currentTime = 0; - } - if (loop) - sound.loop = loop; - - // Sometimes, when playing multiple times, readyState is HAVE_METADATA. - if (sound.readyState == 0) { // HAVE_NOTHING - console.log("bad ready state: " + sound.readyState); - } else if (sound.error) { - console.log("media error: " + sound.error); - } else { - didPlay(id); - sound.play(); - } - } else { - console.log("bad playSound: " + id); - } -} - -function stopSound(id) { - console.log("stopSound: " + id); - var sound = sounds[id]; - if (sound && sound.src && !sound.paused) { - sound.pause(); - sound.currentTime = 0; - } -} - -var base_url = "http://dl.google.com/dl/chrome/extensions/audio/"; - -function soundLoadError(audio, id) { - console.log("failed to load sound: " + id + "-" + audio.src); - audio.src = ""; - if (id == "startup") - started = true; -} - -function soundLoaded(audio, id) { - console.log("loaded sound: " + id); - sounds[id] = audio; - if (id == "startup") - playSound(id); -} - -// Hack to keep a reference to the objects while we're waiting for them to load. -var notYetLoaded = {}; - -function loadSound(file, id) { - if (!file.length) { - console.log("no sound for " + id); - return; - } - var audio = new Audio(); - audio.id = id; - audio.onerror = function() { soundLoadError(audio, id); }; - audio.addEventListener("canplaythrough", - function() { soundLoaded(audio, id); }, false); - if (id == "startup") { - audio.addEventListener("ended", function() { started = true; }); - } - audio.src = base_url + file; - audio.load(); - notYetLoaded[id] = audio; -} - -// Remember the last event so that we can avoid multiple events firing -// unnecessarily (e.g. selection changed due to close). -var eventsToEat = 0; - -function eatEvent(name) { - if (eventsToEat > 0) { - console.log("ate event: " + name); - eventsToEat--; - return true; - } - return false; -} - -function soundEvent(event, name) { - if (event) { - var validator = eventValidator[name]; - if (validator) { - event.addListener(function() { - console.log("handling custom event: " + name); - - // Check this first since the validator may bump the count for future - // events. - var canPlay = (eventsToEat == 0); - if (validator.apply(this, arguments)) { - if (!canPlay) { - console.log("ate event: " + name); - eventsToEat--; - return; - } - playSound(name); - } - }); - } else { - event.addListener(function() { - console.log("handling event: " + name); - if (eatEvent(name)) { - return; - } - playSound(name); - }); - } - } else { - console.log("no event for " + name); - } -} - -var navSound; - -function stopNavSound() { - if (navSound) { - stopSound(navSound); - navSound = null; - } -} - -function playNavSound(id) { - stopNavSound(); - navSound = id; - playSound(id); -} - -function tabNavigated(tabId, changeInfo, tab) { - // Quick fix to catch the case where the content script doesn't have a chance - // to stop itself. - stopSound("keypress"); - - //console.log(JSON.stringify(changeInfo) + JSON.stringify(tab)); - if (changeInfo.status != "complete") { - return false; - } - if (eatEvent("tabNavigated")) { - return false; - } - - console.log(JSON.stringify(tab)); - - if (navSound) - stopSound(navSound); - - var re = /https?:\/\/([^\/:]*)[^\?]*\??(.*)/i; - match = re.exec(tab.url); - if (match) { - if (match.length == 3) { - var query = match[2]; - var parts = query.split("&"); - for (var i in parts) { - if (parts[i].indexOf("q=") == 0) { - var q = decodeURIComponent(parts[i].substring(2)); - q = q.replace("+", " "); - console.log("query == " + q); - var words = q.split(" "); - for (j in words) { - if (searchSounds[words[j]]) { - console.log("searchSound: " + words[j]); - playNavSound(words[j]); - return false; - } - } - break; - } - } - } - if (match.length >= 2) { - var hostname = match[1]; - if (hostname) { - var parts = hostname.split("."); - if (parts.length > 1) { - var tld2 = parts.slice(-2).join("."); - var tld3 = parts.slice(-3).join("."); - var sound = urlSounds[tld2]; - if (sound) { - playNavSound(tld2); - return false; - } - sound = urlSounds[tld3]; - if (sound) { - playNavSound(tld3); - return false; - } - } - } - } - } - - // Now try a direct URL match (without query string). - var url = tab.url; - var query = url.indexOf("?"); - if (query > 0) { - url = tab.url.substring(0, query); - } - console.log(tab.url); - var sound = urlSounds[url]; - if (sound) { - playNavSound(url); - return false; - } - - return true; -} - -var selectedTabId = -1; - -function tabSelectionChanged(tabId) { - selectedTabId = tabId; - if (eatEvent("tabSelectionChanged")) - return false; - - var count = 7; - chrome.tabs.get(tabId, function(tab) { - var index = tab.index % count; - playSound("tab" + index); - }); - return false; -} - -function tabCreated(tab) { - if (eatEvent("tabCreated")) { - return false; - } - eventsToEat++; // tabNavigated or tabSelectionChanged - // TODO - unfortunately, we can't detect whether this tab will get focus, so - // we can't decide whether or not to eat a second event. - return true; -} - -function tabRemoved(tabId) { - if (eatEvent("tabRemoved")) { - return false; - } - if (tabId == selectedTabId) { - eventsToEat++; // tabSelectionChanged - stopNavSound(); - } - return true; -} - -function windowCreated(window) { - if (eatEvent("windowCreated")) { - return false; - } - eventsToEat += 3; // tabNavigated, tabSelectionChanged, windowFocusChanged - if (window.incognito) { - playSound("windowCreatedIncognito"); - return false; - } - return true; -} - -var selectedWindowId = -1; - -function windowFocusChanged(windowId) { - if (windowId == selectedWindowId) { - return false; - } - selectedWindowId = windowId; - if (eatEvent("windowFocusChanged")) { - return false; - } - return true; -} - -function contentScriptHandler(request) { - if (contentSounds[request.eventName]) { - if (request.eventValue == "started") { - playSound(request.eventName, true); - } else if (request.eventValue == "stopped") { - stopSound(request.eventName); - } else { - playSound(request.eventName); - } - } - console.log("got message: " + JSON.stringify(request)); -} - - -////////////////////////////////////////////////////// - -// Listen for messages from content scripts. -chrome.extension.onRequest.addListener(contentScriptHandler); - -// Load the sounds and register event listeners. -for (var list in soundLists) { - for (var id in soundLists[list]) { - loadSound(soundLists[list][id], id); - } -} -for (var name in events) { - soundEvent(events[name], name); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/fx/content.js b/chrome/common/extensions/docs/examples/extensions/fx/content.js deleted file mode 100644 index b79095c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/fx/content.js +++ /dev/null
@@ -1,62 +0,0 @@ -/* - * Content script for Chrome Sounds. - * Tracks in-page events and notifies the background page. - */ - -function sendEvent(event, value) { - console.log("sendEvent: " + event + "," + value); - chrome.extension.sendRequest({eventName: event, eventValue: value}); -} - -// Timers to trigger "stopEvent" for coalescing events. -var timers = {}; - -function stopEvent(type) { - timers[type] = 0; - sendEvent(type, "stopped"); -} - -// Automatically coalesces repeating events into a start and a stop event. -// |validator| is a function which should return true if the event is -// considered to be a valid event of this type. -function handleEvent(event, type, validator) { - if (validator) { - if (!validator(event)) { - return; - } - } - var timerId = timers[type]; - var eventInProgress = (timerId > 0); - if (eventInProgress) { - clearTimeout(timerId); - timers[type] = 0; - } else { - sendEvent(type, "started"); - } - timers[type] = setTimeout(stopEvent, 300, type); -} - -function listenAndCoalesce(target, type, validator) { - target.addEventListener(type, function(event) { - handleEvent(event, type, validator); - }, true); -} - -listenAndCoalesce(document, "scroll"); - -// For some reason, "resize" doesn't seem to work with addEventListener. -if ((window == window.top) && document.body && !document.body.onresize) { - document.body.onresize = function(event) { - sendEvent("resize", ""); - }; -} - -listenAndCoalesce(document, "keypress", function(event) { - if (event.charCode == 13) - return false; - - // TODO(erikkay) This doesn't work in gmail's rich text compose window. - return event.target.tagName == "TEXTAREA" || - event.target.tagName == "INPUT" || - event.target.isContentEditable; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/fx/icon.png b/chrome/common/extensions/docs/examples/extensions/fx/icon.png deleted file mode 100644 index dd6b4a7..0000000 --- a/chrome/common/extensions/docs/examples/extensions/fx/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/fx/manifest.json b/chrome/common/extensions/docs/examples/extensions/fx/manifest.json deleted file mode 100644 index 962c5eec..0000000 --- a/chrome/common/extensions/docs/examples/extensions/fx/manifest.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "name": "Chrome Sounds", - "version": "1.2", - "description": "Enjoy a more magical and immersive experience when browsing the web using the power of sound.", - "background": { - "scripts": ["bg.js"] - }, - "options_page": "options.html", - "icons": { "128": "icon.png" }, - "permissions": [ - "tabs", - "bookmarks", - "http://*/*", - "https://*/*" - ], - "content_scripts": [ { - "matches": ["http://*/*", "https://*/*"], - "js": ["content.js"], - "all_frames": true - }], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/fx/options.html b/chrome/common/extensions/docs/examples/extensions/fx/options.html deleted file mode 100644 index 12d86c3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/fx/options.html +++ /dev/null
@@ -1,31 +0,0 @@ -<!doctype html> -<html> -<head> -<style> -body { - font-family: sans-serif; -} -#attributions { - margin-top: 20px; - color: #666666; - Xfont-size: 10px; -} -.sound { - cursor: pointer; -} -</style> -<script src="options.js"></script> -</head> -<body> -<div id="sounds"></div> -<div id="attributions"> -Sounds from: -<ul> -<li><a href="http://www.freesound.org">www.freesound.org</a></li> -<li><a href="http://www.free-samples-n-loops.com/loops.html">www.free-samples-n-loops.com/loops.html</a></li> -<li>Googlers with microphones.*</li> -</ul> -<span style="font-size:10px">* Canadian sound made by actual Canadian.</span> -</div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/fx/options.js b/chrome/common/extensions/docs/examples/extensions/fx/options.js deleted file mode 100644 index 21d0afaa..0000000 --- a/chrome/common/extensions/docs/examples/extensions/fx/options.js +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function playSound(id) { - console.log(id); - chrome.extension.getBackgroundPage().playSound(id, false); -} - -function stopSound(id) { - chrome.extension.getBackgroundPage().stopSound(id); -} - -function soundChanged(event) { - var key = event.target.name; - var checked = event.target.checked; - if (checked) { - localStorage.setItem(key, "enabled"); - playSound(event.target.name); - } else { - localStorage.setItem(key, "disabled"); - stopSound(event.target.name); - } -} - -function showSounds() { - var sounds = document.getElementById("sounds"); - if (!localStorage.length) { - sounds.innerText = ""; - return; - } - sounds.innerText = "Discovered sounds: (uncheck to disable)"; - var keys = new Array(); - for (var key in localStorage) { - keys.push(key); - console.log(key); - } - keys.sort(); - for (var index in keys) { - var key = keys[index]; - var div = document.createElement("div"); - var check = document.createElement("input"); - check.type = "checkbox" - check.name = key; - check.checked = localStorage[key] == "enabled"; - check.onchange = soundChanged; - div.appendChild(check); - var text = document.createElement("span"); - text.id = key; - text.innerText = key; - text.className = "sound"; - text.onclick = function(event) { playSound(event.target.id); }; - div.appendChild(text); - sounds.appendChild(div); - } -} - -document.addEventListener('DOMContentLoaded', showSounds); -document.addEventListener('focus', showSounds);
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/README b/chrome/common/extensions/docs/examples/extensions/gdocs/README deleted file mode 100644 index 9c0393b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/README +++ /dev/null
@@ -1,69 +0,0 @@ -Sample extension to demonstrate integration with an OAuth service. - -Overview --------- -This sample demonstrates the use of OAuth to authorize against -Google's Contacts API inside of an extension. It implements a library which -may be reused generically to authorize requests to any 3-legged OAuth API. - -Library -------- -The library files are: - * chrome_ex_oauth.html - * chrome_ex_oauth.js - * chrome_ex_oauthsimple.js - -To use these files, place them in the root of your extension and include both -.js files in your background page in the following order: - - <script type="text/javascript" src="chrome_ex_oauthsimple.js"></script> - <script type="text/javascript" src="chrome_ex_oauth.js"></script> - -To initialize the API, create a ChromeExOAuth object in the background page: - - var oauth = ChromeExOAuth.initBackgroundPage({ - 'request_url' : <OAuth request URL>, - 'authorize_url' : <OAuth authorize URL>, - 'access_url' : <OAuth access token URL>, - 'consumer_key' : <OAuth consumer key>, - 'consumer_secret' : <OAuth consumer secret>, - 'scope' : <scope parameter for this auth>, - 'app_name' : <application name, not used by all OAuth providers> - }); - -Call the authorize() function to redirect the user to the OAuth provider in -order to obtain an access token. The client library abstracts most of this -process, so all you need to do is pass a callback to the authorize() function -and a new tab will open and redirect the user. If the library already has -stored an access token for the current scope, then no tab will be opened. In -either case, the callback will be called with the resulting token and secret. - - oauth.authorize(onAuthorized); - -There is no need to store the token and secret, as this library already stores -these values in localStorage. Once the callback you specified is called, you -can call the sendSignedRequest function to send OAuth-signed requests to the -API. The sendSignedRequest call takes an url to fetch, a callback function, -and an optional parameter object as its arguments. The callback is passed -the response text as well as the XMLHttpRequest object which was used to -make the request as its arguments. - - function callback(text, xhr) { - //... - }; - - function onAuthorized() { - var url = <API url inside of the requested scope>; - var request = { - 'method' : 'GET', - 'parameters' : { - <Any request parameters as key : value pairs> - } - } - oauth.sendSignedRequest(url, callback, request); - }; - oauth.authorize(onAuthorized); - - - -
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/background.html b/chrome/common/extensions/docs/examples/extensions/gdocs/background.html deleted file mode 100644 index 34478f5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/background.html +++ /dev/null
@@ -1,61 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. - * - * Author: Eric Bidelman <ericbidelman@chromium.org> ---> -<html> - <head> - <script type="text/javascript" src="chrome_ex_oauthsimple.js"></script> - <script type="text/javascript" src="chrome_ex_oauth.js"></script> - <script type="text/javascript"> - var DOCLIST_SCOPE = 'https://docs.google.com/feeds'; - var DOCLIST_FEED = DOCLIST_SCOPE + '/default/private/full/'; - var docs = []; // In memory cache for the user's entire doclist. - var refreshRate = localStorage.refreshRate || 300; // 5 min default. - var pollIntervalMin = 1000 * refreshRate; - var requests = []; - - var oauth = ChromeExOAuth.initBackgroundPage({ - 'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken', - 'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken', - 'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken', - 'consumer_key': 'anonymous', - 'consumer_secret': 'anonymous', - 'scope': DOCLIST_SCOPE, - 'app_name': 'Chrome Extension Sample - Accessing Google Docs with OAuth' - }); - - function setIcon(opt_badgeObj) { - if (opt_badgeObj) { - var badgeOpts = {}; - if (opt_badgeObj && opt_badgeObj.text != undefined) { - badgeOpts['text'] = opt_badgeObj.text; - } - if (opt_badgeObj && opt_badgeObj.tabId) { - badgeOpts['tabId'] = opt_badgeObj.tabId; - } - chrome.browserAction.setBadgeText(badgeOpts); - } - }; - - function clearPendingRequests() { - for (var i = 0, req; req = requests[i]; ++i) { - window.clearTimeout(req); - } - requests = []; - }; - - function logout() { - docs = []; - setIcon({'text': ''}); - oauth.clearTokens(); - clearPendingRequests(); - }; - </script> - </head> - <body> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.html b/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.html deleted file mode 100644 index 61d0ac2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.html +++ /dev/null
@@ -1,30 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. - * - * Author: Eric Bidelman <ericbidelman@chromium.org> ---> -<html> - <head> - <meta charset="UTF-8"> - <title>OAuth Redirect Page</title> - <style type="text/css"> - body { - font: 16px Arial; - color: #333; - } - </style> - <script type="text/javascript" src="chrome_ex_oauthsimple.js"></script> - <script type="text/javascript" src="chrome_ex_oauth.js"></script> - <script type="text/javascript"> - function onLoad() { - ChromeExOAuth.initCallbackPage(); - }; - </script> - </head> - <body onload="onLoad();"> - Redirecting... - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.js b/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.js deleted file mode 100644 index e28a594..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauth.js +++ /dev/null
@@ -1,592 +0,0 @@ -// Copyright (c) 2010 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. - -/** - * Constructor - no need to invoke directly, call initBackgroundPage instead. - * @constructor - * @param {String} url_request_token The OAuth request token URL. - * @param {String} url_auth_token The OAuth authorize token URL. - * @param {String} url_access_token The OAuth access token URL. - * @param {String} consumer_key The OAuth consumer key. - * @param {String} consumer_secret The OAuth consumer secret. - * @param {String} oauth_scope The OAuth scope parameter. - * @param {Object} opt_args Optional arguments. Recognized parameters: - * "app_name" {String} Name of the current application - * "callback_page" {String} If you renamed chrome_ex_oauth.html, the name - * this file was renamed to. - */ -function ChromeExOAuth(url_request_token, url_auth_token, url_access_token, - consumer_key, consumer_secret, oauth_scope, opt_args) { - this.url_request_token = url_request_token; - this.url_auth_token = url_auth_token; - this.url_access_token = url_access_token; - this.consumer_key = consumer_key; - this.consumer_secret = consumer_secret; - this.oauth_scope = oauth_scope; - this.app_name = opt_args && opt_args['app_name'] || - "ChromeExOAuth Library"; - this.key_token = "oauth_token"; - this.key_token_secret = "oauth_token_secret"; - this.callback_page = opt_args && opt_args['callback_page'] || - "chrome_ex_oauth.html"; - this.auth_params = {}; - if (opt_args && opt_args['auth_params']) { - for (key in opt_args['auth_params']) { - if (opt_args['auth_params'].hasOwnProperty(key)) { - this.auth_params[key] = opt_args['auth_params'][key]; - } - } - } -}; - -/******************************************************************************* - * PUBLIC API METHODS - * Call these from your background page. - ******************************************************************************/ - -/** - * Initializes the OAuth helper from the background page. You must call this - * before attempting to make any OAuth calls. - * @param {Object} oauth_config Configuration parameters in a JavaScript object. - * The following parameters are recognized: - * "request_url" {String} OAuth request token URL. - * "authorize_url" {String} OAuth authorize token URL. - * "access_url" {String} OAuth access token URL. - * "consumer_key" {String} OAuth consumer key. - * "consumer_secret" {String} OAuth consumer secret. - * "scope" {String} OAuth access scope. - * "app_name" {String} Application name. - * "auth_params" {Object} Additional parameters to pass to the - * Authorization token URL. For an example, 'hd', 'hl', 'btmpl': - * http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth - * @return {ChromeExOAuth} An initialized ChromeExOAuth object. - */ -ChromeExOAuth.initBackgroundPage = function(oauth_config) { - window.chromeExOAuthConfig = oauth_config; - window.chromeExOAuth = ChromeExOAuth.fromConfig(oauth_config); - window.chromeExOAuthRedirectStarted = false; - window.chromeExOAuthRequestingAccess = false; - - var url_match = chrome.extension.getURL(window.chromeExOAuth.callback_page); - var tabs = {}; - chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { - if (changeInfo.url && - changeInfo.url.substr(0, url_match.length) === url_match && - changeInfo.url != tabs[tabId] && - window.chromeExOAuthRequestingAccess == false) { - chrome.tabs.create({ 'url' : changeInfo.url }, function(tab) { - tabs[tab.id] = tab.url; - chrome.tabs.remove(tabId); - }); - } - }); - - return window.chromeExOAuth; -}; - -/** - * Authorizes the current user with the configued API. You must call this - * before calling sendSignedRequest. - * @param {Function} callback A function to call once an access token has - * been obtained. This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - */ -ChromeExOAuth.prototype.authorize = function(callback) { - if (this.hasToken()) { - callback(this.getToken(), this.getTokenSecret()); - } else { - window.chromeExOAuthOnAuthorize = function(token, secret) { - callback(token, secret); - }; - chrome.tabs.create({ 'url' :chrome.extension.getURL(this.callback_page) }); - } -}; - -/** - * Clears any OAuth tokens stored for this configuration. Effectively a - * "logout" of the configured OAuth API. - */ -ChromeExOAuth.prototype.clearTokens = function() { - delete localStorage[this.key_token + encodeURI(this.oauth_scope)]; - delete localStorage[this.key_token_secret + encodeURI(this.oauth_scope)]; -}; - -/** - * Returns whether a token is currently stored for this configuration. - * Effectively a check to see whether the current user is "logged in" to - * the configured OAuth API. - * @return {Boolean} True if an access token exists. - */ -ChromeExOAuth.prototype.hasToken = function() { - return !!this.getToken(); -}; - -/** - * Makes an OAuth-signed HTTP request with the currently authorized tokens. - * @param {String} url The URL to send the request to. Querystring parameters - * should be omitted. - * @param {Function} callback A function to be called once the request is - * completed. This callback will be passed the following arguments: - * responseText {String} The text response. - * xhr {XMLHttpRequest} The XMLHttpRequest object which was used to - * send the request. Useful if you need to check response status - * code, etc. - * @param {Object} opt_params Additional parameters to configure the request. - * The following parameters are accepted: - * "method" {String} The HTTP method to use. Defaults to "GET". - * "body" {String} A request body to send. Defaults to null. - * "parameters" {Object} Query parameters to include in the request. - * "headers" {Object} Additional headers to include in the request. - */ -ChromeExOAuth.prototype.sendSignedRequest = function(url, callback, - opt_params) { - var method = opt_params && opt_params['method'] || 'GET'; - var body = opt_params && opt_params['body'] || null; - var params = opt_params && opt_params['parameters'] || {}; - var headers = opt_params && opt_params['headers'] || {}; - - var signedUrl = this.signURL(url, method, params); - - ChromeExOAuth.sendRequest(method, signedUrl, headers, body, function (xhr) { - if (xhr.readyState == 4) { - callback(xhr.responseText, xhr); - } - }); -}; - -/** - * Adds the required OAuth parameters to the given url and returns the - * result. Useful if you need a signed url but don't want to make an XHR - * request. - * @param {String} method The http method to use. - * @param {String} url The base url of the resource you are querying. - * @param {Object} opt_params Query parameters to include in the request. - * @return {String} The base url plus any query params plus any OAuth params. - */ -ChromeExOAuth.prototype.signURL = function(url, method, opt_params) { - var token = this.getToken(); - var secret = this.getTokenSecret(); - if (!token || !secret) { - throw new Error("No oauth token or token secret"); - } - - var params = opt_params || {}; - - var result = OAuthSimple().sign({ - action : method, - path : url, - parameters : params, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret, - oauth_secret : secret, - oauth_token: token - } - }); - - return result.signed_url; -}; - -/** - * Generates the Authorization header based on the oauth parameters. - * @param {String} url The base url of the resource you are querying. - * @param {Object} opt_params Query parameters to include in the request. - * @return {String} An Authorization header containing the oauth_* params. - */ -ChromeExOAuth.prototype.getAuthorizationHeader = function(url, method, - opt_params) { - var token = this.getToken(); - var secret = this.getTokenSecret(); - if (!token || !secret) { - throw new Error("No oauth token or token secret"); - } - - var params = opt_params || {}; - - return OAuthSimple().getHeaderString({ - action: method, - path : url, - parameters : params, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret, - oauth_secret : secret, - oauth_token: token - } - }); -}; - -/******************************************************************************* - * PRIVATE API METHODS - * Used by the library. There should be no need to call these methods directly. - ******************************************************************************/ - -/** - * Creates a new ChromeExOAuth object from the supplied configuration object. - * @param {Object} oauth_config Configuration parameters in a JavaScript object. - * The following parameters are recognized: - * "request_url" {String} OAuth request token URL. - * "authorize_url" {String} OAuth authorize token URL. - * "access_url" {String} OAuth access token URL. - * "consumer_key" {String} OAuth consumer key. - * "consumer_secret" {String} OAuth consumer secret. - * "scope" {String} OAuth access scope. - * "app_name" {String} Application name. - * "auth_params" {Object} Additional parameters to pass to the - * Authorization token URL. For an example, 'hd', 'hl', 'btmpl': - * http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth - * @return {ChromeExOAuth} An initialized ChromeExOAuth object. - */ -ChromeExOAuth.fromConfig = function(oauth_config) { - return new ChromeExOAuth( - oauth_config['request_url'], - oauth_config['authorize_url'], - oauth_config['access_url'], - oauth_config['consumer_key'], - oauth_config['consumer_secret'], - oauth_config['scope'], - { - 'app_name' : oauth_config['app_name'], - 'auth_params' : oauth_config['auth_params'] - } - ); -}; - -/** - * Initializes chrome_ex_oauth.html and redirects the page if needed to start - * the OAuth flow. Once an access token is obtained, this function closes - * chrome_ex_oauth.html. - */ -ChromeExOAuth.initCallbackPage = function() { - var background_page = chrome.extension.getBackgroundPage(); - var oauth_config = background_page.chromeExOAuthConfig; - var oauth = ChromeExOAuth.fromConfig(oauth_config); - background_page.chromeExOAuthRedirectStarted = true; - oauth.initOAuthFlow(function (token, secret) { - background_page.chromeExOAuthOnAuthorize(token, secret); - background_page.chromeExOAuthRedirectStarted = false; - chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { - chrome.tabs.remove(tabs[0].id); - }); - }); -}; - -/** - * Sends an HTTP request. Convenience wrapper for XMLHttpRequest calls. - * @param {String} method The HTTP method to use. - * @param {String} url The URL to send the request to. - * @param {Object} headers Optional request headers in key/value format. - * @param {String} body Optional body content. - * @param {Function} callback Function to call when the XMLHttpRequest's - * ready state changes. See documentation for XMLHttpRequest's - * onreadystatechange handler for more information. - */ -ChromeExOAuth.sendRequest = function(method, url, headers, body, callback) { - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function(data) { - callback(xhr, data); - } - xhr.open(method, url, true); - if (headers) { - for (var header in headers) { - if (headers.hasOwnProperty(header)) { - xhr.setRequestHeader(header, headers[header]); - } - } - } - xhr.send(body); -}; - -/** - * Decodes a URL-encoded string into key/value pairs. - * @param {String} encoded An URL-encoded string. - * @return {Object} An object representing the decoded key/value pairs found - * in the encoded string. - */ -ChromeExOAuth.formDecode = function(encoded) { - var params = encoded.split("&"); - var decoded = {}; - for (var i = 0, param; param = params[i]; i++) { - var keyval = param.split("="); - if (keyval.length == 2) { - var key = ChromeExOAuth.fromRfc3986(keyval[0]); - var val = ChromeExOAuth.fromRfc3986(keyval[1]); - decoded[key] = val; - } - } - return decoded; -}; - -/** - * Returns the current window's querystring decoded into key/value pairs. - * @return {Object} A object representing any key/value pairs found in the - * current window's querystring. - */ -ChromeExOAuth.getQueryStringParams = function() { - var urlparts = window.location.href.split("?"); - if (urlparts.length >= 2) { - var querystring = urlparts.slice(1).join("?"); - return ChromeExOAuth.formDecode(querystring); - } - return {}; -}; - -/** - * Binds a function call to a specific object. This function will also take - * a variable number of additional arguments which will be prepended to the - * arguments passed to the bound function when it is called. - * @param {Function} func The function to bind. - * @param {Object} obj The object to bind to the function's "this". - * @return {Function} A closure that will call the bound function. - */ -ChromeExOAuth.bind = function(func, obj) { - var newargs = Array.prototype.slice.call(arguments).slice(2); - return function() { - var combinedargs = newargs.concat(Array.prototype.slice.call(arguments)); - func.apply(obj, combinedargs); - }; -}; - -/** - * Encodes a value according to the RFC3986 specification. - * @param {String} val The string to encode. - */ -ChromeExOAuth.toRfc3986 = function(val){ - return encodeURIComponent(val) - .replace(/\!/g, "%21") - .replace(/\*/g, "%2A") - .replace(/'/g, "%27") - .replace(/\(/g, "%28") - .replace(/\)/g, "%29"); -}; - -/** - * Decodes a string that has been encoded according to RFC3986. - * @param {String} val The string to decode. - */ -ChromeExOAuth.fromRfc3986 = function(val){ - var tmp = val - .replace(/%21/g, "!") - .replace(/%2A/g, "*") - .replace(/%27/g, "'") - .replace(/%28/g, "(") - .replace(/%29/g, ")"); - return decodeURIComponent(tmp); -}; - -/** - * Adds a key/value parameter to the supplied URL. - * @param {String} url An URL which may or may not contain querystring values. - * @param {String} key A key - * @param {String} value A value - * @return {String} The URL with URL-encoded versions of the key and value - * appended, prefixing them with "&" or "?" as needed. - */ -ChromeExOAuth.addURLParam = function(url, key, value) { - var sep = (url.indexOf('?') >= 0) ? "&" : "?"; - return url + sep + - ChromeExOAuth.toRfc3986(key) + "=" + ChromeExOAuth.toRfc3986(value); -}; - -/** - * Stores an OAuth token for the configured scope. - * @param {String} token The token to store. - */ -ChromeExOAuth.prototype.setToken = function(token) { - localStorage[this.key_token + encodeURI(this.oauth_scope)] = token; -}; - -/** - * Retrieves any stored token for the configured scope. - * @return {String} The stored token. - */ -ChromeExOAuth.prototype.getToken = function() { - return localStorage[this.key_token + encodeURI(this.oauth_scope)]; -}; - -/** - * Stores an OAuth token secret for the configured scope. - * @param {String} secret The secret to store. - */ -ChromeExOAuth.prototype.setTokenSecret = function(secret) { - localStorage[this.key_token_secret + encodeURI(this.oauth_scope)] = secret; -}; - -/** - * Retrieves any stored secret for the configured scope. - * @return {String} The stored secret. - */ -ChromeExOAuth.prototype.getTokenSecret = function() { - return localStorage[this.key_token_secret + encodeURI(this.oauth_scope)]; -}; - -/** - * Starts an OAuth authorization flow for the current page. If a token exists, - * no redirect is needed and the supplied callback is called immediately. - * If this method detects that a redirect has finished, it grabs the - * appropriate OAuth parameters from the URL and attempts to retrieve an - * access token. If no token exists and no redirect has happened, then - * an access token is requested and the page is ultimately redirected. - * @param {Function} callback The function to call once the flow has finished. - * This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - */ -ChromeExOAuth.prototype.initOAuthFlow = function(callback) { - if (!this.hasToken()) { - var params = ChromeExOAuth.getQueryStringParams(); - if (params['chromeexoauthcallback'] == 'true') { - var oauth_token = params['oauth_token']; - var oauth_verifier = params['oauth_verifier'] - this.getAccessToken(oauth_token, oauth_verifier, callback); - } else { - var request_params = { - 'url_callback_param' : 'chromeexoauthcallback' - } - this.getRequestToken(function(url) { - window.location.href = url; - }, request_params); - } - } else { - callback(this.getToken(), this.getTokenSecret()); - } -}; - -/** - * Requests an OAuth request token. - * @param {Function} callback Function to call once the authorize URL is - * calculated. This callback will be passed the following arguments: - * url {String} The URL the user must be redirected to in order to - * approve the token. - * @param {Object} opt_args Optional arguments. The following parameters - * are accepted: - * "url_callback" {String} The URL the OAuth provider will redirect to. - * "url_callback_param" {String} A parameter to include in the callback - * URL in order to indicate to this library that a redirect has - * taken place. - */ -ChromeExOAuth.prototype.getRequestToken = function(callback, opt_args) { - if (typeof callback !== "function") { - throw new Error("Specified callback must be a function."); - } - var url = opt_args && opt_args['url_callback'] || - window && window.top && window.top.location && - window.top.location.href; - - var url_param = opt_args && opt_args['url_callback_param'] || - "chromeexoauthcallback"; - var url_callback = ChromeExOAuth.addURLParam(url, url_param, "true"); - - var result = OAuthSimple().sign({ - path : this.url_request_token, - parameters: { - "xoauth_displayname" : this.app_name, - "scope" : this.oauth_scope, - "oauth_callback" : url_callback - }, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret - } - }); - var onToken = ChromeExOAuth.bind(this.onRequestToken, this, callback); - ChromeExOAuth.sendRequest("GET", result.signed_url, null, null, onToken); -}; - -/** - * Called when a request token has been returned. Stores the request token - * secret for later use and sends the authorization url to the supplied - * callback (for redirecting the user). - * @param {Function} callback Function to call once the authorize URL is - * calculated. This callback will be passed the following arguments: - * url {String} The URL the user must be redirected to in order to - * approve the token. - * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the - * request token. - */ -ChromeExOAuth.prototype.onRequestToken = function(callback, xhr) { - if (xhr.readyState == 4) { - if (xhr.status == 200) { - var params = ChromeExOAuth.formDecode(xhr.responseText); - var token = params['oauth_token']; - this.setTokenSecret(params['oauth_token_secret']); - var url = ChromeExOAuth.addURLParam(this.url_auth_token, - "oauth_token", token); - for (var key in this.auth_params) { - if (this.auth_params.hasOwnProperty(key)) { - url = ChromeExOAuth.addURLParam(url, key, this.auth_params[key]); - } - } - callback(url); - } else { - throw new Error("Fetching request token failed. Status " + xhr.status); - } - } -}; - -/** - * Requests an OAuth access token. - * @param {String} oauth_token The OAuth request token. - * @param {String} oauth_verifier The OAuth token verifier. - * @param {Function} callback The function to call once the token is obtained. - * This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - */ -ChromeExOAuth.prototype.getAccessToken = function(oauth_token, oauth_verifier, - callback) { - if (typeof callback !== "function") { - throw new Error("Specified callback must be a function."); - } - var bg = chrome.extension.getBackgroundPage(); - if (bg.chromeExOAuthRequestingAccess == false) { - bg.chromeExOAuthRequestingAccess = true; - - var result = OAuthSimple().sign({ - path : this.url_access_token, - parameters: { - "oauth_token" : oauth_token, - "oauth_verifier" : oauth_verifier - }, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret, - oauth_secret : this.getTokenSecret(this.oauth_scope) - } - }); - - var onToken = ChromeExOAuth.bind(this.onAccessToken, this, callback); - ChromeExOAuth.sendRequest("GET", result.signed_url, null, null, onToken); - } -}; - -/** - * Called when an access token has been returned. Stores the access token and - * access token secret for later use and sends them to the supplied callback. - * @param {Function} callback The function to call once the token is obtained. - * This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the - * access token. - */ -ChromeExOAuth.prototype.onAccessToken = function(callback, xhr) { - if (xhr.readyState == 4) { - var bg = chrome.extension.getBackgroundPage(); - if (xhr.status == 200) { - var params = ChromeExOAuth.formDecode(xhr.responseText); - var token = params["oauth_token"]; - var secret = params["oauth_token_secret"]; - this.setToken(token); - this.setTokenSecret(secret); - bg.chromeExOAuthRequestingAccess = false; - callback(token, secret); - } else { - bg.chromeExOAuthRequestingAccess = false; - throw new Error("Fetching access token failed with status " + xhr.status); - } - } -}; -
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauthsimple.js b/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauthsimple.js deleted file mode 100644 index af0fe8a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/chrome_ex_oauthsimple.js +++ /dev/null
@@ -1,458 +0,0 @@ -/* OAuthSimple - * A simpler version of OAuth - * - * author: jr conlin - * mail: src@anticipatr.com - * copyright: unitedHeroes.net - * version: 1.0 - * url: http://unitedHeroes.net/OAuthSimple - * - * Copyright (c) 2009, unitedHeroes.net - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the unitedHeroes.net nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -var OAuthSimple; - -if (OAuthSimple === undefined) -{ - /* Simple OAuth - * - * This class only builds the OAuth elements, it does not do the actual - * transmission or reception of the tokens. It does not validate elements - * of the token. It is for client use only. - * - * api_key is the API key, also known as the OAuth consumer key - * shared_secret is the shared secret (duh). - * - * Both the api_key and shared_secret are generally provided by the site - * offering OAuth services. You need to specify them at object creation - * because nobody <explative>ing uses OAuth without that minimal set of - * signatures. - * - * If you want to use the higher order security that comes from the - * OAuth token (sorry, I don't provide the functions to fetch that because - * sites aren't horribly consistent about how they offer that), you need to - * pass those in either with .setTokensAndSecrets() or as an argument to the - * .sign() or .getHeaderString() functions. - * - * Example: - <code> - var oauthObject = OAuthSimple().sign({path:'http://example.com/rest/', - parameters: 'foo=bar&gorp=banana', - signatures:{ - api_key:'12345abcd', - shared_secret:'xyz-5309' - }}); - document.getElementById('someLink').href=oauthObject.signed_url; - </code> - * - * that will sign as a "GET" using "SHA1-MAC" the url. If you need more than - * that, read on, McDuff. - */ - - /** OAuthSimple creator - * - * Create an instance of OAuthSimple - * - * @param api_key {string} The API Key (sometimes referred to as the consumer key) This value is usually supplied by the site you wish to use. - * @param shared_secret (string) The shared secret. This value is also usually provided by the site you wish to use. - */ - OAuthSimple = function (consumer_key,shared_secret) - { -/* if (api_key == undefined) - throw("Missing argument: api_key (oauth_consumer_key) for OAuthSimple. This is usually provided by the hosting site."); - if (shared_secret == undefined) - throw("Missing argument: shared_secret (shared secret) for OAuthSimple. This is usually provided by the hosting site."); -*/ this._secrets={}; - this._parameters={}; - - // General configuration options. - if (consumer_key !== undefined) { - this._secrets['consumer_key'] = consumer_key; - } - if (shared_secret !== undefined) { - this._secrets['shared_secret'] = shared_secret; - } - this._default_signature_method= "HMAC-SHA1"; - this._action = "GET"; - this._nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - - this.reset = function() { - this._parameters={}; - this._path=undefined; - return this; - }; - - /** set the parameters either from a hash or a string - * - * @param {string,object} List of parameters for the call, this can either be a URI string (e.g. "foo=bar&gorp=banana" or an object/hash) - */ - this.setParameters = function (parameters) { - if (parameters === undefined) { - parameters = {}; - } - if (typeof(parameters) == 'string') { - parameters=this._parseParameterString(parameters); - } - this._parameters = parameters; - if (this._parameters['oauth_nonce'] === undefined) { - this._getNonce(); - } - if (this._parameters['oauth_timestamp'] === undefined) { - this._getTimestamp(); - } - if (this._parameters['oauth_method'] === undefined) { - this.setSignatureMethod(); - } - if (this._parameters['oauth_consumer_key'] === undefined) { - this._getApiKey(); - } - if(this._parameters['oauth_token'] === undefined) { - this._getAccessToken(); - } - - return this; - }; - - /** convienence method for setParameters - * - * @param parameters {string,object} See .setParameters - */ - this.setQueryString = function (parameters) { - return this.setParameters(parameters); - }; - - /** Set the target URL (does not include the parameters) - * - * @param path {string} the fully qualified URI (excluding query arguments) (e.g "http://example.org/foo") - */ - this.setURL = function (path) { - if (path == '') { - throw ('No path specified for OAuthSimple.setURL'); - } - this._path = path; - return this; - }; - - /** convienence method for setURL - * - * @param path {string} see .setURL - */ - this.setPath = function(path){ - return this.setURL(path); - }; - - /** set the "action" for the url, (e.g. GET,POST, DELETE, etc.) - * - * @param action {string} HTTP Action word. - */ - this.setAction = function(action) { - if (action === undefined) { - action="GET"; - } - action = action.toUpperCase(); - if (action.match('[^A-Z]')) { - throw ('Invalid action specified for OAuthSimple.setAction'); - } - this._action = action; - return this; - }; - - /** set the signatures (as well as validate the ones you have) - * - * @param signatures {object} object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:} - */ - this.setTokensAndSecrets = function(signatures) { - if (signatures) - { - for (var i in signatures) { - this._secrets[i] = signatures[i]; - } - } - // Aliases - if (this._secrets['api_key']) { - this._secrets.consumer_key = this._secrets.api_key; - } - if (this._secrets['access_token']) { - this._secrets.oauth_token = this._secrets.access_token; - } - if (this._secrets['access_secret']) { - this._secrets.oauth_secret = this._secrets.access_secret; - } - // Gauntlet - if (this._secrets.consumer_key === undefined) { - throw('Missing required consumer_key in OAuthSimple.setTokensAndSecrets'); - } - if (this._secrets.shared_secret === undefined) { - throw('Missing required shared_secret in OAuthSimple.setTokensAndSecrets'); - } - if ((this._secrets.oauth_token !== undefined) && (this._secrets.oauth_secret === undefined)) { - throw('Missing oauth_secret for supplied oauth_token in OAuthSimple.setTokensAndSecrets'); - } - return this; - }; - - /** set the signature method (currently only Plaintext or SHA-MAC1) - * - * @param method {string} Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now) - */ - this.setSignatureMethod = function(method) { - if (method === undefined) { - method = this._default_signature_method; - } - //TODO: accept things other than PlainText or SHA-MAC1 - if (method.toUpperCase().match(/(PLAINTEXT|HMAC-SHA1)/) === undefined) { - throw ('Unknown signing method specified for OAuthSimple.setSignatureMethod'); - } - this._parameters['oauth_signature_method']= method.toUpperCase(); - return this; - }; - - /** sign the request - * - * note: all arguments are optional, provided you've set them using the - * other helper functions. - * - * @param args {object} hash of arguments for the call - * {action:, path:, parameters:, method:, signatures:} - * all arguments are optional. - */ - this.sign = function (args) { - if (args === undefined) { - args = {}; - } - // Set any given parameters - if(args['action'] !== undefined) { - this.setAction(args['action']); - } - if (args['path'] !== undefined) { - this.setPath(args['path']); - } - if (args['method'] !== undefined) { - this.setSignatureMethod(args['method']); - } - this.setTokensAndSecrets(args['signatures']); - if (args['parameters'] !== undefined){ - this.setParameters(args['parameters']); - } - // check the parameters - var normParams = this._normalizedParameters(); - this._parameters['oauth_signature']=this._generateSignature(normParams); - return { - parameters: this._parameters, - signature: this._oauthEscape(this._parameters['oauth_signature']), - signed_url: this._path + '?' + this._normalizedParameters(), - header: this.getHeaderString() - }; - }; - - /** Return a formatted "header" string - * - * NOTE: This doesn't set the "Authorization: " prefix, which is required. - * I don't set it because various set header functions prefer different - * ways to do that. - * - * @param args {object} see .sign - */ - this.getHeaderString = function(args) { - if (this._parameters['oauth_signature'] === undefined) { - this.sign(args); - } - - var result = 'OAuth '; - for (var pName in this._parameters) - { - if (!pName.match(/^oauth/)) { - continue; - } - if ((this._parameters[pName]) instanceof Array) - { - var pLength = this._parameters[pName].length; - for (var j=0;j<pLength;j++) - { - result += pName +'="'+this._oauthEscape(this._parameters[pName][j])+'" '; - } - } - else - { - result += pName + '="'+this._oauthEscape(this._parameters[pName])+'" '; - } - } - return result; - }; - - // Start Private Methods. - - /** convert the parameter string into a hash of objects. - * - */ - this._parseParameterString = function(paramString){ - var elements = paramString.split('&'); - var result={}; - for(var element=elements.shift();element;element=elements.shift()) - { - var keyToken=element.split('='); - var value=''; - if (keyToken[1]) { - value=decodeURIComponent(keyToken[1]); - } - if(result[keyToken[0]]){ - if (!(result[keyToken[0]] instanceof Array)) - { - result[keyToken[0]] = Array(result[keyToken[0]],value); - } - else - { - result[keyToken[0]].push(value); - } - } - else - { - result[keyToken[0]]=value; - } - } - return result; - }; - - this._oauthEscape = function(string) { - if (string === undefined) { - return ""; - } - if (string instanceof Array) - { - throw('Array passed to _oauthEscape'); - } - return encodeURIComponent(string).replace(/\!/g, "%21"). - replace(/\*/g, "%2A"). - replace(/'/g, "%27"). - replace(/\(/g, "%28"). - replace(/\)/g, "%29"); - }; - - this._getNonce = function (length) { - if (length === undefined) { - length=5; - } - var result = ""; - var cLength = this._nonce_chars.length; - for (var i = 0; i < length;i++) { - var rnum = Math.floor(Math.random() *cLength); - result += this._nonce_chars.substring(rnum,rnum+1); - } - this._parameters['oauth_nonce']=result; - return result; - }; - - this._getApiKey = function() { - if (this._secrets.consumer_key === undefined) { - throw('No consumer_key set for OAuthSimple.'); - } - this._parameters['oauth_consumer_key']=this._secrets.consumer_key; - return this._parameters.oauth_consumer_key; - }; - - this._getAccessToken = function() { - if (this._secrets['oauth_secret'] === undefined) { - return ''; - } - if (this._secrets['oauth_token'] === undefined) { - throw('No oauth_token (access_token) set for OAuthSimple.'); - } - this._parameters['oauth_token'] = this._secrets.oauth_token; - return this._parameters.oauth_token; - }; - - this._getTimestamp = function() { - var d = new Date(); - var ts = Math.floor(d.getTime()/1000); - this._parameters['oauth_timestamp'] = ts; - return ts; - }; - - this.b64_hmac_sha1 = function(k,d,_p,_z){ - // heavily optimized and compressed version of http://pajhome.org.uk/crypt/md5/sha1.js - // _p = b64pad, _z = character size; not used here but I left them available just in case - if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d); - } - - - this._normalizedParameters = function() { - var elements = new Array(); - var paramNames = []; - var ra =0; - for (var paramName in this._parameters) - { - if (ra++ > 1000) { - throw('runaway 1'); - } - paramNames.unshift(paramName); - } - paramNames = paramNames.sort(); - pLen = paramNames.length; - for (var i=0;i<pLen; i++) - { - paramName=paramNames[i]; - //skip secrets. - if (paramName.match(/\w+_secret/)) { - continue; - } - if (this._parameters[paramName] instanceof Array) - { - var sorted = this._parameters[paramName].sort(); - var spLen = sorted.length; - for (var j = 0;j<spLen;j++){ - if (ra++ > 1000) { - throw('runaway 1'); - } - elements.push(this._oauthEscape(paramName) + '=' + - this._oauthEscape(sorted[j])); - } - continue; - } - elements.push(this._oauthEscape(paramName) + '=' + - this._oauthEscape(this._parameters[paramName])); - } - return elements.join('&'); - }; - - this._generateSignature = function() { - - var secretKey = this._oauthEscape(this._secrets.shared_secret)+'&'+ - this._oauthEscape(this._secrets.oauth_secret); - if (this._parameters['oauth_signature_method'] == 'PLAINTEXT') - { - return secretKey; - } - if (this._parameters['oauth_signature_method'] == 'HMAC-SHA1') - { - var sigString = this._oauthEscape(this._action)+'&'+this._oauthEscape(this._path)+'&'+this._oauthEscape(this._normalizedParameters()); - return this.b64_hmac_sha1(secretKey,sigString); - } - return null; - }; - - return this; - }; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-128.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-128.gif deleted file mode 100644 index e85c4fd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-128.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-32.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-32.gif deleted file mode 100644 index da38b31..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-32.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-48.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-48.gif deleted file mode 100644 index dd54d63..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/docs_spreadsheets-48.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/audio.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/audio.gif deleted file mode 100644 index 997d82d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/audio.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/document.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/document.gif deleted file mode 100644 index f202ab19..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/document.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/file.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/file.gif deleted file mode 100644 index 9374dd2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/file.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/folder.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/folder.gif deleted file mode 100644 index f6bc4f1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/folder.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/form.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/form.gif deleted file mode 100644 index e7b521d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/form.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/pdf.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/pdf.gif deleted file mode 100644 index 136eb0b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/pdf.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/presentation.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/presentation.gif deleted file mode 100644 index cede720..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/presentation.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/spreadsheet.gif b/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/spreadsheet.gif deleted file mode 100644 index ec3954f6..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/img/icons/spreadsheet.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/js/jquery-1.4.1.min.js b/chrome/common/extensions/docs/examples/extensions/gdocs/js/jquery-1.4.1.min.js deleted file mode 100644 index 0c7294c9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/js/jquery-1.4.1.min.js +++ /dev/null
@@ -1,152 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.1 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon Jan 25 19:43:33 2010 -0500 - */ -(function(z,v){function la(){if(!c.isReady){try{r.documentElement.doScroll("left")}catch(a){setTimeout(la,1);return}c.ready()}}function Ma(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var n in b)X(a,n,b[n],f,e,d);return a}if(d!==v){f=!i&&f&&c.isFunction(d);for(n=0;n<j;n++)e(a[n],b,f?d.call(a[n],n,e(a[n],b)):d,i);return a}return j? -e(a[0],b):null}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function ma(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function na(a){var b,d=[],f=[],e=arguments,i,j,n,o,m,s,x=c.extend({},c.data(this,"events").live);if(!(a.button&&a.type==="click")){for(o in x){j=x[o];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete x[o]}i=c(a.target).closest(f, -a.currentTarget);m=0;for(s=i.length;m<s;m++)for(o in x){j=x[o];n=i[m].elem;f=null;if(i[m].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==n)d.push({elem:n,fn:j})}}m=0;for(s=d.length;m<s;m++){i=d[m];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}}function oa(a,b){return"live."+(a?a+".":"")+b.replace(/\./g,"`").replace(/ /g,"&")}function pa(a){return!a||!a.parentNode||a.parentNode.nodeType=== -11}function qa(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ra(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0&&(c.support.checkClone||!sa.test(a[0]))){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:r;f=b.createDocumentFragment(); -c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=i?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(ta.concat.apply([],ta.slice(0,b)),function(){d[this]=a});return d}function ua(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Na=z.jQuery,Oa=z.$,r=z.document,S,Pa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Qa=/^.[^:#\[\.,]*$/,Ra=/\S/,Sa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Ta=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,O=navigator.userAgent, -va=false,P=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,Q=Array.prototype.slice,wa=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Pa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:r;if(a=Ta.exec(a))if(c.isPlainObject(b)){a=[r.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ra([d[1]], -[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=r.getElementById(d[2])){if(b.id!==d[2])return S.find(a);this.length=1;this[0]=b}this.context=r;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=r;a=r.getElementsByTagName(a)}else return!b||b.jquery?(b||S).find(a):c(b).find(a);else if(c.isFunction(a))return S.ready(a);if(a.selector!==v){this.selector=a.selector;this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a, -this)},selector:"",jquery:"1.4.1",length:0,size:function(){return this.length},toArray:function(){return Q.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=0;ba.apply(this,a);return this},each:function(a,b){return c.each(this, -a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(r,c);else P&&P.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(Q.apply(this,arguments),"slice",Q.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice}; -c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,n;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];n=e[i];if(a!==n)if(f&&n&&(c.isPlainObject(n)||c.isArray(n))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(n)?[]:{};a[i]=c.extend(f,j,n)}else if(n!==v)a[i]=n}return a};c.extend({noConflict:function(a){z.$= -Oa;if(a)z.jQuery=Na;return c},isReady:false,ready:function(){if(!c.isReady){if(!r.body)return setTimeout(c.ready,13);c.isReady=true;if(P){for(var a,b=0;a=P[b++];)a.call(r,c);P=null}c.fn.triggerHandler&&c(r).triggerHandler("ready")}},bindReady:function(){if(!va){va=true;if(r.readyState==="complete")return c.ready();if(r.addEventListener){r.addEventListener("DOMContentLoaded",L,false);z.addEventListener("load",c.ready,false)}else if(r.attachEvent){r.attachEvent("onreadystatechange",L);z.attachEvent("onload", -c.ready);var a=false;try{a=z.frameElement==null}catch(b){}r.documentElement.doScroll&&a&&la()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===v||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false; -return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return z.JSON&&z.JSON.parse?z.JSON.parse(a):(new Function("return "+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Ra.test(a)){var b=r.getElementsByTagName("head")[0]|| -r.documentElement,d=r.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(r.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===v||c.isFunction(a);if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d= -a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Sa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!== -v;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=v}else if(b&&!c.isFunction(b)){d=b;b=v}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b}, -uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});O=c.uaMatch(O);if(O.browser){c.browser[O.browser]=true;c.browser.version=O.version}if(c.browser.webkit)c.browser.safari=true;if(wa)c.inArray=function(a,b){return wa.call(b,a)};S=c(r);if(r.addEventListener)L=function(){r.removeEventListener("DOMContentLoaded", -L,false);c.ready()};else if(r.attachEvent)L=function(){if(r.readyState==="complete"){r.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=r.documentElement,b=r.createElement("script"),d=r.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support= -{leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:r.createElement("select").appendChild(r.createElement("option")).selected,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null}; -b.type="text/javascript";try{b.appendChild(r.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,a.firstChild);if(z[f]){c.support.scriptEval=true;delete z[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function n(){c.support.noCloneEvent=false;d.detachEvent("onclick",n)});d.cloneNode(true).fireEvent("onclick")}d=r.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=r.createDocumentFragment();a.appendChild(d.firstChild); -c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var n=r.createElement("div");n.style.width=n.style.paddingLeft="1px";r.body.appendChild(n);c.boxModel=c.support.boxModel=n.offsetWidth===2;r.body.removeChild(n).style.display="none"});a=function(n){var o=r.createElement("div");n="on"+n;var m=n in o;if(!m){o.setAttribute(n,"return;");m=typeof o[n]==="function"}return m};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props= -{"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ua=0,xa={},Va={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var f=a[G],e=c.cache;if(!b&&!f)return null;f||(f=++Ua);if(typeof b==="object"){a[G]=f;e=e[f]=c.extend(true, -{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Va:(e[f]={});if(d!==v){a[G]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[G]}catch(i){a.removeAttribute&&a.removeAttribute(G)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this, -a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===v){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===v&&this.length)f=c.data(this[0],a);return f===v&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d); -return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===v)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]|| -a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var ya=/[\n\t]/g,ca=/\s+/,Wa=/\r/g,Xa=/href|src|style/,Ya=/(button|input)/i,Za=/(button|input|object|select|textarea)/i,$a=/^(a|area)$/i,za=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(o){var m= -c(this);m.addClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,n=b.length;j<n;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=c(this);m.removeClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string"||a===v)for(var b=(a||"").split(ca), -d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(ya," "),j=0,n=b.length;j<n;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),n=b,o= -a.split(ca);e=o[i++];){n=f?n:!j.hasClass(e);j[n?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(ya," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===v){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value|| -{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(za.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Wa,"")}return v}var n=c.isFunction(a);return this.each(function(o){var m=c(this),s=a;if(this.nodeType===1){if(n)s=a.call(this,o,m.val()); -if(typeof s==="number")s+="";if(c.isArray(s)&&za.test(this.type))this.checked=c.inArray(m.val(),s)>=0;else if(c.nodeName(this,"select")){var x=c.makeArray(s);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),x)>=0});if(!x.length)this.selectedIndex=-1}else this.value=s}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return v;if(f&&b in c.attrFn)return c(a)[b](d); -f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==v;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Xa.test(b);if(b in a&&f&&!i){if(e){b==="type"&&Ya.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Za.test(a.nodeName)||$a.test(a.nodeName)&&a.href?0:v;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText= -""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?v:a}return c.style(a,b,d)}});var ab=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==z&&!a.frameElement)a=z;if(!d.guid)d.guid=c.guid++;if(f!==v){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j= -function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):v};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var n,o=0;n=b[o++];){var m=n.split(".");n=m.shift();if(o>1){d=c.proxy(d);if(f!==v)d.data=f}d.type=m.slice(0).sort().join(".");var s=e[n],x=this.special[n]||{};if(!s){s=e[n]={};if(!x.setup||x.setup.call(a,f,m,d)===false)if(a.addEventListener)a.addEventListener(n,i,false);else a.attachEvent&&a.attachEvent("on"+n,i)}if(x.add)if((m=x.add.call(a, -d,f,m,s))&&c.isFunction(m)){m.guid=m.guid||d.guid;m.data=m.data||d.data;m.type=m.type||d.type;d=m}s[d.guid]=d;this.global[n]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===v||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);for(var n=0;i=b[n++];){var o=i.split(".");i=o.shift();var m=!o.length,s=c.map(o.slice(0).sort(),ab);s=new RegExp("(^|\\.)"+ -s.join("\\.(?:.*\\.)?")+"(\\.|$)");var x=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var A in f[i])if(m||s.test(f[i][A].type))delete f[i][A];x.remove&&x.remove.call(a,o,j);for(e in f[i])break;if(!e){if(!x.teardown||x.teardown.call(a,o)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(A=c.data(a,"handle"))A.elem=null;c.removeData(a, -"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return v;a.result=v;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d, -b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(i){}if(!a.isPropagationStopped()&&f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){d=a.target;var j;if(!(c.nodeName(d,"a")&&e==="click")&&!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){try{if(d[e]){if(j=d["on"+e])d["on"+e]=null;this.triggered=true;d[e]()}}catch(n){}if(j)d["on"+e]=j;this.triggered=false}}},handle:function(a){var b, -d;a=arguments[0]=c.event.fix(a||z.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==v){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), -fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||r;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=r.documentElement;d=r.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop|| -d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==v)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;b.liveProxy=a;c.event.add(this,b.live,na,b)},remove:function(a){if(a.length){var b= -0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],na)}},special:{}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true}; -c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y};var Aa=function(a){for(var b= -a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ba=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ba:Aa,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ba:Aa)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!== -"form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return ma("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return ma("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this, -"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var da=/textarea|input|select/i;function Ca(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ea(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Ca(d);if(a.type!=="focusout"|| -d.type!=="radio")c.data(d,"_change_data",e);if(!(f===v||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}}c.event.special.change={filters:{focusout:ea,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ea.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ea.call(this,a)},beforeactivate:function(a){a= -a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Ca(a))}},setup:function(a,b,d){for(var f in T)c.event.add(this,f+".specialChange."+d.guid,T[f]);return da.test(this.nodeName)},remove:function(a,b){for(var d in T)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),T[d]);return da.test(this.nodeName)}};var T=c.event.special.change.filters}r.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this, -f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){e=f;f=v}var j=b==="one"?c.proxy(e,function(n){c(this).unbind(n,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a, -b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+ -a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e){var i,j=0;if(c.isFunction(f)){e=f;f=v}for(d=(d||"").split(/\s+/);(i=d[j++])!=null;){i=i==="focus"?"focusin":i==="blur"?"focusout":i==="hover"?d.push("mouseleave")&&"mouseenter":i;b==="live"?c(this.context).bind(oa(i,this.selector),{data:f,selector:this.selector, -live:i},e):c(this.context).unbind(oa(i,this.selector),e?{guid:e.guid+this.selector+i}:null)}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});z.attachEvent&&!z.addEventListener&&z.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); -(function(){function a(g){for(var h="",k,l=0;g[l];l++){k=g[l];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===k){y=l[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=k;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}l[q]=y}}}function d(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache=== -k){y=l[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=k;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(o.filter(h,[t]).length>0){y=t;break}}t=t[g]}l[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,i=Object.prototype.toString,j=false,n=true;[0,0].sort(function(){n=false;return 0});var o=function(g,h,k,l){k=k||[];var q=h=h||r;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g|| -typeof g!=="string")return k;for(var p=[],u,t,y,R,H=true,M=w(h),I=g;(f.exec(""),u=f.exec(I))!==null;){I=u[3];p.push(u[1]);if(u[2]){R=u[3];break}}if(p.length>1&&s.exec(g))if(p.length===2&&m.relative[p[0]])t=fa(p[0]+p[1],h);else for(t=m.relative[p[0]]?[h]:o(p.shift(),h);p.length;){g=p.shift();if(m.relative[g])g+=p.shift();t=fa(g,t)}else{if(!l&&p.length>1&&h.nodeType===9&&!M&&m.match.ID.test(p[0])&&!m.match.ID.test(p[p.length-1])){u=o.find(p.shift(),h,M);h=u.expr?o.filter(u.expr,u.set)[0]:u.set[0]}if(h){u= -l?{expr:p.pop(),set:A(l)}:o.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=u.expr?o.filter(u.expr,u.set):u.set;if(p.length>0)y=A(t);else H=false;for(;p.length;){var D=p.pop();u=D;if(m.relative[D])u=p.pop();else D="";if(u==null)u=h;m.relative[D](y,u,M)}}else y=[]}y||(y=t);y||o.error(D||g);if(i.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))k.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&& -y[g].nodeType===1&&k.push(t[g]);else k.push.apply(k,y);else A(y,k);if(R){o(R,q,k,l);o.uniqueSort(k)}return k};o.uniqueSort=function(g){if(C){j=n;g.sort(C);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};o.matches=function(g,h){return o(g,null,null,h)};o.find=function(g,h,k){var l,q;if(!g)return[];for(var p=0,u=m.order.length;p<u;p++){var t=m.order[p];if(q=m.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");l=m.find[t](q, -h,k);if(l!=null){g=g.replace(m.match[t],"");break}}}}l||(l=h.getElementsByTagName("*"));return{set:l,expr:g}};o.filter=function(g,h,k,l){for(var q=g,p=[],u=h,t,y,R=h&&h[0]&&w(h[0]);g&&h.length;){for(var H in m.filter)if((t=m.leftMatch[H].exec(g))!=null&&t[2]){var M=m.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(u===p)p=[];if(m.preFilter[H])if(t=m.preFilter[H](t,u,k,p,l,R)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=u[U])!=null;U++)if(D){I=M(D,t,U,u);var Da= -l^!!I;if(k&&I!=null)if(Da)y=true;else u[U]=false;else if(Da){p.push(D);y=true}}if(I!==v){k||(u=p);g=g.replace(m.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)o.error(g);else break;q=g}return u};o.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var m=o.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, -TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,h){var k=typeof h==="string",l=k&&!/\W/.test(h);k=k&&!l;if(l)h=h.toLowerCase();l=0;for(var q=g.length, -p;l<q;l++)if(p=g[l]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[l]=k||p&&p.nodeName.toLowerCase()===h?p||false:p===h}k&&o.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var l=0,q=g.length;l<q;l++){var p=g[l];if(p){k=p.parentNode;g[l]=k.nodeName.toLowerCase()===h?k:false}}}else{l=0;for(q=g.length;l<q;l++)if(p=g[l])g[l]=k?p.parentNode:p.parentNode===h;k&&o.filter(h,g,true)}},"":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p= -h=h.toLowerCase();q=b}q("parentNode",h,l,g,p,k)},"~":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,l,g,p,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];h=h.getElementsByName(g[1]);for(var l=0,q=h.length;l<q;l++)h[l].getAttribute("name")===g[1]&&k.push(h[l]);return k.length===0?null:k}}, -TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,l,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var u;(u=h[p])!=null;p++)if(u)if(q^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||l.push(u);else if(k)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&& -"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,l,q,p){h=g[1].replace(/\\/g,"");if(!p&&m.attrMap[h])g[1]=m.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,l,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=o(g[3],null,null,h);else{g=o.filter(g[3],h,k,true^q);k||l.push.apply(l,g);return false}else if(m.match.POS.test(g[0])||m.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true); -return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!o(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"=== -g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,h){return h===0},last:function(g,h,k,l){return h===l.length-1},even:function(g,h){return h%2=== -0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,l){var q=h[1],p=m.filters[q];if(p)return p(g,k,h,l);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=h[3];k=0;for(l=h.length;k<l;k++)if(h[k]===g)return false;return true}else o.error("Syntax error, unrecognized expression: "+ -q)},CHILD:function(g,h){var k=h[1],l=g;switch(k){case "only":case "first":for(;l=l.previousSibling;)if(l.nodeType===1)return false;if(k==="first")return true;l=g;case "last":for(;l=l.nextSibling;)if(l.nodeType===1)return false;return true;case "nth":k=h[2];var q=h[3];if(k===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var u=0;for(l=p.firstChild;l;l=l.nextSibling)if(l.nodeType===1)l.nodeIndex=++u;p.sizcache=h}g=g.nodeIndex-q;return k===0?g===0:g%k===0&&g/k>= -0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=m.attrHandle[k]?m.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var l=h[2];h=h[4];return g==null?l==="!=":l==="="?k===h:l==="*="?k.indexOf(h)>=0:l==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:l==="!="?k!==h:l==="^="? -k.indexOf(h)===0:l==="$="?k.substr(k.length-h.length)===h:l==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,l){var q=m.setFilters[h[2]];if(q)return q(g,k,h,l)}}},s=m.match.POS;for(var x in m.match){m.match[x]=new RegExp(m.match[x].source+/(?![^\[]*\])(?![^\(]*\))/.source);m.leftMatch[x]=new RegExp(/(^(?:.|\r|\n)*?)/.source+m.match[x].source.replace(/\\(\d+)/g,function(g,h){return"\\"+(h-0+1)}))}var A=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g}; -try{Array.prototype.slice.call(r.documentElement.childNodes,0)}catch(B){A=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,l=g.length;k<l;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var C;if(r.documentElement.compareDocumentPosition)C=function(g,h){if(!g.compareDocumentPosition||!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g=== -h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in r.documentElement)C=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(r.createRange)C=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),l=h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);l.setStart(h,0);l.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END, -l);if(g===0)j=true;return g};(function(){var g=r.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=r.documentElement;k.insertBefore(g,k.firstChild);if(r.getElementById(h)){m.find.ID=function(l,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(l[1]))?q.id===l[1]||typeof q.getAttributeNode!=="undefined"&&q.getAttributeNode("id").nodeValue===l[1]?[q]:v:[]};m.filter.ID=function(l,q){var p=typeof l.getAttributeNode!=="undefined"&&l.getAttributeNode("id"); -return l.nodeType===1&&p&&p.nodeValue===q}}k.removeChild(g);k=g=null})();(function(){var g=r.createElement("div");g.appendChild(r.createComment(""));if(g.getElementsByTagName("*").length>0)m.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var l=0;k[l];l++)k[l].nodeType===1&&h.push(k[l]);k=h}return k};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")m.attrHandle.href=function(h){return h.getAttribute("href", -2)};g=null})();r.querySelectorAll&&function(){var g=o,h=r.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){o=function(l,q,p,u){q=q||r;if(!u&&q.nodeType===9&&!w(q))try{return A(q.querySelectorAll(l),p)}catch(t){}return g(l,q,p,u)};for(var k in g)o[k]=g[k];h=null}}();(function(){var g=r.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length=== -0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){m.order.splice(1,0,"CLASS");m.find.CLASS=function(h,k,l){if(typeof k.getElementsByClassName!=="undefined"&&!l)return k.getElementsByClassName(h[1])};g=null}}})();var E=r.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,h){return g!==h&&(g.contains?g.contains(h):true)},w=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},fa=function(g,h){var k=[], -l="",q;for(h=h.nodeType?[h]:h;q=m.match.PSEUDO.exec(g);){l+=q[0];g=g.replace(m.match.PSEUDO,"")}g=m.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)o(g,h[q],k);return o.filter(l,k)};c.find=o;c.expr=o.selectors;c.expr[":"]=c.expr.filters;c.unique=o.uniqueSort;c.getText=a;c.isXMLDoc=w;c.contains=E})();var bb=/Until$/,cb=/^(?:parents|prevUntil|prevAll)/,db=/,/;Q=Array.prototype.slice;var Ea=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a, -function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Qa.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d= -0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ea(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ea(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i={},j;if(f&&a.length){e=0;for(var n=a.length;e<n;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)> --1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var o=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(m,s){for(;s&&s.ownerDocument&&s!==b;){if(o?o.index(s)>-1:c(s).is(a))return s;s=s.parentNode}return null})},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(), -a);return this.pushStack(pa(a[0])||pa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")}, -nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);bb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e): -e;if((this.length>1||db.test(f))&&cb.test(a))e=e.reverse();return this.pushStack(e,a,Q.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===v||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!== -b&&d.push(a);return d}});var Fa=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ga=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,sa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ia=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"], -col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==v)return this.empty().append((this[0]&&this[0].ownerDocument||r).createTextNode(a));return c.getText(this)}, -wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length? -d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments, -false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&& -!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Fa,"").replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){qa(this,b);qa(this.find("*"),b.find("*"))}return b},html:function(a){if(a===v)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Fa,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(Ha.exec(a)|| -["",""])[1].toLowerCase()]){a=a.replace(Ga,Ia);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this, -b,f))});else a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(s){return c.nodeName(s,"table")?s.getElementsByTagName("tbody")[0]||s.appendChild(s.ownerDocument.createElement("tbody")):s}var e,i,j=a[0],n=[];if(!c.support.checkClone&&arguments.length===3&&typeof j=== -"string"&&sa.test(j))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(j))return this.each(function(s){var x=c(this);a[0]=j.call(this,s,b?x.html():v);x.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ra(a,this,n);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var o=0,m=this.length;o<m;o++)d.call(b?f(this[o],i):this[o],e.cacheable||this.length>1||o>0?e.fragment.cloneNode(true):e.fragment)}n&&c.each(n, -Ma)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){c.cleanData(this.getElementsByTagName("*"));c.cleanData([this])}this.parentNode&& -this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&c.cleanData(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||r;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||r;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j=== -"string"){j=j.replace(Ga,Ia);var n=(Ha.exec(j)||["",""])[1].toLowerCase(),o=F[n]||F._default,m=o[0];i=b.createElement("div");for(i.innerHTML=o[1]+j+o[2];m--;)i=i.lastChild;if(!c.support.tbody){m=fb.test(j);n=n==="table"&&!m?i.firstChild&&i.firstChild.childNodes:o[1]==="<table>"&&!m?i.childNodes:[];for(o=n.length-1;o>=0;--o)c.nodeName(n[o],"tbody")&&!n[o].childNodes.length&&n[o].parentNode.removeChild(n[o])}!c.support.leadingWhitespace&&V.test(j)&&i.insertBefore(b.createTextNode(V.exec(j)[0]),i.firstChild); -j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()==="text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e},cleanData:function(a){for(var b=0,d;(d=a[b])!=null;b++){c.event.remove(d);c.removeData(d)}}});var hb=/z-?index|font-?weight|opacity|zoom|line-?height/i, -Ja=/alpha\([^)]*\)/,Ka=/opacity=([^)]*)/,ga=/float/i,ha=/-([a-z])/ig,ib=/([A-Z])/g,jb=/^-?\d+(?:px)?$/i,kb=/^-?\d/,lb={position:"absolute",visibility:"hidden",display:"block"},mb=["Left","Right"],nb=["Top","Bottom"],ob=r.defaultView&&r.defaultView.getComputedStyle,La=c.support.cssFloat?"cssFloat":"styleFloat",ia=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===v)return c.curCSS(d,f);if(typeof e==="number"&&!hb.test(f))e+="px";c.style(d,f,e)})}; -c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return v;if((b==="width"||b==="height")&&parseFloat(d)<0)d=v;var f=a.style||a,e=d!==v;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ja.test(a)?a.replace(Ja,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ka.exec(f.filter)[1])/100+"":""}if(ga.test(b))b=La;b=b.replace(ha,ia);if(e)f[b]=d;return f[b]},css:function(a, -b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?mb:nb;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,lb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&& -a.currentStyle){f=Ka.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ga.test(b))b=La;if(!d&&e&&e[b])f=e[b];else if(ob){if(ga.test(b))b="float";b=b.replace(ib,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ha,ia);f=a.currentStyle[b]||a.currentStyle[d];if(!jb.test(f)&&kb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left= -a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var pb= -J(),qb=/<script(.|\s)*?\/script>/gi,rb=/select|textarea/i,sb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ja=/\?/,tb=/(\?|&)_=.*?(&|$)/,ub=/^(\w+:)?\/\/([^\/?#]+)/,vb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b= -c.param(b,c.ajaxSettings.traditional);f="POST"}var i=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(j,n){if(n==="success"||n==="notmodified")i.html(e?c("<div />").append(j.responseText.replace(qb,"")).find(e):j.responseText);d&&i.each(d,[j.responseText,n,j])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&& -(this.checked||rb.test(this.nodeName)||sb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a, -b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:z.XMLHttpRequest&&(z.location.protocol!=="file:"||!z.ActiveXObject)?function(){return new z.XMLHttpRequest}: -function(){try{return new z.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(o,n,j,w);e.global&&f("ajaxSuccess",[w,e])}function d(){e.complete&&e.complete.call(o,w,j);e.global&&f("ajaxComplete",[w,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")} -function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,n,o=a&&a.context||e,m=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(m==="GET")N.test(e.url)||(e.url+=(ja.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)|| -N.test(e.url))){i=e.jsonpCallback||"jsonp"+pb++;if(e.data)e.data=(e.data+"").replace(N,"="+i+"$1");e.url=e.url.replace(N,"="+i+"$1");e.dataType="script";z[i]=z[i]||function(q){n=q;b();d();z[i]=v;try{delete z[i]}catch(p){}A&&A.removeChild(B)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&m==="GET"){var s=J(),x=e.url.replace(tb,"$1_="+s+"$2");e.url=x+(x===e.url?(ja.test(e.url)?"&":"?")+"_="+s:"")}if(e.data&&m==="GET")e.url+=(ja.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&& -c.event.trigger("ajaxStart");s=(s=ub.exec(e.url))&&(s[1]&&s[1]!==location.protocol||s[2]!==location.host);if(e.dataType==="script"&&m==="GET"&&s){var A=r.getElementsByTagName("head")[0]||r.documentElement,B=r.createElement("script");B.src=e.url;if(e.scriptCharset)B.charset=e.scriptCharset;if(!i){var C=false;B.onload=B.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;b();d();B.onload=B.onreadystatechange=null;A&&B.parentNode&& -A.removeChild(B)}}}A.insertBefore(B,A.firstChild);return v}var E=false,w=e.xhr();if(w){e.username?w.open(m,e.url,e.async,e.username,e.password):w.open(m,e.url,e.async);try{if(e.data||a&&a.contentType)w.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&w.setRequestHeader("If-None-Match",c.etag[e.url])}s||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept", -e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(fa){}if(e.beforeSend&&e.beforeSend.call(o,w,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");w.abort();return false}e.global&&f("ajaxSend",[w,e]);var g=w.onreadystatechange=function(q){if(!w||w.readyState===0||q==="abort"){E||d();E=true;if(w)w.onreadystatechange=c.noop}else if(!E&&w&&(w.readyState===4||q==="timeout")){E=true;w.onreadystatechange=c.noop;j=q==="timeout"?"timeout":!c.httpSuccess(w)? -"error":e.ifModified&&c.httpNotModified(w,e.url)?"notmodified":"success";var p;if(j==="success")try{n=c.httpData(w,e.dataType,e)}catch(u){j="parsererror";p=u}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,w,j,p);d();q==="timeout"&&w.abort();if(e.async)w=null}};try{var h=w.abort;w.abort=function(){w&&h.call(w);g("abort")}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){w&&!E&&g("timeout")},e.timeout);try{w.send(m==="POST"||m==="PUT"||m==="DELETE"?e.data:null)}catch(l){c.handleError(e, -w,null,l);d()}e.async||g();return w}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]= -f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(j,n){if(c.isArray(n))c.each(n, -function(o,m){b?f(j,m):d(j+"["+(typeof m==="object"||c.isArray(m)?o:"")+"]",m)});else!b&&n!=null&&typeof n==="object"?c.each(n,function(o,m){d(j+"["+o+"]",m)}):f(j,n)}function f(j,n){n=c.isFunction(n)?n():n;e[e.length]=encodeURIComponent(j)+"="+encodeURIComponent(n)}var e=[];if(b===v)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var i in a)d(i,a[i]);return e.join("&").replace(vb,"+")}});var ka={},wb=/toggle|show|hide/,xb=/^([+-]=)?([\d+-.]+)(.*)$/, -W,ta=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(ka[d])f=ka[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove(); -ka[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&& -c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,n=this.nodeType===1&&c(this).is(":hidden"), -o=this;for(j in a){var m=j.replace(ha,ia);if(j!==m){a[m]=a[j];delete a[j];j=m}if(a[j]==="hide"&&n||a[j]==="show"&&!n)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(s,x){var A=new c.fx(o,i,s);if(wb.test(x))A[x==="toggle"?n?"show":"hide":x](a); -else{var B=xb.exec(x),C=A.cur(true)||0;if(B){x=parseFloat(B[2]);var E=B[3]||"px";if(E!=="px"){o.style[s]=(x||1)+E;C=(x||1)/A.cur(true)*C;o.style[s]=C+E}if(B[1])x=(B[1]==="-="?-1:1)*x+C;A.custom(C,x,E)}else A.custom(C,x,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle", -1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a, -b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]== -null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop=== -"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow= -this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos= -c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!= -null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in r.documentElement?function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(), -f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(s){c.offset.setOffset(this,a,s)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f= -b,e=b.ownerDocument,i,j=e.documentElement,n=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var o=b.offsetTop,m=b.offsetLeft;(b=b.parentNode)&&b!==n&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;o-=b.scrollTop;m-=b.scrollLeft;if(b===d){o+=b.offsetTop;m+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){o+=parseFloat(i.borderTopWidth)|| -0;m+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){o+=parseFloat(i.borderTopWidth)||0;m+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){o+=n.offsetTop;m+=n.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){o+=Math.max(j.scrollTop,n.scrollTop);m+=Math.max(j.scrollLeft,n.scrollLeft)}return{top:o,left:m}};c.offset={initialize:function(){var a=r.body,b=r.createElement("div"), -d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild); -d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop}, -bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left- -e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a= -this.offsetParent||r.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==v)return this.each(function(){if(i=ua(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=ua(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}}); -c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(i){var j=c(this);j[d](f.call(this,i,j[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]|| -e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===v?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});z.jQuery=z.$=c})(window);
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/manifest.json b/chrome/common/extensions/docs/examples/extensions/gdocs/manifest.json deleted file mode 100644 index 03d1758..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/manifest.json +++ /dev/null
@@ -1,25 +0,0 @@ -{ - "name": "Google Document List Viewer", - "version": "1.0.2", - "icons": { - "48": "img/docs_spreadsheets-48.gif", - "128": "img/docs_spreadsheets-128.gif" - }, - "description": "Demonstrates how to use OAuth to connect the Google Documents List Data API.", - "background": { - "page": "background.html" - }, - "options_page": "options.html", - "browser_action": { - "default_title": "List your Google Docs", - "default_icon": "img/docs_spreadsheets-32.gif", - "default_popup": "popup.html" - }, - "permissions": [ - "tabs", - "https://docs.google.com/feeds/*", - "https://www.google.com/accounts/OAuthGetRequestToken", - "https://www.google.com/accounts/OAuthAuthorizeToken", - "https://www.google.com/accounts/OAuthGetAccessToken" - ] -}
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/options.html b/chrome/common/extensions/docs/examples/extensions/gdocs/options.html deleted file mode 100644 index fc5ab5bb6..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/options.html +++ /dev/null
@@ -1,44 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. - * - * Author: Eric Bidelman <ericbidelman@chromium.org> ---> -<html> - <head> - <title>Options</title> - <script type="text/javascript" src="js/jquery-1.4.1.min.js"></script> - </head> - <body onload="initUI();"> - <p><button id="revoke" onclick="logout();">Revoke your OAuth token</button></p> - <p>Refresh rate (seconds): <input id="refresh_rate" value="300"></p> - <script type="text/javascript"> - var bgPage = chrome.extension.getBackgroundPage(); - - $('#refresh_rate').change(function() { - localStorage.refreshRate = $(this).val(); - bgPage.refreshRate = localStorage.refreshRate; - bgPage.pollIntervalMin = bgPage.refreshRate * 1000; - }); - - function logout() { - bgPage.logout(); - $('#revoke').get(0).disabled = true; - } - - function initUI() { - if (!bgPage.oauth.hasToken()) { - $('#revoke').get(0).disabled = true; - } - - if (localStorage.refreshRate) { - $('#refresh_rate').val(localStorage.refreshRate); - } else { - $('#refresh_rate').val(bgPage.refreshRate); - } - } - </script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/gdocs/popup.html b/chrome/common/extensions/docs/examples/extensions/gdocs/popup.html deleted file mode 100644 index f2d9933c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gdocs/popup.html +++ /dev/null
@@ -1,579 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. - * - * Author: Eric Bidelman <ericbidelman@chromium.org> ---> -<html> -<head> -<title>Your Google Documents List</title> -<script type="text/javascript" src="js/jquery-1.4.1.min.js"></script> -<style type="text/css"> -body { - font: 12px 'Myriad Pro', 'Tw Cen MT', Arial, Verdana, sans-serif; - color: #666666; - overflow-x: hidden; -} -ul { - padding: 0; - list-style: none; -} -li { - clear: both; - padding: 2px 0; -} -li div img { - margin: 0 5px; - vertical-align: middle; -} -li div { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - width: 250px; - float: left; - padding: 2px 0; -} -li span { - margin-left: 5px; -} -li:hover { - background-color: #fffccc; -} -a { - color: #4E7DC2; - text-decoration: none; -} -a:hover { - color: #880000; - text-decoration: underline; -} -#butter { - color: #fff; - background-color: #000033; - padding: 5px 20px; - border-radius: 15px; - width: auto; - text-align: center; - float: right; - display: none; -} -#butter.error { - background-color: red; -} -#new_doc_container { - display: none; -} -#new_doc_container input[type='text'],textarea { - width: 100%; -} -#output { - width: 375px; - clear: both; -} -[contenteditable]:hover { - outline: 1px dotted #666; -} -.star { - margin-top: 1px; - margin-right: 3px; - width: 16px; - height: 16px; - background: no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAA3ADcAN3PbifMAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfZAwkAAh4LdI38AAAC00lEQVQoz42SS2hUZxzFz/d99zF35s7EScxEEzW1mkSlVkQJCNWSakDdxY2P0lKkSMi6G1uqbcVXF12WiiK4EMQixgeoGCMalWZRTYlG0kwNtebtzGQmmZk78937/7sQREWhB87m8DurcwTeo0Pn8xuFEN+A+djetkjnuxj5rvDbUxOLzCDTPkdOtlqU/nrvqYnG/13OZaY+rq3AZ9tb5qkP5qpPZtJTa99m2g92wXg96DjcLT2t6l2z8GVtZTwed23UVspYLFTcsfunWw8UFwaP799CAPDbd5sgdu+7XJPLl+LEosIJmYtjbqh5VWPN5zs3NyViEQszBY1z3UPPe/tHz87Olu4WvPKwEjzthu204TPtW7E0sbnCtSKGlOH51VFn9fIaGYtY0D5x1DHFhjULqlzH2DM6mftC+1TMzpYK/41nrxmaKJxIROt2tS6z41EbAMDMKJUDBlh4RFyfcMWH8xsNANFUzouevTGoh8enw2rZhp0DQ8/S1cxY2rQwbkopUNLExCwCAoghtE9MxMIrB+jsSXrXep9c1MQH1EDPmXTD+h39j5+m52nCwhX1VQ4xCx0wiF8aEIIZONeTzJ6/k7xS8unHS0faBiQAXD7clswHfOh638jIk7EclBQgYjADRIClJEZTedx6ODaeKuifrxzd9uiNnYvSnpa2FTKVhB8whABMQ0IIQAcMQwpIywp5ys69cZJP93eBlJEIlBmujNpQUiAICE8nZlDWAQwlMMe1QYbpBMqobvmhSwB4eZIcpAw7aklt3InGXQt9w2k+/cezzMBUIdNQ5VTsaq6ram6YK+oqHXcoVVwyVaZeAL4BAFoaUlpqdcRS9i9Xk8ULj1NDQUAnMvnyxWyJW+9f+qd9a1NmuQIsO2St0r7/+6uyNEzKBfjr6r/ebSG8P0tanHz4/fq/W37tx82OlSc+OnCvu3Mw+xUz1hHLPtuyfAB4AUJFSguX3LKbAAAAAElFTkSuQmCC) !important; -} -.star.selected { - background: no-repeat url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAGYktHRAA3ADcAN3PbifMAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfZAwkAAB45Qu9+AAAC1ElEQVQoz42SWUhUYRzFz/+7986dVTPT0SzNFnHBJZHCKGmTAisJgooIIrJ87CGIHopKWp/qoYdAJIIg6qEUy/aiSMoWmpbJyjJCs3SacRZnrvfe7/t6KioKOo+H3+HA4RD+oYMXxpYQ0Q5IeXLXas/FvzHsb+b2tvH8bPaiudrXUZ+rPN2yvc0s+u+wiPdVZHi1xfVzJynZE9h8Huur+ZNpPnAD9KvRdKCbxU13QVXewJFV8+SakrICet8bkO33HZ09AxU7VRF7c2b/XPGDp817Ov2huJahwEr3umRh7gRjTlWRb8O6ZWnZ5ABk8j3a75ih7qDn3HAi434s5eznkkYz3fGwakuxp640vFx1ZXocCneXT7FcFUWSkcYgxyOSVKKlVR8y/W5j6/PB/I0py5ESppV8OZR/VbWEcM+cnMhbscivK66JALIAbkCaYUkiSpKPSG+aoNqaqFpb0+0TCe678niKFRjKcyvFdeuDPf1pWSolZ5ZOTWokDEhrVJIcJfBhEB8haX+TJMZJWsDFx8XGqQcLOkzBWpTgvbPhWXVrXwQ+IkcR8anlBSEXiSiBjwAiBPAICAYB47jwqCh6+kF1V8pW9nUeXhlkAHDpUGNfwtYOXg5og4lwH4BBgA8BPAxIAwDHWFzieu/0L1+T3qNXjzS8AgD1x+wp5hpVHAmnShGAK4C0AMYBLgDBoZENRYPTYI7YbydZuPcahMqyDdLdTpcFkA0IA1YsCdgGQDYcugmTaS6uKFlL9nXRz+aQ8LIsT3RGhf+TD7pAZMiUrY+qI7cHSiPzct6mN1V1Z/pzTCqb9MnbH0uf8XEs9yEAWwUAi2mMaTR7muezfu5eYer4s8XvmLRbB+ITO2K2Xt81WNm8teRmSa5z2OHUeaWVUs//DOsaF9/s9MCx3oa7BDxJWHpbcPect40nL6F9W0NraUvPrROvl20CUGsJ5VmaM2UDwHchqUbp2jdIoAAAAABJRU5ErkJggg==) !important; -} -</style> -</head> -<body> - -<div style="height:15px;"> - <div style="float:left;"> - <a href="javascript:void(0);" onclick="gdocs.refreshDocs();return false;">Refresh list</a>, - <a href="javascript:void(0);" onclick="$('#new_doc_container').toggle();return false;">New Document</a> - </div> - <div id="butter">Fetching your docs</div> -</div> -<div id="new_doc_container"> - Create a: <select id="doc_type"> - <option value="document">document</option> - <option value="presentation">presentation</option> - <option value="spreadsheet">spreadsheet</option> - </select> - <input type="text" id="doc_title" placeholder="Enter a title"><br> - <textarea id="doc_content" placeholder="Enter document content"></textarea> - Star it? <input type="checkbox" id="doc_starred"> - <button onclick="gdocs.createDoc();" style="float:right;">Create new doc</button> -</div> -<div id="output"></div> - -<script type="text/javascript"> -// Protected namespaces. -var util = {}; -var gdocs = {}; - -var bgPage = chrome.extension.getBackgroundPage(); -var pollIntervalMax = 1000 * 60 * 60; // 1 hour -var requestFailureCount = 0; // used for exponential backoff -var requestTimeout = 1000 * 2; // 5 seconds - -var DEFAULT_MIMETYPES = { - 'atom': 'application/atom+xml', - 'document': 'text/plain', - 'spreadsheet': 'text/csv', - 'presentation': 'text/plain', - 'pdf': 'application/pdf' -}; - -// Persistent click handler for star icons. -$('#doc_type').change(function() { - if ($(this).val() === 'presentation') { - $('#doc_content').attr('disabled', 'true') - .attr('placeholder', 'N/A for presentations'); - } else { - $('#doc_content').removeAttr('disabled') - .attr('placeholder', 'Enter document content'); - } -}); - - -// Persistent click handler for changing the title of a document. -$('[contenteditable="true"]').live('blur', function(index) { - var index = $(this).parent().parent().attr('data-index'); - - // Only make the XHR if the user chose a new title. - if ($(this).text() != bgPage.docs[index].title) { - bgPage.docs[index].title = $(this).text(); - gdocs.updateDoc(bgPage.docs[index]); - } -}); - -// Persistent click handler for star icons. -$('.star').live('click', function() { - $(this).toggleClass('selected'); - - var index = $(this).parent().attr('data-index'); - bgPage.docs[index].starred = $(this).hasClass('selected'); - gdocs.updateDoc(bgPage.docs[index]); -}); - -/** - * Class to compartmentalize properties of a Google document. - * @param {Object} entry A JSON representation of a DocList atom entry. - * @constructor - */ -gdocs.GoogleDoc = function(entry) { - this.entry = entry; - this.title = entry.title.$t; - this.resourceId = entry.gd$resourceId.$t; - this.type = gdocs.getCategory( - entry.category, 'http://schemas.google.com/g/2005#kind'); - this.starred = gdocs.getCategory( - entry.category, 'http://schemas.google.com/g/2005/labels', - 'http://schemas.google.com/g/2005/labels#starred') ? true : false; - this.link = { - 'alternate': gdocs.getLink(entry.link, 'alternate').href - }; - this.contentSrc = entry.content.src; -}; - -/** - * Sets up a future poll for the user's document list. - */ -util.scheduleRequest = function() { - var exponent = Math.pow(2, requestFailureCount); - var delay = Math.min(bgPage.pollIntervalMin * exponent, - pollIntervalMax); - delay = Math.round(delay); - - if (bgPage.oauth.hasToken()) { - var req = bgPage.window.setTimeout(function() { - gdocs.getDocumentList(); - util.scheduleRequest(); - }, delay); - bgPage.requests.push(req); - } -}; - -/** - * Urlencodes a JSON object of key/value query parameters. - * @param {Object} parameters Key value pairs representing URL parameters. - * @return {string} query parameters concatenated together. - */ -util.stringify = function(parameters) { - var params = []; - for(var p in parameters) { - params.push(encodeURIComponent(p) + '=' + - encodeURIComponent(parameters[p])); - } - return params.join('&'); -}; - -/** - * Creates a JSON object of key/value pairs - * @param {string} paramStr A string of Url query parmeters. - * For example: max-results=5&startindex=2&showfolders=true - * @return {Object} The query parameters as key/value pairs. - */ -util.unstringify = function(paramStr) { - var parts = paramStr.split('&'); - - var params = {}; - for (var i = 0, pair; pair = parts[i]; ++i) { - var param = pair.split('='); - params[decodeURIComponent(param[0])] = decodeURIComponent(param[1]); - } - return params; -}; - -/** - * Utility for displaying a message to the user. - * @param {string} msg The message. - */ -util.displayMsg = function(msg) { - $('#butter').removeClass('error').text(msg).show(); -}; - -/** - * Utility for removing any messages currently showing to the user. - */ -util.hideMsg = function() { - $('#butter').fadeOut(1500); -}; - -/** - * Utility for displaying an error to the user. - * @param {string} msg The message. - */ -util.displayError = function(msg) { - util.displayMsg(msg); - $('#butter').addClass('error'); -}; - -/** - * Returns the correct atom link corresponding to the 'rel' value passed in. - * @param {Array<Object>} links A list of atom link objects. - * @param {string} rel The rel value of the link to return. For example: 'next'. - * @return {string|null} The appropriate link for the 'rel' passed in, or null - * if one is not found. - */ -gdocs.getLink = function(links, rel) { - for (var i = 0, link; link = links[i]; ++i) { - if (link.rel === rel) { - return link; - } - } - return null; -}; - -/** - * Returns the correct atom category corresponding to the scheme/term passed in. - * @param {Array<Object>} categories A list of atom category objects. - * @param {string} scheme The category's scheme to look up. - * @param {opt_term?} An optional term value for the category to look up. - * @return {string|null} The appropriate category, or null if one is not found. - */ -gdocs.getCategory = function(categories, scheme, opt_term) { - for (var i = 0, cat; cat = categories[i]; ++i) { - if (opt_term) { - if (cat.scheme === scheme && opt_term === cat.term) { - return cat; - } - } else if (cat.scheme === scheme) { - return cat; - } - } - return null; -}; - -/** - * A generic error handler for failed XHR requests. - * @param {XMLHttpRequest} xhr The xhr request that failed. - * @param {string} textStatus The server's returned status. - */ -gdocs.handleError = function(xhr, textStatus) { - util.displayError('Failed to fetch docs. Please try again.'); - ++requestFailureCount; -}; - -/** - * A helper for constructing the raw Atom xml send in the body of an HTTP post. - * @param {XMLHttpRequest} xhr The xhr request that failed. - * @param {string} docTitle A title for the document. - * @param {string} docType The type of document to create. - * (eg. 'document', 'spreadsheet', etc.) - * @param {boolean?} opt_starred Whether the document should be starred. - * @return {string} The Atom xml as a string. - */ -gdocs.constructAtomXml_ = function(docTitle, docType, opt_starred) { - var starred = opt_starred || null; - - var starCat = ['<category scheme="http://schemas.google.com/g/2005/labels" ', - 'term="http://schemas.google.com/g/2005/labels#starred" ', - 'label="starred"/>'].join(''); - - var atom = ["<?xml version='1.0' encoding='UTF-8'?>", - '<entry xmlns="http://www.w3.org/2005/Atom">', - '<category scheme="http://schemas.google.com/g/2005#kind"', - ' term="http://schemas.google.com/docs/2007#', docType, '"/>', - starred ? starCat : '', - '<title>', docTitle, '</title>', - '</entry>'].join(''); - return atom; -}; - -/** - * A helper for constructing the body of a mime-mutlipart HTTP request. - * @param {string} title A title for the new document. - * @param {string} docType The type of document to create. - * (eg. 'document', 'spreadsheet', etc.) - * @param {string} body The body of the HTTP request. - * @param {string} contentType The Content-Type of the (non-Atom) portion of the - * http body. - * @param {boolean?} opt_starred Whether the document should be starred. - * @return {string} The Atom xml as a string. - */ -gdocs.constructContentBody_ = function(title, docType, body, contentType, - opt_starred) { - var body = ['--END_OF_PART\r\n', - 'Content-Type: application/atom+xml;\r\n\r\n', - gdocs.constructAtomXml_(title, docType, opt_starred), '\r\n', - '--END_OF_PART\r\n', - 'Content-Type: ', contentType, '\r\n\r\n', - body, '\r\n', - '--END_OF_PART--\r\n'].join(''); - return body; -}; - -/** - * Creates a new document in Google Docs. - */ -gdocs.createDoc = function() { - var title = $.trim($('#doc_title').val()); - if (!title) { - alert('Please provide a title'); - return; - } - var content = $('#doc_content').val(); - var starred = $('#doc_starred').is(':checked'); - var docType = $('#doc_type').val(); - - util.displayMsg('Creating doc...'); - - var handleSuccess = function(resp, xhr) { - bgPage.docs.splice(0, 0, new gdocs.GoogleDoc(JSON.parse(resp).entry)); - - gdocs.renderDocList(); - bgPage.setIcon({'text': bgPage.docs.length.toString()}); - - $('#new_doc_container').hide(); - $('#doc_title').val(''); - $('#doc_content').val(''); - util.displayMsg('Document created!'); - util.hideMsg(); - - requestFailureCount = 0; - }; - - var params = { - 'method': 'POST', - 'headers': { - 'GData-Version': '3.0', - 'Content-Type': 'multipart/related; boundary=END_OF_PART', - }, - 'parameters': {'alt': 'json'}, - 'body': gdocs.constructContentBody_(title, docType, content, - DEFAULT_MIMETYPES[docType], starred) - }; - - // Presentation can only be created from binary content. Instead, create a - // blank presentation. - if (docType === 'presentation') { - params['headers']['Content-Type'] = DEFAULT_MIMETYPES['atom']; - params['body'] = gdocs.constructAtomXml_(title, docType, starred); - } - - bgPage.oauth.sendSignedRequest(bgPage.DOCLIST_FEED, handleSuccess, params); -}; - -/** - * Updates a document's metadata (title, starred, etc.). - * @param {gdocs.GoogleDoc} googleDocObj An object containing the document to - * update. - */ -gdocs.updateDoc = function(googleDocObj) { - var handleSuccess = function(resp) { - util.displayMsg('Updated!'); - util.hideMsg(); - requestFailureCount = 0; - }; - - var params = { - 'method': 'PUT', - 'headers': { - 'GData-Version': '3.0', - 'Content-Type': 'application/atom+xml', - 'If-Match': '*' - }, - 'body': gdocs.constructAtomXml_(googleDocObj.title, googleDocObj.type, - googleDocObj.starred) - }; - - var url = bgPage.DOCLIST_FEED + googleDocObj.resourceId; - bgPage.oauth.sendSignedRequest(url, handleSuccess, params); -}; - -/** - * Deletes a document from the user's document list. - * @param {integer} index An index intro the background page's docs array. - */ -gdocs.deleteDoc = function(index) { - var handleSuccess = function(resp, xhr) { - util.displayMsg('Document trashed!'); - util.hideMsg(); - requestFailureCount = 0; - bgPage.docs.splice(index, 1); - bgPage.setIcon({'text': bgPage.docs.length.toString()}); - } - - var params = { - 'method': 'DELETE', - 'headers': { - 'GData-Version': '3.0', - 'If-Match': '*' - } - }; - - $('#output li').eq(index).fadeOut('slow'); - - bgPage.oauth.sendSignedRequest( - bgPage.DOCLIST_FEED + bgPage.docs[index].resourceId, - handleSuccess, params); -}; - -/** - * Callback for processing the JSON feed returned by the DocList API. - * @param {string} response The server's response. - * @param {XMLHttpRequest} xhr The xhr request that was made. - */ -gdocs.processDocListResults = function(response, xhr) { - if (xhr.status != 200) { - gdocs.handleError(xhr, response); - return; - } else { - requestFailureCount = 0; - } - - var data = JSON.parse(response); - - for (var i = 0, entry; entry = data.feed.entry[i]; ++i) { - bgPage.docs.push(new gdocs.GoogleDoc(entry)); - } - - var nextLink = gdocs.getLink(data.feed.link, 'next'); - if (nextLink) { - gdocs.getDocumentList(nextLink.href); // Fetch next page of results. - } else { - gdocs.renderDocList(); - } -}; - -/** - * Presents the in-memory documents that were fetched from the server as HTML. - */ -gdocs.renderDocList = function() { - util.hideMsg(); - - // Construct the iframe's HTML. - var html = []; - for (var i = 0, doc; doc = bgPage.docs[i]; ++i) { - // If we have an arbitrary file, use generic file icon. - var type = doc.type.label; - if (doc.type.term == 'http://schemas.google.com/docs/2007#file') { - type = 'file'; - } - - var starred = doc.starred ? ' selected' : ''; - html.push( - '<li data-index="', i , '"><div class="star', starred, '"></div>', - '<div><img src="img/icons/', type, '.gif">', - '<span contenteditable="true" class="doc_title"></span></div>', - '<span>[<a href="', doc.link['alternate'], - '" target="_new">view</a> | <a href="javascript:void(0);" ', - 'onclick="gdocs.deleteDoc(',i, - ');return false;">delete</a>]','</span></li>'); - } - $('#output').html('<ul>' + html.join('') + '</ul>'); - - // Set each span's innerText to be the doc title. We're filling this after - // the html has been rendered to the page prevent XSS attacks when using - // innerHTML. - $('#output li span.doc_title').each(function(i, ul) { - $(ul).text(bgPage.docs[i].title); - }); - - bgPage.setIcon({'text': bgPage.docs.length.toString()}); -}; - -/** - * Fetches the user's document list. - * @param {string?} opt_url A url to query the doclist API with. If omitted, - * the main doclist feed uri is used. - */ -gdocs.getDocumentList = function(opt_url) { - var url = opt_url || null; - - var params = { - 'headers': { - 'GData-Version': '3.0' - } - }; - - if (!url) { - util.displayMsg('Fetching your docs'); - bgPage.setIcon({'text': '...'}); - - bgPage.docs = []; // Clear document list. We're doing a refresh. - - url = bgPage.DOCLIST_FEED; - params['parameters'] = { - 'alt': 'json', - 'showfolders': 'true' - }; - } else { - util.displayMsg($('#butter').text() + '.'); - - var parts = url.split('?'); - if (parts.length > 1) { - url = parts[0]; // Extract base URI. Params are passed in separately. - params['parameters'] = util.unstringify(parts[1]); - } - } - - bgPage.oauth.sendSignedRequest(url, gdocs.processDocListResults, params); -}; - -/** - * Refreshes the user's document list. - */ -gdocs.refreshDocs = function() { - bgPage.clearPendingRequests(); - gdocs.getDocumentList(); - util.scheduleRequest(); -}; - - -bgPage.oauth.authorize(function() { - if (!bgPage.docs.length) { - gdocs.getDocumentList(); - } else { - gdocs.renderDocList(); - } - util.scheduleRequest(); -}); -</script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ar/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ar/messages.json deleted file mode 100644 index 87faf64..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ar/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u0644\u0639\u0631\u0636 \u0639\u062f\u062f \u0627\u0644\u0631\u0633\u0627\u0626\u0644 \u063a\u064a\u0631 \u0627\u0644\u0645\u0642\u0631\u0648\u0621\u0629 \u0641\u064a \u0627\u0644\u0628\u0631\u064a\u062f \u0627\u0644\u0648\u0627\u0631\u062f \u0641\u064a Google Mail. \u0643\u0645\u0627 \u064a\u0645\u0643\u0646\u0643 \u0627\u0644\u0646\u0642\u0631 \u0639\u0644\u0649 \u0627\u0644\u0632\u0631 \u0644\u0641\u062a\u062d \u0628\u0631\u064a\u062f\u0643 \u0627\u0644\u0648\u0627\u0631\u062f."},"gmailcheck_node_error":{"message":"\u062e\u0637\u0623: \u062a\u0645 \u0627\u0633\u062a\u0631\u062f\u0627\u062f \u0627\u0644\u062e\u0644\u0627\u0635\u0629\u060c \u0648\u0644\u0643\u0646 \u0644\u0645 \u064a\u062a\u0645 \u0627\u0644\u0639\u062b\u0648\u0631 \u0639\u0644\u0649 <fullcount> \u0645\u0646 \u0627\u0644\u0639\u064f\u0642\u062f"},"gmailcheck_exception":{"message":"\u0627\u0633\u062a\u062b\u0646\u0627\u0621: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/bg/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/bg/messages.json deleted file mode 100644 index 0903503..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/bg/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043f\u043e\u0449\u0430\u0442\u0430"},"gmailcheck_description":{"message":"\u041f\u043e\u043a\u0430\u0437\u0432\u0430 \u0431\u0440\u043e\u044f \u043d\u0435\u043f\u0440\u043e\u0447\u0435\u0442\u0435\u043d\u0438 \u0441\u044a\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u044a\u0432 \u0432\u0445\u043e\u0434\u044f\u0449\u0430\u0442\u0430 \u0432\u0438 \u043f\u043e\u0449\u0430 \u0432 Google Mail. \u041c\u043e\u0436\u0435\u0442\u0435 \u0441\u044a\u0449\u043e \u0434\u0430 \u043a\u043b\u0438\u043a\u043d\u0435\u0442\u0435 \u0432\u044a\u0440\u0445\u0443 \u0431\u0443\u0442\u043e\u043d\u0430, \u0437\u0430 \u0434\u0430 \u044f \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0435."},"gmailcheck_node_error":{"message":"\u0413\u0440\u0435\u0448\u043a\u0430: \u0415\u043c\u0438\u0441\u0438\u044f\u0442\u0430 \u0431\u0435 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0430, \u043d\u043e \u043d\u044f\u043c\u0430 \u043d\u0430\u043c\u0435\u0440\u0435\u043d \u0432\u044a\u0437\u0435\u043b <fullcount>"},"gmailcheck_exception":{"message":"\u0438\u0437\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ca/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ca/messages.json deleted file mode 100644 index 6c2b1b2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ca/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Verificador de Google Mail"},"gmailcheck_description":{"message":"Mostra el nombre de missatges no llegits que hi ha a la vostra safata d'entrada de Google Mail. Tamb\u00e9 podeu fer clic al bot\u00f3 per obrir la safata d'entrada."},"gmailcheck_node_error":{"message":"Error: s'ha recuperat el feed, per\u00f2 no s'ha trobat cap node <fullcount>"},"gmailcheck_exception":{"message":"excepci\u00f3: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/cs/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/cs/messages.json deleted file mode 100644 index 394e6add..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/cs/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Kontrola e-mailu Google"},"gmailcheck_description":{"message":"Zobraz\u00ed po\u010det nep\u0159e\u010dten\u00fdch zpr\u00e1v ve slo\u017ece Doru\u010den\u00e1 po\u0161ta slu\u017eby Google Mail. Kliknut\u00edm na tla\u010d\u00edtko tuto slo\u017eku otev\u0159ete."},"gmailcheck_node_error":{"message":"Chyba: Zdroj byl na\u010dten, nebyl v\u0161ak nalezen \u017e\u00e1dn\u00fd uzel <fullcount>."},"gmailcheck_exception":{"message":"v\u00fdjimka: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/da/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/da/messages.json deleted file mode 100644 index e1c2f82..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/da/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google E-mail-t\u00e6ller"},"gmailcheck_description":{"message":"Viser antallet af ul\u00e6ste meddelelser i din Google Mail-indbakke. Du kan ogs\u00e5 klikke p\u00e5 knappen for at \u00e5bne din indbakke."},"gmailcheck_node_error":{"message":"Fejl: Feedet blev hentet, men der blev ikke fundet nogen <fullcount>-node"},"gmailcheck_exception":{"message":"undtagelse: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/de/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/de/messages.json deleted file mode 100644 index 6c21886..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/de/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail-Checker"},"gmailcheck_description":{"message":"Zeigt die Anzahl ungelesener Nachrichten in Ihrem Google Mail-Posteingang an. Sie k\u00f6nnen auch auf diese Schaltfl\u00e4che klicken, um Ihren Posteingang zu \u00f6ffnen."},"gmailcheck_node_error":{"message":"Fehler: Feed abgerufen, aber kein <fullcount> Knoten gefunden"},"gmailcheck_exception":{"message":"Ausnahme: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/el/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/el/messages.json deleted file mode 100644 index 7db2714..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/el/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"\u0388\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03c4\u03bf\u03c5 Google Mail"},"gmailcheck_description":{"message":"\u0395\u03bc\u03c6\u03b1\u03bd\u03af\u03b6\u03b5\u03b9 \u03c4\u03bf\u03bd \u03b1\u03c1\u03b9\u03b8\u03bc\u03cc \u03c4\u03c9\u03bd \u03bc\u03b7 \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c3\u03bc\u03ad\u03bd\u03c9\u03bd \u03bc\u03b7\u03bd\u03c5\u03bc\u03ac\u03c4\u03c9\u03bd \u03c3\u03c4\u03b1 \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03b1 \u03c4\u03bf\u03c5 Google Mail \u03c3\u03b1\u03c2. \u039c\u03c0\u03bf\u03c1\u03b5\u03af\u03c4\u03b5 \u03b5\u03c0\u03af\u03c3\u03b7\u03c2 \u03bd\u03b1 \u03ba\u03ac\u03bd\u03b5\u03c4\u03b5 \u03ba\u03bb\u03b9\u03ba \u03c3\u03c4\u03bf \u03ba\u03bf\u03c5\u03bc\u03c0\u03af \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b1\u03bd\u03bf\u03af\u03be\u03b5\u03c4\u03b5 \u03c4\u03b1 \u03b5\u03b9\u03c3\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03ac \u03c3\u03b1\u03c2."},"gmailcheck_node_error":{"message":"\u03a3\u03c6\u03ac\u03bb\u03bc\u03b1: \u03ad\u03b3\u03b9\u03bd\u03b5 \u03b1\u03bd\u03ac\u03ba\u03c4\u03b7\u03c3\u03b7 \u03c1\u03bf\u03ae\u03c2, \u03b1\u03bb\u03bb\u03ac \u03b4\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5 \u03ba\u03cc\u03bc\u03b2\u03bf\u03c2 <fullcount>"},"gmailcheck_exception":{"message":"\u03b5\u03be\u03b1\u03af\u03c1\u03b5\u03c3\u03b7: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en/messages.json deleted file mode 100644 index 063b9ca..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Displays the number of unread messages in your Google Mail inbox. You can also click the button to open your inbox."},"gmailcheck_node_error":{"message":"Error: feed retrieved, but no <fullcount> node found"},"gmailcheck_exception":{"message":"exception: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en_GB/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en_GB/messages.json deleted file mode 100644 index d3fa3a3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/en_GB/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Displays the number of unread messages in your Google Mail inbox. You can also click the button to open your inbox."},"gmailcheck_node_error":{"message":"Error: Feed retrieved, but no <fullcount> node found"},"gmailcheck_exception":{"message":"exception: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es/messages.json deleted file mode 100644 index 4d8364f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Permite ver el n\u00famero de mensajes sin leer en la bandeja de entrada de Google Mail. Tambi\u00e9n puedes hacer clic en el bot\u00f3n para abrir la bandeja de entrada."},"gmailcheck_node_error":{"message":"Se ha producido un error: el feed se ha recuperado, pero no se ha encontrado ning\u00fan nodo <fullcount>."},"gmailcheck_exception":{"message":"excepci\u00f3n: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es_419/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es_419/messages.json deleted file mode 100644 index 54bf2703..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/es_419/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Muestra el n\u00famero de mensajes sin leer en tu bandeja de entrada de Google Mail. Tambi\u00e9n puedes hacer clic en el bot\u00f3n para abrir tu bandeja de entrada."},"gmailcheck_node_error":{"message":"Error: se recuper\u00f3 el feed, pero no se encontr\u00f3 el nodo <fullcount>"},"gmailcheck_exception":{"message":"excepci\u00f3n: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/et/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/et/messages.json deleted file mode 100644 index 20b1e844..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/et/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google'i meilikontrollija"},"gmailcheck_description":{"message":"Kuvab Google Maili postkastis olevate lugemata s\u00f5numite arvu. V\u00f5ite kl\u00f5psata ka nupul ja avada postkasti."},"gmailcheck_node_error":{"message":"Viga: voog vastuv\u00f5etud, kuid \u00fchtki <fullcount> s\u00f5lme ei leitud"},"gmailcheck_exception":{"message":"erand: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fi/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fi/messages.json deleted file mode 100644 index f9da2c1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fi/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google-s\u00e4hk\u00f6postin tarkistus"},"gmailcheck_description":{"message":"N\u00e4ytt\u00e4\u00e4, kuinka monta lukematonta viesti\u00e4 Google Mail -postilaatikossasi on. Voit my\u00f6s avata postilaatikkosi napsauttamalla painiketta."},"gmailcheck_node_error":{"message":"Virhe: sy\u00f6te haettiin, mutta <fullcount>-solmua ei l\u00f6ytynyt"},"gmailcheck_exception":{"message":"poikkeus: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fil/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fil/messages.json deleted file mode 100644 index 1a019a60..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fil/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Ipinapakita ang bilang ng mga hindi pa nababasang mensahe sa inbox ng iyong Google Mail. Maaari mo ring i-click ang pindutan upang buksan ang iyong inbox."},"gmailcheck_node_error":{"message":"Error: nakuha ang feed, ngunit walang <fullcount> node na natagpuan"},"gmailcheck_exception":{"message":"pagbubukod: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fr/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fr/messages.json deleted file mode 100644 index 2900819..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/fr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"V\u00e9rificateur de messages Google"},"gmailcheck_description":{"message":"Affiche le nombre de messages non lus dans votre bo\u00eete de r\u00e9ception Google\u00a0Mail. Vous avez \u00e9galement la possibilit\u00e9 de cliquer sur ce bouton pour ouvrir cette derni\u00e8re."},"gmailcheck_node_error":{"message":"Erreur\u00a0: flux r\u00e9cup\u00e9r\u00e9, mais aucun n\u0153ud <fullcount> trouv\u00e9"},"gmailcheck_exception":{"message":"exception\u00a0: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/he/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/he/messages.json deleted file mode 100644 index c32e982..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/he/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u05de\u05e6\u05d9\u05d2 \u05d0\u05ea \u05de\u05e1\u05e4\u05e8 \u05d4\u05d4\u05d5\u05d3\u05e2\u05d5\u05ea \u05e9\u05dc\u05d0 \u05e0\u05e7\u05e8\u05d0\u05d5 \u05d1\u05ea\u05d9\u05d1\u05ea \u05d4\u05d3\u05d5\u05d0\u05e8 \u05d4\u05e0\u05db\u05e0\u05e1 \u05e9\u05dc\u05da \u05d1-Google Mail. \u05d1\u05e0\u05d5\u05e1\u05e3, \u05ea\u05d5\u05db\u05dc \u05dc\u05dc\u05d7\u05d5\u05e5 \u05e2\u05dc \u05d4\u05dc\u05d7\u05e6\u05df \u05db\u05d3\u05d9 \u05dc\u05e4\u05ea\u05d5\u05d7 \u05d0\u05ea \u05ea\u05d9\u05d1\u05ea \u05d4\u05d3\u05d5\u05d0\u05e8 \u05d4\u05e0\u05db\u05e0\u05e1."},"gmailcheck_node_error":{"message":"\u05e9\u05d2\u05d9\u05d0\u05d4: \u05d4\u05e2\u05d3\u05db\u05d5\u05df \u05d0\u05d5\u05d7\u05d6\u05e8, \u05d0\u05da \u05dc\u05d0 \u05e0\u05de\u05e6\u05d0\u05d5 \u05e6\u05de\u05ea\u05d9\u05dd \u05e9\u05dc <fullcount>"},"gmailcheck_exception":{"message":"\u05d7\u05e8\u05d9\u05d2: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hi/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hi/messages.json deleted file mode 100644 index 0056c56..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hi/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google \u092e\u0947\u0932 \u091c\u093e\u0902\u091a\u0915\u0930\u094d\u0924\u093e"},"gmailcheck_description":{"message":"\u0906\u092a\u0915\u0947 Google \u092e\u0947\u0932 \u0907\u0928\u092c\u0949\u0915\u094d\u0938 \u092e\u0947\u0902 \u0928 \u092a\u095d\u0947 \u0917\u090f \u0938\u0902\u0926\u0947\u0936\u094b\u0902 \u0915\u0940 \u0938\u0902\u0916\u094d\u092f\u093e \u092a\u094d\u0930\u0926\u0930\u094d\u0936\u093f\u0924 \u0915\u0930\u0924\u093e \u0939\u0948. \u0906\u092a \u0905\u092a\u0928\u093e \u0907\u0928\u092c\u0949\u0915\u094d\u0938 \u0916\u094b\u0932\u0928\u0947 \u0915\u0947 \u0932\u093f\u090f \u092c\u091f\u0928 \u0915\u094d\u0932\u093f\u0915 \u092d\u0940 \u0915\u0930 \u0938\u0915\u0924\u0947 \u0939\u0948\u0902."},"gmailcheck_node_error":{"message":"\u0924\u094d\u0930\u0941\u091f\u093f: \u095e\u0940\u0921 \u092a\u0941\u0928\u0930\u094d\u092a\u094d\u0930\u093e\u092a\u094d\u0924 \u0915\u0940 \u0917\u0908, \u0932\u0947\u0915\u093f\u0928 \u0915\u094b\u0908 <fullcount> \u0928\u094b\u0921 \u0928\u0939\u0940\u0902 \u092e\u093f\u0932\u093e"},"gmailcheck_exception":{"message":"\u0905\u092a\u0935\u093e\u0926: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hr/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hr/messages.json deleted file mode 100644 index 94dce1c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Provjera po\u0161te"},"gmailcheck_description":{"message":"Prikazuje broj nepro\u010ditanih poruka u ulaznom pretincu usluge Google Mail. Mo\u017eete tako\u0111er kliknuti gumb za otvaranje ulazne po\u0161te."},"gmailcheck_node_error":{"message":"Pogre\u0161ka: Feed je dohva\u0107en, ali nije prona\u0111eno \u010dvori\u0161te <fullcount>"},"gmailcheck_exception":{"message":"izuzetak: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hu/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hu/messages.json deleted file mode 100644 index 8b3e6c9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/hu/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Lev\u00e9lfigyel\u0151"},"gmailcheck_description":{"message":"Megjelen\u00edti az olvasatlan \u00fczeneteket a Google Mail be\u00e9rkez\u0151 levelei k\u00f6z\u00f6tt. A gombra kattintva is megnyithatja a be\u00e9rkez\u0151 leveleit."},"gmailcheck_node_error":{"message":"Hiba: h\u00edrcsatorna leh\u00edvva, de a csom\u00f3pont (<fullcount>) hi\u00e1nyzik"},"gmailcheck_exception":{"message":"kiv\u00e9tel: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/id/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/id/messages.json deleted file mode 100644 index 4a8d09c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/id/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Menampilkan jumlah pesan yang belum dibaca dalam kotak masuk Google Mail. Anda juga dapat mengeklik tombol ini untuk membuka kotak masuk."},"gmailcheck_node_error":{"message":"Galat: umpan diperoleh, tetapi tidak ada <fullcount> node yang ditemukan"},"gmailcheck_exception":{"message":"pengecualian: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/it/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/it/messages.json deleted file mode 100644 index 13b6e78..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/it/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Avvisi email"},"gmailcheck_description":{"message":"Visualizza il numero di messaggi da leggere nella posta in arrivo di Google Mail. Puoi anche fare clic sul pulsante per aprire la tua posta in arrivo."},"gmailcheck_node_error":{"message":"Errore: feed recuperato ma non sono stati trovati nodi <fullcount>"},"gmailcheck_exception":{"message":"eccezione: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ja/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ja/messages.json deleted file mode 100644 index 3ce2669..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ja/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Google Mail \u306e\u53d7\u4fe1\u30c8\u30ec\u30a4\u306b\u3042\u308b\u672a\u8aad\u306e\u30e1\u30fc\u30eb\u6570\u3092\u8868\u793a\u3057\u307e\u3059\u3002\u3053\u306e\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u53d7\u4fe1\u30c8\u30ec\u30a4\u3092\u958b\u304f\u3053\u3068\u3082\u3067\u304d\u307e\u3059\u3002"},"gmailcheck_node_error":{"message":"\u30a8\u30e9\u30fc: \u53d6\u5f97\u3057\u305f\u30d5\u30a3\u30fc\u30c9\u306b <fullcount> \u30ce\u30fc\u30c9\u304c\u3042\u308a\u307e\u305b\u3093"},"gmailcheck_exception":{"message":"\u4f8b\u5916: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ko/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ko/messages.json deleted file mode 100644 index 934e49e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ko/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Gmaill \ubc1b\uc740\ud3b8\uc9c0\ud568\uc5d0\uc11c \uc77d\uc9c0 \uc54a\uc740 \uba54\uc77c\uc758 \uc218\ub97c \ub098\ud0c0\ub0c5\ub2c8\ub2e4. \ub610\ud55c \ubc84\ud2bc\uc744 \ud074\ub9ad\ud558\uc5ec \ubc1b\uc740\ud3b8\uc9c0\ud568\uc744 \uc5f4 \uc218\ub3c4 \uc788\uc2b5\ub2c8\ub2e4."},"gmailcheck_node_error":{"message":"\uc624\ub958: \ud53c\ub4dc\ub97c \uac80\uc0c9\ud588\uc73c\ub098 \ucd1d <fullcount>\uac1c\uc758 \ub178\ub4dc\ub97c \ucc3e\uc9c0 \ubabb\ud588\uc2b5\ub2c8\ub2e4."},"gmailcheck_exception":{"message":"\uc608\uc678: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lt/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lt/messages.json deleted file mode 100644 index 7da57e1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lt/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"\u201eGoogle\u201c pa\u0161to tikrintuvas"},"gmailcheck_description":{"message":"Pateikiamas \u201eGoogle\u201c pa\u0161to gaut\u0173 lai\u0161k\u0173 aplanke esan\u010di\u0173 neperskaityt\u0173 prane\u0161im\u0173 skai\u010dius. Be to, jei norite atidaryti gaut\u0173 lai\u0161k\u0173 aplank\u0105, galite spustel\u0117ti mygtuk\u0105."},"gmailcheck_node_error":{"message":"Klaida: sklaidos kanalas nuskaitytas, ta\u010diau nerastas joks <fullcount> mazgas"},"gmailcheck_exception":{"message":"i\u0161imtis: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lv/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lv/messages.json deleted file mode 100644 index 52f2ca3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/lv/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Tiek r\u0101d\u012bts nelas\u012bto zi\u0146ojumu skaits Google Mail ies\u016btn\u0113. Varat ar\u012b noklik\u0161\u0137in\u0101t uz pogas, lai atv\u0113rtu ies\u016btni."},"gmailcheck_node_error":{"message":"K\u013c\u016bda: pl\u016bsma ir izg\u016bta, ta\u010du netika atrasts neviens <fullcount> mezgls"},"gmailcheck_exception":{"message":"iz\u0146\u0113mums: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nb/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nb/messages.json deleted file mode 100644 index ad8a09d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nb/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google e-post-sjekker"},"gmailcheck_description":{"message":"Viser antallet uleste meldinger i innboksen for Google Mail. Du kan ogs\u00e5 klikke p\u00e5 knappen for \u00e5 \u00e5pne innboksen."},"gmailcheck_node_error":{"message":"Feil: innmating hentet, men finner ingen <fullcount>-node"},"gmailcheck_exception":{"message":"unntak: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nl/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nl/messages.json deleted file mode 100644 index c40d81fa..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/nl/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Hiermee wordt het aantal ongelezen berichten in uw Postvak IN van Gmail weergegeven. U kunt ook op de knop klikken om het Postvak IN te openen."},"gmailcheck_node_error":{"message":"Fout: feed opgehaald, maar het knooppunt <fullcount> is niet gevonden"},"gmailcheck_exception":{"message":"uitzondering: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pl/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pl/messages.json deleted file mode 100644 index d607a06..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pl/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Sprawdzanie poczty Google"},"gmailcheck_description":{"message":"Wy\u015bwietla liczb\u0119 nieprzeczytanych wiadomo\u015bci w Twojej skrzynce odbiorczej Google Mail. Mo\u017cesz te\u017c klikn\u0105\u0107 przycisk, aby otworzy\u0107 swoj\u0105 skrzynk\u0119 odbiorcz\u0105."},"gmailcheck_node_error":{"message":"B\u0142\u0105d: pobrano kana\u0142, ale nie odnaleziono w\u0119z\u0142a <fullcount>"},"gmailcheck_exception":{"message":"wyj\u0105tek: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_BR/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_BR/messages.json deleted file mode 100644 index 1175d0c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_BR/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Verificador de mensagens do Google"},"gmailcheck_description":{"message":"Exibe o n\u00famero de mensagens n\u00e3o lidas na sua Caixa de entrada do Gmail. Voc\u00ea tamb\u00e9m pode clicar no bot\u00e3o para abrir a sua caixa de entrada."},"gmailcheck_node_error":{"message":"Erro: feed recuperado, mas nenhum n\u00f3 <fullcount> encontrado"},"gmailcheck_exception":{"message":"exce\u00e7\u00e3o: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_PT/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_PT/messages.json deleted file mode 100644 index e6d8992a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/pt_PT/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Verificador do Google Mail"},"gmailcheck_description":{"message":"Apresenta o n\u00famero de mensagens n\u00e3o lidas existentes na sua caixa de entrada do Google Mail. Pode tamb\u00e9m clicar no bot\u00e3o para abrir a caixa de entrada."},"gmailcheck_node_error":{"message":"Erro: obteve-se o feed, mas n\u00e3o foi encontrado nenhum n\u00f3 <fullcount>"},"gmailcheck_exception":{"message":"excep\u00e7\u00e3o: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ro/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ro/messages.json deleted file mode 100644 index d0d5838..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ro/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Verificator de e-mail"},"gmailcheck_description":{"message":"Afi\u015feaz\u0103 num\u0103rul mesajelor necitite din folderul Mesaje primite al contului Google Mail. De asemenea, pute\u0163i s\u0103 face\u0163i clic pe buton pentru a deschide folderul Mesaje primite."},"gmailcheck_node_error":{"message":"Eroare: s-a preluat feedul, dar nu s-a g\u0103sit niciun nod <fullcount>"},"gmailcheck_exception":{"message":"excep\u0163ie: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ru/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ru/messages.json deleted file mode 100644 index dedaef13..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/ru/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u043c \u044f\u0449\u0438\u043a\u0435 Google Mail. \u041c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0436\u0430\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u043f\u043a\u0443 \"\u0412\u0445\u043e\u0434\u044f\u0449\u0438\u0435\"."},"gmailcheck_node_error":{"message":"\u041e\u0448\u0438\u0431\u043a\u0430: \u0444\u0438\u0434 \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0435\u043d, \u043d\u043e \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0443\u0437\u0435\u043b <fullcount>"},"gmailcheck_exception":{"message":"\u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sk/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sk/messages.json deleted file mode 100644 index 13d902a7..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sk/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Kontrola po\u0161ty Google"},"gmailcheck_description":{"message":"Zobraz\u00ed po\u010det nepre\u010d\u00edtan\u00fdch spr\u00e1v v prie\u010dinku doru\u010denej po\u0161ty v slu\u017ebe Gmail. Kliknut\u00edm na tla\u010didlo prie\u010dinok doru\u010denej po\u0161ty otvor\u00edte."},"gmailcheck_node_error":{"message":"Chyba: informa\u010dn\u00fd kan\u00e1l bol na\u010d\u00edtan\u00fd, nena\u0161iel sa v\u0161ak \u017eiadny uzol <fullcount>."},"gmailcheck_exception":{"message":"v\u00fdnimka: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sl/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sl/messages.json deleted file mode 100644 index 962a8c6e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sl/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Preverjevalnik za Google Mail"},"gmailcheck_description":{"message":"Prika\u017ee \u0161tevilo neprebranih sporo\u010dil v nabiralniku storitve Google Mail. Nabiralnik lahko odprete tudi s klikom gumba."},"gmailcheck_node_error":{"message":"Napaka: vir prejet, vendar ni bilo najdeno nobeno vozli\u0161\u010de <fullcount>"},"gmailcheck_exception":{"message":"izjema: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sr/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sr/messages.json deleted file mode 100644 index a2cfdb4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google \u043f\u0440\u043e\u0432\u0435\u0440\u0430 \u043f\u043e\u0448\u0442\u0435"},"gmailcheck_description":{"message":"\u041f\u0440\u0438\u043a\u0430\u0437\u0443\u0458\u0435 \u0431\u0440\u043e\u0458 \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0445 \u043f\u0440\u0438\u043c\u0459\u0435\u043d\u0438\u0445 \u043f\u043e\u0440\u0443\u043a\u0430 Google Mail-\u0430. \u041c\u043e\u0436\u0435\u0442\u0435 \u0438 \u0434\u0430 \u043a\u043b\u0438\u043a\u043d\u0435\u0442\u0435 \u043d\u0430 \u0434\u0443\u0433\u043c\u0435 \u0438 \u043e\u0442\u0432\u043e\u0440\u0438\u0442\u0435 \u043f\u0440\u0438\u043c\u0459\u0435\u043d\u0435 \u043f\u043e\u0440\u0443\u043a\u0435."},"gmailcheck_node_error":{"message":"\u0413\u0440\u0435\u0448\u043a\u0430: \u0424\u0438\u0434 \u0458\u0435 \u043f\u0440\u0435\u0443\u0437\u0435\u0442, \u0430\u043b\u0438 \u0447\u0432\u043e\u0440 <fullcount> \u043d\u0438\u0458\u0435 \u043f\u0440\u043e\u043d\u0430\u0452\u0435\u043d"},"gmailcheck_exception":{"message":"\u0438\u0437\u0443\u0437\u0435\u0442\u0430\u043a: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sv/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sv/messages.json deleted file mode 100644 index b4359f35..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/sv/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Visar hur m\u00e5nga ol\u00e4sta meddelanden du har i inkorgen i Google Mail. Du kan ocks\u00e5 klicka p\u00e5 knappen om du vill \u00f6ppna inkorgen."},"gmailcheck_node_error":{"message":"Fel: feeden h\u00e4mtades, men ingen <fullcount>-nod hittades"},"gmailcheck_exception":{"message":"undantag: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/th/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/th/messages.json deleted file mode 100644 index e5bef6c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/th/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u0e41\u0e2a\u0e14\u0e07\u0e08\u0e33\u0e19\u0e27\u0e19\u0e02\u0e2d\u0e07\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e17\u0e35\u0e48\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e2d\u0e48\u0e32\u0e19\u0e43\u0e19\u0e01\u0e25\u0e48\u0e2d\u0e07\u0e08\u0e14\u0e2b\u0e21\u0e32\u0e22 Google Mail \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13 \u0e41\u0e25\u0e30\u0e04\u0e38\u0e13\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e04\u0e25\u0e34\u0e01\u0e1b\u0e38\u0e48\u0e21\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e40\u0e1b\u0e34\u0e14\u0e01\u0e25\u0e48\u0e2d\u0e07\u0e08\u0e14\u0e2b\u0e21\u0e32\u0e22\u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e40\u0e0a\u0e48\u0e19\u0e01\u0e31\u0e19"},"gmailcheck_node_error":{"message":"\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14: \u0e40\u0e23\u0e35\u0e22\u0e01\u0e04\u0e37\u0e19\u0e1f\u0e35\u0e14\u0e41\u0e25\u0e49\u0e27 \u0e41\u0e15\u0e48\u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e42\u0e2b\u0e19\u0e14 <fullcount>"},"gmailcheck_exception":{"message":"\u0e02\u0e49\u0e2d\u0e22\u0e01\u0e40\u0e27\u0e49\u0e19: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/tr/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/tr/messages.json deleted file mode 100644 index 593057dc7..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/tr/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"Google Mail gelen kutunuzdaki okunmam\u0131\u015f iletilerin say\u0131s\u0131n\u0131 g\u00f6r\u00fcnt\u00fcler. Ayr\u0131ca, d\u00fc\u011fmeyi t\u0131klayarak gelen kutunuzu da a\u00e7abilirsiniz."},"gmailcheck_node_error":{"message":"Hata: yay\u0131n al\u0131nd\u0131, ancak <fullcount> d\u00fc\u011f\u00fcm\u00fc bulunamad\u0131"},"gmailcheck_exception":{"message":"\u00f6zel durum: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/uk/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/uk/messages.json deleted file mode 100644 index 0d196cc..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/uk/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"\u041f\u0435\u0440\u0435\u0432\u0456\u0440\u043a\u0430 \u043f\u043e\u0448\u0442\u0438 Google"},"gmailcheck_description":{"message":"\u0412\u0456\u0434\u043e\u0431\u0440\u0430\u0436\u0430\u0454 \u043a\u0456\u043b\u044c\u043a\u0456\u0441\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u0438\u0445 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u044c \u0443 \u043f\u0430\u043f\u0446\u0456 \u0437 \u0432\u0445\u0456\u0434\u043d\u0438\u043c\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438 \u0441\u043b\u0443\u0436\u0431\u0438 Google Mail. \u0429\u043e\u0431 \u0432\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043f\u0430\u043f\u043a\u0443 \u0437 \u0432\u0445\u0456\u0434\u043d\u0438\u043c\u0438 \u043f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f\u043c\u0438, \u043c\u043e\u0436\u043d\u0430 \u0442\u0430\u043a\u043e\u0436 \u043d\u0430\u0442\u0438\u0441\u043d\u0443\u0442\u0438 \u0446\u044e \u043a\u043d\u043e\u043f\u043a\u0443."},"gmailcheck_node_error":{"message":"\u041f\u043e\u043c\u0438\u043b\u043a\u0430: \u043a\u0430\u043d\u0430\u043b \u0432\u0456\u0434\u043d\u043e\u0432\u043b\u0435\u043d\u043e, \u0430\u043b\u0435 \u0436\u043e\u0434\u043d\u043e\u0433\u043e \u0432\u0443\u0437\u043b\u0430 <fullcount> \u043d\u0435 \u0437\u043d\u0430\u0439\u0434\u0435\u043d\u043e"},"gmailcheck_exception":{"message":"\u0432\u0438\u043d\u044f\u0442\u043e\u043a: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/vi/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/vi/messages.json deleted file mode 100644 index d26050f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/vi/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Tr\u00ecnh Ki\u1ec3m tra Th\u01b0 c\u1ee7a Google"},"gmailcheck_description":{"message":"Hi\u1ec3n th\u1ecb s\u1ed1 th\u01b0 ch\u01b0a \u0111\u1ecdc trong h\u1ed9p th\u01b0 \u0111\u1ebfn Gmail c\u1ee7a b\u1ea1n. B\u1ea1n c\u0169ng c\u00f3 th\u1ec3 nh\u1ea5p v\u00e0o n\u00fat \u0111\u1ec3 m\u1edf h\u1ed9p th\u01b0 \u0111\u1ebfn c\u1ee7a m\u00ecnh."},"gmailcheck_node_error":{"message":"L\u1ed7i: ngu\u1ed3n c\u1ea5p d\u1eef li\u1ec7u \u0111\u00e3 \u0111\u01b0\u1ee3c truy xu\u1ea5t nh\u01b0ng kh\u00f4ng t\u00ecm th\u1ea5y n\u00fat <fullcount> n\u00e0o"},"gmailcheck_exception":{"message":"ngo\u1ea1i l\u1ec7: $1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_CN/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_CN/messages.json deleted file mode 100644 index ae6227f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_CN/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u663e\u793a Google Mail \u6536\u4ef6\u7bb1\u4e2d\u7684\u672a\u8bfb\u90ae\u4ef6\u6570\u3002\u70b9\u51fb\u8be5\u6309\u94ae\u8fd8\u53ef\u4ee5\u6253\u5f00\u60a8\u7684\u6536\u4ef6\u7bb1\u3002"},"gmailcheck_node_error":{"message":"\u9519\u8bef\uff1a\u7cfb\u7edf\u5df2\u68c0\u7d22\u4f9b\u7a3f\uff0c\u4f46\u672a\u53d1\u73b0 <fullcount> \u8282\u70b9"},"gmailcheck_exception":{"message":"\u5f02\u5e38\uff1a$1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_TW/messages.json b/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_TW/messages.json deleted file mode 100644 index 4c317934..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/_locales/zh_TW/messages.json +++ /dev/null
@@ -1 +0,0 @@ -{"gmailcheck_name":{"message":"Google Mail Checker"},"gmailcheck_description":{"message":"\u5728 Google Mail \u6536\u4ef6\u5323\u4e2d\u986f\u793a\u672a\u8b80\u90f5\u4ef6\u7684\u6578\u76ee\u3002\u6309\u4e00\u4e0b\u6309\u9215\u4e5f\u53ef\u4ee5\u958b\u555f\u6536\u4ef6\u5323\u3002"},"gmailcheck_node_error":{"message":"\u932f\u8aa4\uff1a\u64f7\u53d6\u5230\u8cc7\u8a0a\u63d0\u4f9b\uff0c\u4f46\u627e\u4e0d\u5230 <fullcount> \u7bc0\u9ede"},"gmailcheck_exception":{"message":"\u4f8b\u5916\u72c0\u6cc1\uff1a$1","placeholders":{"1":{"content":"$1"}}}}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/background.html b/chrome/common/extensions/docs/examples/extensions/gmail/background.html deleted file mode 100644 index d7aa811..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/background.html +++ /dev/null
@@ -1,3 +0,0 @@ -<img id="logged_in" src="gmail_logged_in.png"> -<canvas id="canvas" width="19" height="19"> -<script src="background.js"></script>
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/background.js b/chrome/common/extensions/docs/examples/extensions/gmail/background.js deleted file mode 100644 index 8d2c355d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/background.js +++ /dev/null
@@ -1,351 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var animationFrames = 36; -var animationSpeed = 10; // ms -var canvas = document.getElementById('canvas'); -var loggedInImage = document.getElementById('logged_in'); -var canvasContext = canvas.getContext('2d'); -var pollIntervalMin = 1; // 1 minute -var pollIntervalMax = 60; // 1 hour -var requestTimeout = 1000 * 2; // 2 seconds -var rotation = 0; -var loadingAnimation = new LoadingAnimation(); - -// Legacy support for pre-event-pages. -var oldChromeVersion = !chrome.runtime; -var requestTimerId; - -function getGmailUrl() { - return "https://mail.google.com/mail/"; -} - -// Identifier used to debug the possibility of multiple instances of the -// extension making requests on behalf of a single user. -function getInstanceId() { - if (!localStorage.hasOwnProperty("instanceId")) - localStorage.instanceId = 'gmc' + parseInt(Date.now() * Math.random(), 10); - return localStorage.instanceId; -} - -function getFeedUrl() { - // "zx" is a Gmail query parameter that is expected to contain a random - // string and may be ignored/stripped. - return getGmailUrl() + "feed/atom?zx=" + encodeURIComponent(getInstanceId()); -} - -function isGmailUrl(url) { - // Return whether the URL starts with the Gmail prefix. - return url.startsWith(getGmailUrl()); -} - -// A "loading" animation displayed while we wait for the first response from -// Gmail. This animates the badge text with a dot that cycles from left to -// right. -function LoadingAnimation() { - this.timerId_ = 0; - this.maxCount_ = 8; // Total number of states in animation - this.current_ = 0; // Current state - this.maxDot_ = 4; // Max number of dots in animation -} - -LoadingAnimation.prototype.paintFrame = function() { - var text = ""; - for (var i = 0; i < this.maxDot_; i++) { - text += (i == this.current_) ? "." : " "; - } - if (this.current_ >= this.maxDot_) - text += ""; - - chrome.browserAction.setBadgeText({text:text}); - this.current_++; - if (this.current_ == this.maxCount_) - this.current_ = 0; -} - -LoadingAnimation.prototype.start = function() { - if (this.timerId_) - return; - - var self = this; - this.timerId_ = window.setInterval(function() { - self.paintFrame(); - }, 100); -} - -LoadingAnimation.prototype.stop = function() { - if (!this.timerId_) - return; - - window.clearInterval(this.timerId_); - this.timerId_ = 0; -} - -function updateIcon() { - if (!localStorage.hasOwnProperty('unreadCount')) { - chrome.browserAction.setIcon({path:"gmail_not_logged_in.png"}); - chrome.browserAction.setBadgeBackgroundColor({color:[190, 190, 190, 230]}); - chrome.browserAction.setBadgeText({text:"?"}); - } else { - chrome.browserAction.setIcon({path: "gmail_logged_in.png"}); - chrome.browserAction.setBadgeBackgroundColor({color:[208, 0, 24, 255]}); - chrome.browserAction.setBadgeText({ - text: localStorage.unreadCount != "0" ? localStorage.unreadCount : "" - }); - } -} - -function scheduleRequest() { - console.log('scheduleRequest'); - var randomness = Math.random() * 2; - var exponent = Math.pow(2, localStorage.requestFailureCount || 0); - var multiplier = Math.max(randomness * exponent, 1); - var delay = Math.min(multiplier * pollIntervalMin, pollIntervalMax); - delay = Math.round(delay); - console.log('Scheduling for: ' + delay); - - if (oldChromeVersion) { - if (requestTimerId) { - window.clearTimeout(requestTimerId); - } - requestTimerId = window.setTimeout(onAlarm, delay*60*1000); - } else { - console.log('Creating alarm'); - // Use a repeating alarm so that it fires again if there was a problem - // setting the next alarm. - chrome.alarms.create('refresh', {periodInMinutes: delay}); - } -} - -// ajax stuff -function startRequest(params) { - // Schedule request immediately. We want to be sure to reschedule, even in the - // case where the extension process shuts down while this request is - // outstanding. - if (params && params.scheduleRequest) scheduleRequest(); - - function stopLoadingAnimation() { - if (params && params.showLoadingAnimation) loadingAnimation.stop(); - } - - if (params && params.showLoadingAnimation) - loadingAnimation.start(); - - getInboxCount( - function(count) { - stopLoadingAnimation(); - updateUnreadCount(count); - }, - function() { - stopLoadingAnimation(); - delete localStorage.unreadCount; - updateIcon(); - } - ); -} - -function getInboxCount(onSuccess, onError) { - var xhr = new XMLHttpRequest(); - var abortTimerId = window.setTimeout(function() { - xhr.abort(); // synchronously calls onreadystatechange - }, requestTimeout); - - function handleSuccess(count) { - localStorage.requestFailureCount = 0; - window.clearTimeout(abortTimerId); - if (onSuccess) - onSuccess(count); - } - - var invokedErrorCallback = false; - function handleError() { - ++localStorage.requestFailureCount; - window.clearTimeout(abortTimerId); - if (onError && !invokedErrorCallback) - onError(); - invokedErrorCallback = true; - } - - try { - xhr.onreadystatechange = function() { - if (xhr.readyState != 4) - return; - - if (xhr.responseXML) { - var xmlDoc = xhr.responseXML; - var fullCountSet = xmlDoc.evaluate("/gmail:feed/gmail:fullcount", - xmlDoc, gmailNSResolver, XPathResult.ANY_TYPE, null); - var fullCountNode = fullCountSet.iterateNext(); - if (fullCountNode) { - handleSuccess(fullCountNode.textContent); - return; - } else { - console.error(chrome.i18n.getMessage("gmailcheck_node_error")); - } - } - - handleError(); - }; - - xhr.onerror = function(error) { - handleError(); - }; - - xhr.open("GET", getFeedUrl(), true); - xhr.send(null); - } catch(e) { - console.error(chrome.i18n.getMessage("gmailcheck_exception", e)); - handleError(); - } -} - -function gmailNSResolver(prefix) { - if(prefix == 'gmail') { - return 'http://purl.org/atom/ns#'; - } -} - -function updateUnreadCount(count) { - var changed = localStorage.unreadCount != count; - localStorage.unreadCount = count; - updateIcon(); - if (changed) - animateFlip(); -} - - -function ease(x) { - return (1-Math.sin(Math.PI/2+x*Math.PI))/2; -} - -function animateFlip() { - rotation += 1/animationFrames; - drawIconAtRotation(); - - if (rotation <= 1) { - setTimeout(animateFlip, animationSpeed); - } else { - rotation = 0; - updateIcon(); - } -} - -function drawIconAtRotation() { - canvasContext.save(); - canvasContext.clearRect(0, 0, canvas.width, canvas.height); - canvasContext.translate( - Math.ceil(canvas.width/2), - Math.ceil(canvas.height/2)); - canvasContext.rotate(2*Math.PI*ease(rotation)); - canvasContext.drawImage(loggedInImage, - -Math.ceil(canvas.width/2), - -Math.ceil(canvas.height/2)); - canvasContext.restore(); - - chrome.browserAction.setIcon({imageData:canvasContext.getImageData(0, 0, - canvas.width,canvas.height)}); -} - -function goToInbox() { - console.log('Going to inbox...'); - chrome.tabs.getAllInWindow(undefined, function(tabs) { - for (var i = 0, tab; tab = tabs[i]; i++) { - if (tab.url && isGmailUrl(tab.url)) { - console.log('Found Gmail tab: ' + tab.url + '. ' + - 'Focusing and refreshing count...'); - chrome.tabs.update(tab.id, {selected: true}); - startRequest({scheduleRequest:false, showLoadingAnimation:false}); - return; - } - } - console.log('Could not find Gmail tab. Creating one...'); - chrome.tabs.create({url: getGmailUrl()}); - }); -} - -function onInit() { - console.log('onInit'); - localStorage.requestFailureCount = 0; // used for exponential backoff - startRequest({scheduleRequest:true, showLoadingAnimation:true}); - if (!oldChromeVersion) { - // TODO(mpcomplete): We should be able to remove this now, but leaving it - // for a little while just to be sure the refresh alarm is working nicely. - chrome.alarms.create('watchdog', {periodInMinutes:5}); - } -} - -function onAlarm(alarm) { - console.log('Got alarm', alarm); - // |alarm| can be undefined because onAlarm also gets called from - // window.setTimeout on old chrome versions. - if (alarm && alarm.name == 'watchdog') { - onWatchdog(); - } else { - startRequest({scheduleRequest:true, showLoadingAnimation:false}); - } -} - -function onWatchdog() { - chrome.alarms.get('refresh', function(alarm) { - if (alarm) { - console.log('Refresh alarm exists. Yay.'); - } else { - console.log('Refresh alarm doesn\'t exist!? ' + - 'Refreshing now and rescheduling.'); - startRequest({scheduleRequest:true, showLoadingAnimation:false}); - } - }); -} - -if (oldChromeVersion) { - updateIcon(); - onInit(); -} else { - chrome.runtime.onInstalled.addListener(onInit); - chrome.alarms.onAlarm.addListener(onAlarm); -} - -var filters = { - // TODO(aa): Cannot use urlPrefix because all the url fields lack the protocol - // part. See crbug.com/140238. - url: [{urlContains: getGmailUrl().replace(/^https?\:\/\//, '')}] -}; - -function onNavigate(details) { - if (details.url && isGmailUrl(details.url)) { - console.log('Recognized Gmail navigation to: ' + details.url + '.' + - 'Refreshing count...'); - startRequest({scheduleRequest:false, showLoadingAnimation:false}); - } -} -if (chrome.webNavigation && chrome.webNavigation.onDOMContentLoaded && - chrome.webNavigation.onReferenceFragmentUpdated) { - chrome.webNavigation.onDOMContentLoaded.addListener(onNavigate, filters); - chrome.webNavigation.onReferenceFragmentUpdated.addListener( - onNavigate, filters); -} else { - chrome.tabs.onUpdated.addListener(function(_, details) { - onNavigate(details); - }); -} - -chrome.browserAction.onClicked.addListener(goToInbox); - -if (chrome.runtime && chrome.runtime.onStartup) { - chrome.runtime.onStartup.addListener(function() { - console.log('Starting browser... updating icon.'); - startRequest({scheduleRequest:false, showLoadingAnimation:false}); - updateIcon(); - }); -} else { - // This hack is needed because Chrome 22 does not persist browserAction icon - // state, and also doesn't expose onStartup. So the icon always starts out in - // wrong state. We don't actually use onStartup except as a clue that we're - // in a version of Chrome that has this problem. - chrome.windows.onCreated.addListener(function() { - console.log('Window created... updating icon.'); - startRequest({scheduleRequest:false, showLoadingAnimation:false}); - updateIcon(); - }); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/gmail_logged_in.png b/chrome/common/extensions/docs/examples/extensions/gmail/gmail_logged_in.png deleted file mode 100644 index 3d3a086..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/gmail_logged_in.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/gmail_not_logged_in.png b/chrome/common/extensions/docs/examples/extensions/gmail/gmail_not_logged_in.png deleted file mode 100644 index 9c6df0b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/gmail_not_logged_in.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/icon_128.png b/chrome/common/extensions/docs/examples/extensions/gmail/icon_128.png deleted file mode 100644 index e65ccb5c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/icon_128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/gmail/manifest.json b/chrome/common/extensions/docs/examples/extensions/gmail/manifest.json deleted file mode 100644 index c181dcd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/gmail/manifest.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "background": { - "persistent": false, - "page": "background.html" - }, - "browser_action": { - "default_icon": "gmail_not_logged_in.png" - }, - "default_locale": "en", - "description": "__MSG_gmailcheck_description__", - "icons": { - "128": "icon_128.png" - }, - "name": "__MSG_gmailcheck_name__", - "permissions": [ - "alarms", - "tabs", - "webNavigation", - "*://*.google.com/" - ], - "version": "4.4.0", - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/NOTICE b/chrome/common/extensions/docs/examples/extensions/imageinfo/NOTICE deleted file mode 100644 index ecc55f6d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/NOTICE +++ /dev/null
@@ -1,5 +0,0 @@ -This extension uses code from the following JavaScript library: - -ImageInfo - A JavaScript library for reading image metadata. -Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ -MIT License [http://www.nihilogic.dk/licenses/mit-license.txt]
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/background.js b/chrome/common/extensions/docs/examples/extensions/imageinfo/background.js deleted file mode 100644 index 41147e4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/background.js +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * Returns a handler which will open a new window when activated. - */ -function getClickHandler() { - return function(info, tab) { - - // The srcUrl property is only available for image elements. - var url = 'info.html#' + info.srcUrl; - - // Create a new window to the info page. - chrome.windows.create({ url: url, width: 520, height: 660 }); - }; -}; - -/** - * Create a context menu which will only show up for images. - */ -chrome.contextMenus.create({ - "title" : "Get image info", - "type" : "normal", - "contexts" : ["image"], - "onclick" : getClickHandler() -});
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-128.png b/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-128.png deleted file mode 100644 index 80645d1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-16.png b/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-16.png deleted file mode 100644 index 39295a73..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-48.png b/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-48.png deleted file mode 100644 index 76a9f2e47..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/binaryajax.js b/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/binaryajax.js deleted file mode 100644 index f4e0426..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/binaryajax.js +++ /dev/null
@@ -1,235 +0,0 @@ - -/* - * Binary Ajax 0.1.5 - * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/ - * MIT License [http://www.opensource.org/licenses/mit-license.php] - */ - - -var BinaryFile = function(strData, iDataOffset, iDataLength) { - var data = strData; - var dataOffset = iDataOffset || 0; - var dataLength = 0; - - this.getRawData = function() { - return data; - } - - if (typeof strData == "string") { - dataLength = iDataLength || data.length; - - this.getByteAt = function(iOffset) { - return data.charCodeAt(iOffset + dataOffset) & 0xFF; - } - } else if (typeof strData == "unknown") { - dataLength = iDataLength || IEBinary_getLength(data); - - this.getByteAt = function(iOffset) { - return IEBinary_getByteAt(data, iOffset + dataOffset); - } - } - - this.getLength = function() { - return dataLength; - } - - this.getSByteAt = function(iOffset) { - var iByte = this.getByteAt(iOffset); - if (iByte > 127) - return iByte - 256; - else - return iByte; - } - - this.getShortAt = function(iOffset, bBigEndian) { - var iShort = bBigEndian ? - (this.getByteAt(iOffset) << 8) + this.getByteAt(iOffset + 1) - : (this.getByteAt(iOffset + 1) << 8) + this.getByteAt(iOffset) - if (iShort < 0) iShort += 65536; - return iShort; - } - this.getSShortAt = function(iOffset, bBigEndian) { - var iUShort = this.getShortAt(iOffset, bBigEndian); - if (iUShort > 32767) - return iUShort - 65536; - else - return iUShort; - } - this.getLongAt = function(iOffset, bBigEndian) { - var iByte1 = this.getByteAt(iOffset), - iByte2 = this.getByteAt(iOffset + 1), - iByte3 = this.getByteAt(iOffset + 2), - iByte4 = this.getByteAt(iOffset + 3); - - var iLong = bBigEndian ? - (((((iByte1 << 8) + iByte2) << 8) + iByte3) << 8) + iByte4 - : (((((iByte4 << 8) + iByte3) << 8) + iByte2) << 8) + iByte1; - if (iLong < 0) iLong += 4294967296; - return iLong; - } - this.getSLongAt = function(iOffset, bBigEndian) { - var iULong = this.getLongAt(iOffset, bBigEndian); - if (iULong > 2147483647) - return iULong - 4294967296; - else - return iULong; - } - this.getStringAt = function(iOffset, iLength) { - var aStr = []; - for (var i=iOffset,j=0;i<iOffset+iLength;i++,j++) { - aStr[j] = String.fromCharCode(this.getByteAt(i)); - } - return aStr.join(""); - } - - this.getCharAt = function(iOffset) { - return String.fromCharCode(this.getByteAt(iOffset)); - } - this.toBase64 = function() { - return window.btoa(data); - } - this.fromBase64 = function(strBase64) { - data = window.atob(strBase64); - } -} - - -var BinaryAjax = (function() { - - function createRequest() { - var oHTTP = null; - if (window.XMLHttpRequest) { - oHTTP = new XMLHttpRequest(); - } else if (window.ActiveXObject) { - oHTTP = new ActiveXObject("Microsoft.XMLHTTP"); - } - return oHTTP; - } - - function getHead(strURL, fncCallback, fncError) { - var oHTTP = createRequest(); - if (oHTTP) { - if (fncCallback) { - if (typeof(oHTTP.onload) != "undefined") { - oHTTP.onload = function() { - if (oHTTP.status == "200") { - fncCallback(this); - } else { - if (fncError) fncError(); - } - oHTTP = null; - }; - } else { - oHTTP.onreadystatechange = function() { - if (oHTTP.readyState == 4) { - if (oHTTP.status == "200") { - fncCallback(this); - } else { - if (fncError) fncError(); - } - oHTTP = null; - } - }; - } - } - oHTTP.open("HEAD", strURL, true); - oHTTP.send(null); - } else { - if (fncError) fncError(); - } - } - - function sendRequest(strURL, fncCallback, fncError, aRange, bAcceptRanges, iFileSize) { - var oHTTP = createRequest(); - if (oHTTP) { - - var iDataOffset = 0; - if (aRange && !bAcceptRanges) { - iDataOffset = aRange[0]; - } - var iDataLen = 0; - if (aRange) { - iDataLen = aRange[1]-aRange[0]+1; - } - - if (fncCallback) { - if (typeof(oHTTP.onload) != "undefined") { - oHTTP.onload = function() { - - if (oHTTP.status == "200" || oHTTP.status == "206") { - this.binaryResponse = new BinaryFile(this.responseText, iDataOffset, iDataLen); - this.fileSize = iFileSize || this.getResponseHeader("Content-Length"); - fncCallback(this); - } else { - if (fncError) fncError(); - } - oHTTP = null; - }; - } else { - oHTTP.onreadystatechange = function() { - if (oHTTP.readyState == 4) { - if (oHTTP.status == "200" || oHTTP.status == "206") { - this.binaryResponse = new BinaryFile(oHTTP.responseBody, iDataOffset, iDataLen); - this.fileSize = iFileSize || this.getResponseHeader("Content-Length"); - fncCallback(this); - } else { - if (fncError) fncError(); - } - oHTTP = null; - } - }; - } - } - oHTTP.open("GET", strURL, true); - - if (oHTTP.overrideMimeType) oHTTP.overrideMimeType('text/plain; charset=x-user-defined'); - - if (aRange && bAcceptRanges) { - oHTTP.setRequestHeader("Range", "bytes=" + aRange[0] + "-" + aRange[1]); - } - - oHTTP.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 1970 00:00:00 GMT"); - - oHTTP.send(null); - } else { - if (fncError) fncError(); - } - } - - return function(strURL, fncCallback, fncError, aRange) { - - if (aRange) { - getHead( - strURL, - function(oHTTP) { - var iLength = parseInt(oHTTP.getResponseHeader("Content-Length"),10); - var strAcceptRanges = oHTTP.getResponseHeader("Accept-Ranges"); - - var iStart, iEnd; - iStart = aRange[0]; - if (aRange[0] < 0) - iStart += iLength; - iEnd = iStart + aRange[1] - 1; - - sendRequest(strURL, fncCallback, fncError, [iStart, iEnd], (strAcceptRanges == "bytes"), iLength); - } - ); - - } else { - sendRequest(strURL, fncCallback, fncError); - } - } - -}()); - - -document.write( - "<script type='text/vbscript'>\r\n" - + "Function IEBinary_getByteAt(strBinary, iOffset)\r\n" - + " IEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\n" - + "End Function\r\n" - + "Function IEBinary_getLength(strBinary)\r\n" - + " IEBinary_getLength = LenB(strBinary)\r\n" - + "End Function\r\n" - + "</script>\r\n" -);
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/exif.js b/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/exif.js deleted file mode 100644 index 29a2782..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/exif.js +++ /dev/null
@@ -1,615 +0,0 @@ -/* - * Javascript EXIF Reader 0.1.2 - * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com, http://blog.nihilogic.dk/ - * MIT License [http://www.opensource.org/licenses/mit-license.php] - */ - - -var EXIF = {}; - -(function() { - -var bDebug = false; - -EXIF.Tags = { - - // version tags - 0x9000 : "ExifVersion", // EXIF version - 0xA000 : "FlashpixVersion", // Flashpix format version - - // colorspace tags - 0xA001 : "ColorSpace", // Color space information tag - - // image configuration - 0xA002 : "PixelXDimension", // Valid width of meaningful image - 0xA003 : "PixelYDimension", // Valid height of meaningful image - 0x9101 : "ComponentsConfiguration", // Information about channels - 0x9102 : "CompressedBitsPerPixel", // Compressed bits per pixel - - // user information - 0x927C : "MakerNote", // Any desired information written by the manufacturer - 0x9286 : "UserComment", // Comments by user - - // related file - 0xA004 : "RelatedSoundFile", // Name of related sound file - - // date and time - 0x9003 : "DateTimeOriginal", // Date and time when the original image was generated - 0x9004 : "DateTimeDigitized", // Date and time when the image was stored digitally - 0x9290 : "SubsecTime", // Fractions of seconds for DateTime - 0x9291 : "SubsecTimeOriginal", // Fractions of seconds for DateTimeOriginal - 0x9292 : "SubsecTimeDigitized", // Fractions of seconds for DateTimeDigitized - - // picture-taking conditions - 0x829A : "ExposureTime", // Exposure time (in seconds) - 0x829D : "FNumber", // F number - 0x8822 : "ExposureProgram", // Exposure program - 0x8824 : "SpectralSensitivity", // Spectral sensitivity - 0x8827 : "ISOSpeedRatings", // ISO speed rating - 0x8828 : "OECF", // Optoelectric conversion factor - 0x9201 : "ShutterSpeedValue", // Shutter speed - 0x9202 : "ApertureValue", // Lens aperture - 0x9203 : "BrightnessValue", // Value of brightness - 0x9204 : "ExposureBias", // Exposure bias - 0x9205 : "MaxApertureValue", // Smallest F number of lens - 0x9206 : "SubjectDistance", // Distance to subject in meters - 0x9207 : "MeteringMode", // Metering mode - 0x9208 : "LightSource", // Kind of light source - 0x9209 : "Flash", // Flash status - 0x9214 : "SubjectArea", // Location and area of main subject - 0x920A : "FocalLength", // Focal length of the lens in mm - 0xA20B : "FlashEnergy", // Strobe energy in BCPS - 0xA20C : "SpatialFrequencyResponse", // - 0xA20E : "FocalPlaneXResolution", // Number of pixels in width direction per FocalPlaneResolutionUnit - 0xA20F : "FocalPlaneYResolution", // Number of pixels in height direction per FocalPlaneResolutionUnit - 0xA210 : "FocalPlaneResolutionUnit", // Unit for measuring FocalPlaneXResolution and FocalPlaneYResolution - 0xA214 : "SubjectLocation", // Location of subject in image - 0xA215 : "ExposureIndex", // Exposure index selected on camera - 0xA217 : "SensingMethod", // Image sensor type - 0xA300 : "FileSource", // Image source (3 == DSC) - 0xA301 : "SceneType", // Scene type (1 == directly photographed) - 0xA302 : "CFAPattern", // Color filter array geometric pattern - 0xA401 : "CustomRendered", // Special processing - 0xA402 : "ExposureMode", // Exposure mode - 0xA403 : "WhiteBalance", // 1 = auto white balance, 2 = manual - 0xA404 : "DigitalZoomRation", // Digital zoom ratio - 0xA405 : "FocalLengthIn35mmFilm", // Equivalent foacl length assuming 35mm film camera (in mm) - 0xA406 : "SceneCaptureType", // Type of scene - 0xA407 : "GainControl", // Degree of overall image gain adjustment - 0xA408 : "Contrast", // Direction of contrast processing applied by camera - 0xA409 : "Saturation", // Direction of saturation processing applied by camera - 0xA40A : "Sharpness", // Direction of sharpness processing applied by camera - 0xA40B : "DeviceSettingDescription", // - 0xA40C : "SubjectDistanceRange", // Distance to subject - - // other tags - 0xA005 : "InteroperabilityIFDPointer", - 0xA420 : "ImageUniqueID" // Identifier assigned uniquely to each image -}; - -EXIF.TiffTags = { - 0x0100 : "ImageWidth", - 0x0101 : "ImageHeight", - 0x8769 : "ExifIFDPointer", - 0x8825 : "GPSInfoIFDPointer", - 0xA005 : "InteroperabilityIFDPointer", - 0x0102 : "BitsPerSample", - 0x0103 : "Compression", - 0x0106 : "PhotometricInterpretation", - 0x0112 : "Orientation", - 0x0115 : "SamplesPerPixel", - 0x011C : "PlanarConfiguration", - 0x0212 : "YCbCrSubSampling", - 0x0213 : "YCbCrPositioning", - 0x011A : "XResolution", - 0x011B : "YResolution", - 0x0128 : "ResolutionUnit", - 0x0111 : "StripOffsets", - 0x0116 : "RowsPerStrip", - 0x0117 : "StripByteCounts", - 0x0201 : "JPEGInterchangeFormat", - 0x0202 : "JPEGInterchangeFormatLength", - 0x012D : "TransferFunction", - 0x013E : "WhitePoint", - 0x013F : "PrimaryChromaticities", - 0x0211 : "YCbCrCoefficients", - 0x0214 : "ReferenceBlackWhite", - 0x0132 : "DateTime", - 0x010E : "ImageDescription", - 0x010F : "Make", - 0x0110 : "Model", - 0x0131 : "Software", - 0x013B : "Artist", - 0x8298 : "Copyright" -} - -EXIF.GPSTags = { - 0x0000 : "GPSVersionID", - 0x0001 : "GPSLatitudeRef", - 0x0002 : "GPSLatitude", - 0x0003 : "GPSLongitudeRef", - 0x0004 : "GPSLongitude", - 0x0005 : "GPSAltitudeRef", - 0x0006 : "GPSAltitude", - 0x0007 : "GPSTimeStamp", - 0x0008 : "GPSSatellites", - 0x0009 : "GPSStatus", - 0x000A : "GPSMeasureMode", - 0x000B : "GPSDOP", - 0x000C : "GPSSpeedRef", - 0x000D : "GPSSpeed", - 0x000E : "GPSTrackRef", - 0x000F : "GPSTrack", - 0x0010 : "GPSImgDirectionRef", - 0x0011 : "GPSImgDirection", - 0x0012 : "GPSMapDatum", - 0x0013 : "GPSDestLatitudeRef", - 0x0014 : "GPSDestLatitude", - 0x0015 : "GPSDestLongitudeRef", - 0x0016 : "GPSDestLongitude", - 0x0017 : "GPSDestBearingRef", - 0x0018 : "GPSDestBearing", - 0x0019 : "GPSDestDistanceRef", - 0x001A : "GPSDestDistance", - 0x001B : "GPSProcessingMethod", - 0x001C : "GPSAreaInformation", - 0x001D : "GPSDateStamp", - 0x001E : "GPSDifferential" -} - -EXIF.StringValues = { - ExposureProgram : { - 0 : "Not defined", - 1 : "Manual", - 2 : "Normal program", - 3 : "Aperture priority", - 4 : "Shutter priority", - 5 : "Creative program", - 6 : "Action program", - 7 : "Portrait mode", - 8 : "Landscape mode" - }, - MeteringMode : { - 0 : "Unknown", - 1 : "Average", - 2 : "CenterWeightedAverage", - 3 : "Spot", - 4 : "MultiSpot", - 5 : "Pattern", - 6 : "Partial", - 255 : "Other" - }, - LightSource : { - 0 : "Unknown", - 1 : "Daylight", - 2 : "Fluorescent", - 3 : "Tungsten (incandescent light)", - 4 : "Flash", - 9 : "Fine weather", - 10 : "Cloudy weather", - 11 : "Shade", - 12 : "Daylight fluorescent (D 5700 - 7100K)", - 13 : "Day white fluorescent (N 4600 - 5400K)", - 14 : "Cool white fluorescent (W 3900 - 4500K)", - 15 : "White fluorescent (WW 3200 - 3700K)", - 17 : "Standard light A", - 18 : "Standard light B", - 19 : "Standard light C", - 20 : "D55", - 21 : "D65", - 22 : "D75", - 23 : "D50", - 24 : "ISO studio tungsten", - 255 : "Other" - }, - Flash : { - 0x0000 : "Flash did not fire", - 0x0001 : "Flash fired", - 0x0005 : "Strobe return light not detected", - 0x0007 : "Strobe return light detected", - 0x0009 : "Flash fired, compulsory flash mode", - 0x000D : "Flash fired, compulsory flash mode, return light not detected", - 0x000F : "Flash fired, compulsory flash mode, return light detected", - 0x0010 : "Flash did not fire, compulsory flash mode", - 0x0018 : "Flash did not fire, auto mode", - 0x0019 : "Flash fired, auto mode", - 0x001D : "Flash fired, auto mode, return light not detected", - 0x001F : "Flash fired, auto mode, return light detected", - 0x0020 : "No flash function", - 0x0041 : "Flash fired, red-eye reduction mode", - 0x0045 : "Flash fired, red-eye reduction mode, return light not detected", - 0x0047 : "Flash fired, red-eye reduction mode, return light detected", - 0x0049 : "Flash fired, compulsory flash mode, red-eye reduction mode", - 0x004D : "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected", - 0x004F : "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected", - 0x0059 : "Flash fired, auto mode, red-eye reduction mode", - 0x005D : "Flash fired, auto mode, return light not detected, red-eye reduction mode", - 0x005F : "Flash fired, auto mode, return light detected, red-eye reduction mode" - }, - SensingMethod : { - 1 : "Not defined", - 2 : "One-chip color area sensor", - 3 : "Two-chip color area sensor", - 4 : "Three-chip color area sensor", - 5 : "Color sequential area sensor", - 7 : "Trilinear sensor", - 8 : "Color sequential linear sensor" - }, - SceneCaptureType : { - 0 : "Standard", - 1 : "Landscape", - 2 : "Portrait", - 3 : "Night scene" - }, - SceneType : { - 1 : "Directly photographed" - }, - CustomRendered : { - 0 : "Normal process", - 1 : "Custom process" - }, - WhiteBalance : { - 0 : "Auto white balance", - 1 : "Manual white balance" - }, - GainControl : { - 0 : "None", - 1 : "Low gain up", - 2 : "High gain up", - 3 : "Low gain down", - 4 : "High gain down" - }, - Contrast : { - 0 : "Normal", - 1 : "Soft", - 2 : "Hard" - }, - Saturation : { - 0 : "Normal", - 1 : "Low saturation", - 2 : "High saturation" - }, - Sharpness : { - 0 : "Normal", - 1 : "Soft", - 2 : "Hard" - }, - SubjectDistanceRange : { - 0 : "Unknown", - 1 : "Macro", - 2 : "Close view", - 3 : "Distant view" - }, - FileSource : { - 3 : "DSC" - }, - - Components : { - 0 : "", - 1 : "Y", - 2 : "Cb", - 3 : "Cr", - 4 : "R", - 5 : "G", - 6 : "B" - } -} - -function addEvent(oElement, strEvent, fncHandler) -{ - if (oElement.addEventListener) { - oElement.addEventListener(strEvent, fncHandler, false); - } else if (oElement.attachEvent) { - oElement.attachEvent("on" + strEvent, fncHandler); - } -} - - -function imageHasData(oImg) -{ - return !!(oImg.exifdata); -} - -function getImageData(oImg, fncCallback) -{ - BinaryAjax( - oImg.src, - function(oHTTP) { - var oEXIF = findEXIFinJPEG(oHTTP.binaryResponse); - oImg.exifdata = oEXIF || {}; - if (fncCallback) fncCallback(); - } - ) -} - -function findEXIFinJPEG(oFile) { - var aMarkers = []; - - if (oFile.getByteAt(0) != 0xFF || oFile.getByteAt(1) != 0xD8) { - return false; // not a valid jpeg - } - - var iOffset = 2; - var iLength = oFile.getLength(); - while (iOffset < iLength) { - if (oFile.getByteAt(iOffset) != 0xFF) { - if (bDebug) console.log("Not a valid marker at offset " + iOffset + ", found: " + oFile.getByteAt(iOffset)); - return false; // not a valid marker, something is wrong - } - - var iMarker = oFile.getByteAt(iOffset+1); - - // we could implement handling for other markers here, - // but we're only looking for 0xFFE1 for EXIF data - - if (iMarker == 22400) { - if (bDebug) console.log("Found 0xFFE1 marker"); - return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2); - iOffset += 2 + oFile.getShortAt(iOffset+2, true); - - } else if (iMarker == 225) { - // 0xE1 = Application-specific 1 (for EXIF) - if (bDebug) console.log("Found 0xFFE1 marker"); - return readEXIFData(oFile, iOffset + 4, oFile.getShortAt(iOffset+2, true)-2); - - } else { - iOffset += 2 + oFile.getShortAt(iOffset+2, true); - } - - } - -} - - -function readTags(oFile, iTIFFStart, iDirStart, oStrings, bBigEnd) -{ - var iEntries = oFile.getShortAt(iDirStart, bBigEnd); - var oTags = {}; - for (var i=0;i<iEntries;i++) { - var iEntryOffset = iDirStart + i*12 + 2; - var strTag = oStrings[oFile.getShortAt(iEntryOffset, bBigEnd)]; - if (!strTag && bDebug) console.log("Unknown tag: " + oFile.getShortAt(iEntryOffset, bBigEnd)); - oTags[strTag] = readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd); - } - return oTags; -} - - -function readTagValue(oFile, iEntryOffset, iTIFFStart, iDirStart, bBigEnd) -{ - var iType = oFile.getShortAt(iEntryOffset+2, bBigEnd); - var iNumValues = oFile.getLongAt(iEntryOffset+4, bBigEnd); - var iValueOffset = oFile.getLongAt(iEntryOffset+8, bBigEnd) + iTIFFStart; - - switch (iType) { - case 1: // byte, 8-bit unsigned int - case 7: // undefined, 8-bit byte, value depending on field - if (iNumValues == 1) { - return oFile.getByteAt(iEntryOffset + 8, bBigEnd); - } else { - var iValOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8); - var aVals = []; - for (var n=0;n<iNumValues;n++) { - aVals[n] = oFile.getByteAt(iValOffset + n); - } - return aVals; - } - break; - - case 2: // ascii, 8-bit byte - var iStringOffset = iNumValues > 4 ? iValueOffset : (iEntryOffset + 8); - return oFile.getStringAt(iStringOffset, iNumValues-1); - break; - - case 3: // short, 16 bit int - if (iNumValues == 1) { - return oFile.getShortAt(iEntryOffset + 8, bBigEnd); - } else { - var iValOffset = iNumValues > 2 ? iValueOffset : (iEntryOffset + 8); - var aVals = []; - for (var n=0;n<iNumValues;n++) { - aVals[n] = oFile.getShortAt(iValOffset + 2*n, bBigEnd); - } - return aVals; - } - break; - - case 4: // long, 32 bit int - if (iNumValues == 1) { - return oFile.getLongAt(iEntryOffset + 8, bBigEnd); - } else { - var aVals = []; - for (var n=0;n<iNumValues;n++) { - aVals[n] = oFile.getLongAt(iValueOffset + 4*n, bBigEnd); - } - return aVals; - } - break; - case 5: // rational = two long values, first is numerator, second is denominator - if (iNumValues == 1) { - return oFile.getLongAt(iValueOffset, bBigEnd) / oFile.getLongAt(iValueOffset+4, bBigEnd); - } else { - var aVals = []; - for (var n=0;n<iNumValues;n++) { - aVals[n] = oFile.getLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getLongAt(iValueOffset+4 + 8*n, bBigEnd); - } - return aVals; - } - break; - case 9: // slong, 32 bit signed int - if (iNumValues == 1) { - return oFile.getSLongAt(iEntryOffset + 8, bBigEnd); - } else { - var aVals = []; - for (var n=0;n<iNumValues;n++) { - aVals[n] = oFile.getSLongAt(iValueOffset + 4*n, bBigEnd); - } - return aVals; - } - break; - case 10: // signed rational, two slongs, first is numerator, second is denominator - if (iNumValues == 1) { - return oFile.getSLongAt(iValueOffset, bBigEnd) / oFile.getSLongAt(iValueOffset+4, bBigEnd); - } else { - var aVals = []; - for (var n=0;n<iNumValues;n++) { - aVals[n] = oFile.getSLongAt(iValueOffset + 8*n, bBigEnd) / oFile.getSLongAt(iValueOffset+4 + 8*n, bBigEnd); - } - return aVals; - } - break; - } -} - - -function readEXIFData(oFile, iStart, iLength) -{ - if (oFile.getStringAt(iStart, 4) != "Exif") { - if (bDebug) console.log("Not valid EXIF data! " + oFile.getStringAt(iStart, 4)); - return false; - } - - var bBigEnd; - - var iTIFFOffset = iStart + 6; - - // test for TIFF validity and endianness - if (oFile.getShortAt(iTIFFOffset) == 0x4949) { - bBigEnd = false; - } else if (oFile.getShortAt(iTIFFOffset) == 0x4D4D) { - bBigEnd = true; - } else { - if (bDebug) console.log("Not valid TIFF data! (no 0x4949 or 0x4D4D)"); - return false; - } - - if (oFile.getShortAt(iTIFFOffset+2, bBigEnd) != 0x002A) { - if (bDebug) console.log("Not valid TIFF data! (no 0x002A)"); - return false; - } - - if (oFile.getLongAt(iTIFFOffset+4, bBigEnd) != 0x00000008) { - if (bDebug) console.log("Not valid TIFF data! (First offset not 8)", oFile.getShortAt(iTIFFOffset+4, bBigEnd)); - return false; - } - - var oTags = readTags(oFile, iTIFFOffset, iTIFFOffset+8, EXIF.TiffTags, bBigEnd); - - if (oTags.ExifIFDPointer) { - var oEXIFTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.ExifIFDPointer, EXIF.Tags, bBigEnd); - for (var strTag in oEXIFTags) { - switch (strTag) { - case "LightSource" : - case "Flash" : - case "MeteringMode" : - case "ExposureProgram" : - case "SensingMethod" : - case "SceneCaptureType" : - case "SceneType" : - case "CustomRendered" : - case "WhiteBalance" : - case "GainControl" : - case "Contrast" : - case "Saturation" : - case "Sharpness" : - case "SubjectDistanceRange" : - case "FileSource" : - oEXIFTags[strTag] = EXIF.StringValues[strTag][oEXIFTags[strTag]]; - break; - - case "ExifVersion" : - case "FlashpixVersion" : - oEXIFTags[strTag] = String.fromCharCode(oEXIFTags[strTag][0], oEXIFTags[strTag][1], oEXIFTags[strTag][2], oEXIFTags[strTag][3]); - break; - - case "ComponentsConfiguration" : - oEXIFTags[strTag] = - EXIF.StringValues.Components[oEXIFTags[strTag][0]] - + EXIF.StringValues.Components[oEXIFTags[strTag][1]] - + EXIF.StringValues.Components[oEXIFTags[strTag][2]] - + EXIF.StringValues.Components[oEXIFTags[strTag][3]]; - break; - } - oTags[strTag] = oEXIFTags[strTag]; - } - } - - if (oTags.GPSInfoIFDPointer) { - var oGPSTags = readTags(oFile, iTIFFOffset, iTIFFOffset + oTags.GPSInfoIFDPointer, EXIF.GPSTags, bBigEnd); - for (var strTag in oGPSTags) { - switch (strTag) { - case "GPSVersionID" : - oGPSTags[strTag] = oGPSTags[strTag][0] - + "." + oGPSTags[strTag][1] - + "." + oGPSTags[strTag][2] - + "." + oGPSTags[strTag][3]; - break; - } - oTags[strTag] = oGPSTags[strTag]; - } - } - - return oTags; -} - - -EXIF.getData = function(oImg, fncCallback) -{ - if (!oImg.complete) return false; - if (!imageHasData(oImg)) { - getImageData(oImg, fncCallback); - } else { - if (fncCallback) fncCallback(); - } - return true; -} - -EXIF.getTag = function(oImg, strTag) -{ - if (!imageHasData(oImg)) return; - return oImg.exifdata[strTag]; -} - -EXIF.pretty = function(oImg) -{ - if (!imageHasData(oImg)) return ""; - var oData = oImg.exifdata; - var strPretty = ""; - for (var a in oData) { - if (oData.hasOwnProperty(a)) { - if (typeof oData[a] == "object") { - strPretty += a + " : [" + oData[a].length + " values]\r\n"; - } else { - strPretty += a + " : " + oData[a] + "\r\n"; - } - } - } - return strPretty; -} - -EXIF.readFromBinaryFile = function(oFile) { - return findEXIFinJPEG(oFile); -} - -function loadAllImages() -{ - var aImages = document.getElementsByTagName("img"); - for (var i=0;i<aImages.length;i++) { - if (aImages[i].getAttribute("exif") == "true") { - if (!aImages[i].complete) { - addEvent(aImages[i], "load", - function() { - EXIF.getData(this); - } - ); - } else { - EXIF.getData(aImages[i]); - } - } - } -} - -addEvent(window, "load", loadAllImages); - -})(); -
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/imageinfo.js b/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/imageinfo.js deleted file mode 100644 index 5a35c766..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/imageinfo.js +++ /dev/null
@@ -1,182 +0,0 @@ -/* - * ImageInfo 0.1.2 - A JavaScript library for reading image metadata. - * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ - * MIT License [http://www.nihilogic.dk/licenses/mit-license.txt] - */ - - -var ImageInfo = {}; - -ImageInfo.useRange = false; -ImageInfo.range = 10240; - -(function() { - - var files = []; - - function readFileData(url, callback) { - BinaryAjax( - url, - function(http) { - var tags = readInfoFromData(http.binaryResponse); - var mime = http.getResponseHeader("Content-Type"); - - tags["mimeType"] = mime; - tags["byteSize"] = http.fileSize; - - files[url] = tags; - if (callback) callback(); - }, - null, - ImageInfo.useRange ? [0, ImageInfo.range] : null - ) - } - - function readInfoFromData(data) { - - var offset = 0; - - if (data.getByteAt(0) == 0xFF && data.getByteAt(1) == 0xD8) { - return readJPEGInfo(data); - } - if (data.getByteAt(0) == 0x89 && data.getStringAt(1, 3) == "PNG") { - return readPNGInfo(data); - } - if (data.getStringAt(0,3) == "GIF") { - return readGIFInfo(data); - } - if (data.getByteAt(0) == 0x42 && data.getByteAt(1) == 0x4D) { - return readBMPInfo(data); - } - if (data.getByteAt(0) == 0x00 && data.getByteAt(1) == 0x00) { - return readICOInfo(data); - } - - return { - format : "UNKNOWN" - }; - } - - - function readPNGInfo(data) { - var w = data.getLongAt(16,true); - var h = data.getLongAt(20,true); - - var bpc = data.getByteAt(24); - var ct = data.getByteAt(25); - - var bpp = bpc; - if (ct == 4) bpp *= 2; - if (ct == 2) bpp *= 3; - if (ct == 6) bpp *= 4; - - var alpha = data.getByteAt(25) >= 4; - - return { - format : "PNG", - version : "", - width : w, - height : h, - bpp : bpp, - alpha : alpha, - exif : {} - } - } - - function readGIFInfo(data) { - var version = data.getStringAt(3,3); - var w = data.getShortAt(6); - var h = data.getShortAt(8); - - var bpp = ((data.getByteAt(10) >> 4) & 7) + 1; - - return { - format : "GIF", - version : version, - width : w, - height : h, - bpp : bpp, - alpha : false, - exif : {} - } - } - - function readJPEGInfo(data) { - - var w = 0; - var h = 0; - var comps = 0; - var len = data.getLength(); - var offset = 2; - while (offset < len) { - var marker = data.getShortAt(offset, true); - offset += 2; - if (marker == 0xFFC0) { - h = data.getShortAt(offset + 3, true); - w = data.getShortAt(offset + 5, true); - comps = data.getByteAt(offset + 7, true) - break; - } else { - offset += data.getShortAt(offset, true) - } - } - - var exif = {}; - - if (typeof EXIF != "undefined" && EXIF.readFromBinaryFile) { - exif = EXIF.readFromBinaryFile(data); - } - - return { - format : "JPEG", - version : "", - width : w, - height : h, - bpp : comps * 8, - alpha : false, - exif : exif - } - } - - function readBMPInfo(data) { - var w = data.getLongAt(18); - var h = data.getLongAt(22); - var bpp = data.getShortAt(28); - return { - format : "BMP", - version : "", - width : w, - height : h, - bpp : bpp, - alpha : false, - exif : {} - } - } - - ImageInfo.loadInfo = function(url, cb) { - if (!files[url]) { - readFileData(url, cb); - } else { - if (cb) cb(); - } - } - - ImageInfo.getAllFields = function(url) { - if (!files[url]) return null; - - var tags = {}; - for (var a in files[url]) { - if (files[url].hasOwnProperty(a)) - tags[a] = files[url][a]; - } - return tags; - } - - ImageInfo.getField = function(url, field) { - if (!files[url]) return null; - return files[url][field]; - } - - -})(); -
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/readme.txt b/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/readme.txt deleted file mode 100644 index 21865b1c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/imageinfo/readme.txt +++ /dev/null
@@ -1,7 +0,0 @@ - -ImageInfo - A JavaScript library for reading image metadata. -Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ -MIT License [http://www.nihilogic.dk/licenses/mit-license.txt] - -For detailed information and code samples please refer to the blog post at: -http://blog.nihilogic.dk/2008/07/imageinfo-reading-image-info-with-javascript.html
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.css b/chrome/common/extensions/docs/examples/extensions/imageinfo/info.css deleted file mode 100644 index 0989945..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.css +++ /dev/null
@@ -1,56 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -body { - font: 14px Arial; -} - -h1 { - margin: 30px 0 5px 0; - padding: 0; -} -code { - padding: 0; - margin: 5px 0; - display: block; -} -table { - border-collapse: collapse; - width: 100%; - margin: 15px 0; -} -td, th { - padding: 4px; -} -th { - text-align: left; - width: 130px; -} -tr { - display: none; -} -tr.rendered { - display: block; -} -tr.rendered:nth-child(odd) { - background: #eee; -} -#thumbnail { - position: fixed; - right: 20px; - top: 20px; - -webkit-box-shadow: 1px 1px 6px #000; - border: 4px solid #fff; - background: #fff; -} -#loader { - font: 30px Arial; - text-align: center; - padding: 100px; -} -#exif, #output { - display: none; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html b/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html deleted file mode 100644 index 4ca3a2e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.html +++ /dev/null
@@ -1,102 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. ---> -<html> - <head> - <script src="imageinfo/binaryajax.js"></script> - <script src="imageinfo/imageinfo.js" ></script> - <script src="imageinfo/exif.js" ></script> - <link href="info.css" rel="stylesheet" type="text/css"></link> - <script src="info.js"></script> - </head> - <body> - <div id="loader"> - Loading... <img src="loader.gif" /> - </div> - <div id="output"> - <div id="info"> - <h1>Image Information</h1> - <code id="url"></code> - <canvas id="thumbnail"></canvas> - <table> - <tr> - <th>Format</th> - <td>format</td> - </tr> - <tr> - <th>Version</th> - <td>version</td> - </tr> - <tr> - <th>Width</th> - <td>width</td> - </tr> - <tr> - <th>Height</th> - <td>height</td> - </tr> - <tr> - <th>Mime Type</th> - <td>mimeType</td> - </tr> - <tr> - <th>Size (Bytes)</th> - <td>byteSize</td> - </tr> - </table> - </div> - <div id="exif"> - <h2>EXIF Information</h2> - <table> - <tr> - <th>Date</th> - <td>DateTime</td> - </tr> - <tr> - <th>Aperture</th> - <td>ApertureValue</td> - </tr> - <tr> - <th>Exposure</th> - <td>ExposureTime</td> - </tr> - <tr> - <th>Shutter Speed</th> - <td>ShutterSpeedValue</td> - </tr> - <tr> - <th>ISO</th> - <td>ISOSpeedRatings</td> - </tr> - <tr> - <th>Camera Make</th> - <td>Make</td> - </tr> - <tr> - <th>Camera Model</th> - <td>Model</td> - </tr> - <tr> - <th>Software</th> - <td>Software</td> - </tr> - <tr> - <th>XResolution</th> - <td>XResolution</td> - </tr> - <tr> - <th>YResolution</th> - <td>YResolution</td> - </tr> - <tr> - <th>Flash</th> - <td>Flash</td> - </tr> - </table> - </div> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.js b/chrome/common/extensions/docs/examples/extensions/imageinfo/info.js deleted file mode 100644 index 40f3b27..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/info.js +++ /dev/null
@@ -1,145 +0,0 @@ -// Copyright (c) 2011 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. - - -/** - * Quick template rendering function. For each cell passed to it, check - * to see if the cell's text content is a key in the supplied data array. - * If yes, replace the cell's contents with the corresponding value and - * unhide the cell. If no, then remove the cell's parent (tr) from the - * DOM. - */ -function renderCells(cells, data) { - for (var i = 0; i < cells.length; i++) { - var cell = cells[i]; - var key = cell.innerText; - if (data[key]) { - cell.innerText = data[key]; - cell.parentElement.className = "rendered"; - } else { - cell.parentElement.parentElement.removeChild(cell.parentElement); - } - } -}; - -/** - * Returns true if the supplies object has no properties. - */ -function isEmpty(obj) { - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - return false; - } - } - return true; -}; - -/** - * Resizes the window to the current dimensions of this page's body. - */ -function resizeWindow() { - window.setTimeout(function() { - chrome.tabs.getCurrent(function (tab) { - var newHeight = Math.min(document.body.offsetHeight + 140, 700); - chrome.windows.update(tab.windowId, { - height: newHeight, - width: 520 - }); - }); - }, 150); -}; - -/** - * Called directly by the background page with information about the - * image. Outputs image data to the DOM. - */ -function renderImageInfo(imageinfo) { - console.log('imageinfo', imageinfo); - - var divloader = document.querySelector('#loader'); - var divoutput = document.querySelector('#output'); - divloader.style.display = "none"; - divoutput.style.display = "block"; - - var divinfo = document.querySelector('#info'); - var divexif = document.querySelector('#exif'); - - // Render general image data. - var datacells = divinfo.querySelectorAll('td'); - renderCells(datacells, imageinfo); - - // If EXIF data exists, unhide the EXIF table and render. - if (imageinfo['exif'] && !isEmpty(imageinfo['exif'])) { - divexif.style.display = 'block'; - var exifcells = divexif.querySelectorAll('td'); - renderCells(exifcells, imageinfo['exif']); - } -}; - -/** - * Renders the URL for the image, trimming if the length is too long. - */ -function renderUrl(url) { - var divurl = document.querySelector('#url'); - var urltext = (url.length < 45) ? url : url.substr(0, 42) + '...'; - var anchor = document.createElement('a'); - anchor.href = url; - anchor.innerText = urltext; - divurl.appendChild(anchor); -}; - -/** - * Renders a thumbnail view of the image. - */ -function renderThumbnail(url) { - var canvas = document.querySelector('#thumbnail'); - var context = canvas.getContext('2d'); - - canvas.width = 100; - canvas.height = 100; - - var image = new Image(); - image.addEventListener('load', function() { - var src_w = image.width; - var src_h = image.height; - var new_w = canvas.width; - var new_h = canvas.height; - var ratio = src_w / src_h; - if (src_w > src_h) { - new_h /= ratio; - } else { - new_w *= ratio; - } - canvas.width = new_w; - canvas.height = new_h; - context.drawImage(image, 0, 0, src_w, src_h, 0, 0, new_w, new_h); - }); - image.src = url; -}; - -/** - * Returns a function which will handle displaying information about the - * image once the ImageInfo class has finished loading. - */ -function getImageInfoHandler(url) { - return function() { - renderUrl(url); - renderThumbnail(url); - var imageinfo = ImageInfo.getAllFields(url); - renderImageInfo(imageinfo); - resizeWindow(); - }; -}; - -/** - * Load the image in question and display it, along with its metadata. - */ -document.addEventListener("DOMContentLoaded", function () { - // The URL of the image to load is passed on the URL fragment. - var imageUrl = window.location.hash.substring(1); - if (imageUrl) { - // Use the ImageInfo library to load the image and parse it. - ImageInfo.loadInfo(imageUrl, getImageInfoHandler(imageUrl)); - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/loader.gif b/chrome/common/extensions/docs/examples/extensions/imageinfo/loader.gif deleted file mode 100644 index c494f28..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/loader.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/imageinfo/manifest.json b/chrome/common/extensions/docs/examples/extensions/imageinfo/manifest.json deleted file mode 100644 index ecda1b1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/imageinfo/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "name" : "Imageinfo", - "version" : "1.0.1", - "description" : "Get image info for images, including EXIF data", - "background" : { "scripts": ["background.js"] }, - "permissions" : [ - "contextMenus", - "tabs", - "http://*/*", - "https://*/*" - ], - "minimum_chrome_version" : "6.0.0.0", - "icons" : { - "16" : "imageinfo-16.png", - "48" : "imageinfo-48.png", - "128" : "imageinfo-128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/README.txt b/chrome/common/extensions/docs/examples/extensions/irc/README.txt deleted file mode 100644 index 692beb9e3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/README.txt +++ /dev/null
@@ -1,29 +0,0 @@ -This directory contains a simple irc app which is a work in progress. - -/app - contains the manifest and any additional resources which are to be - packaged in a crx. - -/servlet - contains the java servlet which will serve the live resources and - also proxy the irc traffic between the client and irc servers - -/conf - contains configuration files for running the servlet. - -This example depends on WebSockets, so it must be run inside a servlet container -which supports WebSockets. - -The following are instructions for setting up a development jetty server to -host the servlet. - -1) Get the jetty 7.x distribution from eclipse.org. Unpack it anywhere. We'll - call that directory JETTY_HOME -2) Delete the contents of JETTY_HOME/webapps. -3) Copy /conf/irc.xml to JETTY_HOME/contexts, edit the value of resourceBase in - irc.xml to point to the contents of /servlet. -4) Copy jetty.xml and webdefault.xml to JETTY_HOME/etc -5) Copy the following jars from JETTY_HOME/lib to /servlet/WEB-INF/lib: - - jetty-client, jetty-continuation, jetty-http, jetty-io, jetty-servlets, - jetty-util - -6) Compile /servlet/src/org/chromium/IRCProxyWebSocket.java and put the - resulting class file in /servlet/WEB-INF/classes
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/app/manifest.json b/chrome/common/extensions/docs/examples/extensions/irc/app/manifest.json deleted file mode 100644 index 9c6b31e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/app/manifest.json +++ /dev/null
@@ -1,11 +0,0 @@ -{ - "name": "Chromium IRC App", - "version": "0.1", - "app": { - "launch" : { - "url": "http://localhost:8080" - }, - "origins": ["http://localhost:8080"] - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/conf/irc.xml b/chrome/common/extensions/docs/examples/extensions/irc/conf/irc.xml deleted file mode 100644 index 13441c9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/conf/irc.xml +++ /dev/null
@@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> -<Configure class="org.eclipse.jetty.webapp.WebAppContext"> - <Set name="contextPath">/</Set> - <Set name="resourceBase">file:/D:/eclipse/irc-proxy</Set> - <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set> -</Configure>
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/conf/jetty.xml b/chrome/common/extensions/docs/examples/extensions/irc/conf/jetty.xml deleted file mode 100644 index 5883d61..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/conf/jetty.xml +++ /dev/null
@@ -1,197 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> - -<!-- =============================================================== --> -<!-- Configure the Jetty Server --> -<!-- --> -<!-- Documentation of this file format can be found at: --> -<!-- http://docs.codehaus.org/display/JETTY/jetty.xml --> -<!-- --> -<!-- =============================================================== --> - - -<Configure id="Server" class="org.eclipse.jetty.server.Server"> - - <!-- =========================================================== --> - <!-- Server Thread Pool --> - <!-- =========================================================== --> - <Set name="ThreadPool"> - <!-- Default queued blocking threadpool - --> - <New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> - <Set name="minThreads">10</Set> - <Set name="maxThreads">200</Set> - </New> - - <!-- Optional Java 5 bounded threadpool with job queue - <New class="org.eclipse.thread.concurrent.ThreadPool"> - <Set name="corePoolSize">50</Set> - <Set name="maximumPoolSize">50</Set> - </New> - --> - </Set> - - - - <!-- =========================================================== --> - <!-- Set connectors --> - <!-- =========================================================== --> - - <Call name="addConnector"> - <Arg> - <New class="org.eclipse.jetty.server.nio.SelectChannelConnector"> - <Set name="host"><SystemProperty name="jetty.host" /></Set> - <Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set> - <Set name="maxIdleTime">300000</Set> - <Set name="Acceptors">2</Set> - <Set name="statsOn">false</Set> - <Set name="confidentialPort">8443</Set> - <Set name="lowResourcesConnections">20000</Set> - <Set name="lowResourcesMaxIdleTime">5000</Set> - </New> - </Arg> - </Call> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- To add a HTTPS SSL connector --> - <!-- mixin jetty-ssl.xml: --> - <!-- java -jar start.jar etc/jetty.xml etc/jetty-ssl.xml --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- To add a HTTP blocking connector --> - <!-- mixin jetty-bio.xml: --> - <!-- java -jar start.jar etc/jetty.xml etc/jetty-bio.xml --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- To allow Jetty to be started from xinetd --> - <!-- mixin jetty-xinetd.xml: --> - <!-- java -jar start.jar etc/jetty.xml etc/jetty-xinetd.xml --> - <!-- --> - <!-- See jetty-xinetd.xml for further instructions. --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - - <!-- =========================================================== --> - <!-- Set handler Collection Structure --> - <!-- =========================================================== --> - <Set name="handler"> - <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection"> - <Set name="handlers"> - <Array type="org.eclipse.jetty.server.Handler"> - <Item> - <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/> - </Item> - <Item> - <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/> - </Item> - <Item> - <New id="RequestLog" class="org.eclipse.jetty.server.handler.RequestLogHandler"/> - </Item> - </Array> - </Set> - </New> - </Set> - - <!-- =========================================================== --> - <!-- Configure the context deployer --> - <!-- A context deployer will deploy contexts described in --> - <!-- configuration files discovered in a directory. --> - <!-- The configuration directory can be scanned for hot --> - <!-- deployments at the configured scanInterval. --> - <!-- --> - <!-- This deployer is configured to deploy contexts configured --> - <!-- in the $JETTY_HOME/contexts directory --> - <!-- --> - <!-- =========================================================== --> - <Call name="addBean"> - <Arg> - <New class="org.eclipse.jetty.deploy.ContextDeployer"> - <Set name="contexts"><Ref id="Contexts"/></Set> - <Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts</Set> - <Set name="scanInterval">5</Set> - <Call name="setAttribute"> - <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg> - <Arg>.*/jsp-api-[^/]*\.jar$|.*/jsp-[^/]*\.jar$</Arg> - </Call> - </New> - </Arg> - </Call> - - <!-- =========================================================== --> - <!-- Configure the webapp deployer. --> - <!-- A webapp deployer will deploy standard webapps discovered --> - <!-- in a directory at startup, without the need for additional --> - <!-- configuration files. It does not support hot deploy or --> - <!-- non standard contexts (see ContextDeployer above). --> - <!-- --> - <!-- This deployer is configured to deploy webapps from the --> - <!-- $JETTY_HOME/webapps directory --> - <!-- --> - <!-- Normally only one type of deployer need be used. --> - <!-- --> - <!-- =========================================================== --> - <Call name="addBean"> - <Arg> - <New class="org.eclipse.jetty.deploy.WebAppDeployer"> - <Set name="contexts"><Ref id="Contexts"/></Set> - <Set name="webAppDir"><SystemProperty name="jetty.home" default="."/>/webapps</Set> - <Set name="parentLoaderPriority">false</Set> - <Set name="extract">true</Set> - <Set name="allowDuplicates">false</Set> - <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set> - <Call name="setAttribute"> - <Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg> - <Arg>.*/jsp-api-[^/]*\.jar$|.*/jsp-[^/]*\.jar$</Arg> - </Call> - </New> - </Arg> - </Call> - - <!-- =========================================================== --> - <!-- Configure Authentication Login Service --> - <!-- Realms may be configured for the entire server here, or --> - <!-- they can be configured for a specific web app in a context --> - <!-- configuration (see $(jetty.home)/contexts/test.xml for an --> - <!-- example). --> - <!-- =========================================================== --> - <Call name="addBean"> - <Arg> - <New class="org.eclipse.jetty.security.HashLoginService"> - <Set name="name">Test Realm</Set> - <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set> - <Set name="refreshInterval">0</Set> - </New> - </Arg> - </Call> - - <!-- =========================================================== --> - <!-- Configure Request Log --> - <!-- Request logs may be configured for the entire server here, --> - <!-- or they can be configured for a specific web app in a --> - <!-- contexts configuration (see $(jetty.home)/contexts/test.xml --> - <!-- for an example). --> - <!-- =========================================================== --> - <Ref id="RequestLog"> - <Set name="requestLog"> - <New id="RequestLogImpl" class="org.eclipse.jetty.server.NCSARequestLog"> - <Set name="filename"><SystemProperty name="jetty.home" default="."/>/logs/yyyy_mm_dd.request.log</Set> - <Set name="filenameDateFormat">yyyy_MM_dd</Set> - <Set name="retainDays">90</Set> - <Set name="append">true</Set> - <Set name="extended">false</Set> - <Set name="logCookies">false</Set> - <Set name="LogTimeZone">GMT</Set> - </New> - </Set> - </Ref> - - <!-- =========================================================== --> - <!-- extra options --> - <!-- =========================================================== --> - <Set name="stopAtShutdown">true</Set> - <Set name="sendServerVersion">true</Set> - <Set name="sendDateHeader">true</Set> - <Set name="gracefulShutdown">1000</Set> - -</Configure>
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/conf/webdefault.xml b/chrome/common/extensions/docs/examples/extensions/irc/conf/webdefault.xml deleted file mode 100644 index b52cadd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/conf/webdefault.xml +++ /dev/null
@@ -1,404 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> - -<!-- ===================================================================== --> -<!-- This file contains the default descriptor for web applications. --> -<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> -<!-- The intent of this descriptor is to include jetty specific or common --> -<!-- configuration for all webapps. If a context has a webdefault.xml --> -<!-- descriptor, it is applied before the contexts own web.xml file --> -<!-- --> -<!-- A context may be assigned a default descriptor by: --> -<!-- + Calling WebApplicationContext.setDefaultsDescriptor --> -<!-- + Passed an arg to addWebApplications --> -<!-- --> -<!-- This file is used both as the resource within the jetty.jar (which is --> -<!-- used as the default if no explicit defaults descriptor is set) and it --> -<!-- is copied to the etc directory of the Jetty distro and explicitly --> -<!-- by the jetty.xml file. --> -<!-- --> -<!-- ===================================================================== --> -<web-app - xmlns="http://java.sun.com/xml/ns/javaee" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" - metadata-complete="true" - version="2.5"> - - <description> - Default web.xml file. - This file is applied to a Web application before it's own WEB_INF/web.xml file - </description> - - - <!-- ==================================================================== --> - <!-- Context params to control Session Cookies --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- UNCOMMENT TO ACTIVATE - <context-param> - <param-name>org.eclipse.jetty.servlet.SessionDomain</param-name> - <param-value>127.0.0.1</param-value> - </context-param> - - <context-param> - <param-name>org.eclipse.jetty.servlet.SessionPath</param-name> - <param-value>/</param-value> - </context-param> - - <context-param> - <param-name>org.eclipse.jetty.servlet.MaxAge</param-name> - <param-value>-1</param-value> - </context-param> - --> - - - <!-- ==================================================================== --> - <!-- The default servlet. --> - <!-- This servlet, normally mapped to /, provides the handling for static --> - <!-- content, OPTIONS and TRACE methods for the context. --> - <!-- The following initParameters are supported: --> - <!-- --> - <!-- acceptRanges If true, range requests and responses are --> - <!-- supported --> - <!-- --> - <!-- dirAllowed If true, directory listings are returned if no --> - <!-- welcome file is found. Else 403 Forbidden. --> - <!-- --> - <!-- welcomeServlets If true, attempt to dispatch to welcome files --> - <!-- that are servlets, if no matching static --> - <!-- resources can be found. --> - <!-- --> - <!-- redirectWelcome If true, redirect welcome file requests --> - <!-- else use request dispatcher forwards --> - <!-- --> - <!-- gzip If set to true, then static content will be served--> - <!-- as gzip content encoded if a matching resource is --> - <!-- found ending with ".gz" --> - <!-- --> - <!-- resoureBase Can be set to replace the context resource base --> - <!-- --> - <!-- relativeResourceBase --> - <!-- Set with a pathname relative to the base of the --> - <!-- servlet context root. Useful for only serving --> - <!-- static content from only specific subdirectories. --> - <!-- --> - <!-- useFileMappedBuffer --> - <!-- If set to true (the default), a memory mapped --> - <!-- file buffer will be used to serve static content --> - <!-- when using an NIO connector. Setting this value --> - <!-- to false means that a direct buffer will be used --> - <!-- instead. If you are having trouble with Windows --> - <!-- file locking, set this to false. --> - <!-- --> - <!-- cacheControl If set, all static content will have this value --> - <!-- set as the cache-control header. --> - <!-- --> - <!-- maxCacheSize Maximum size of the static resource cache --> - <!-- --> - <!-- maxCachedFileSize Maximum size of any single file in the cache --> - <!-- --> - <!-- maxCachedFiles Maximum number of files in the cache --> - <!-- --> - <!-- cacheType "nio", "bio" or "both" to determine the type(s) --> - <!-- of resource cache. A bio cached buffer may be used--> - <!-- by nio but is not as efficient as a nio buffer. --> - <!-- An nio cached buffer may not be used by bio. --> - <!-- --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <servlet> - <servlet-name>default</servlet-name> - <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class> - <init-param> - <param-name>acceptRanges</param-name> - <param-value>true</param-value> - </init-param> - <init-param> - <param-name>dirAllowed</param-name> - <param-value>true</param-value> - </init-param> - <init-param> - <param-name>welcomeServlets</param-name> - <param-value>false</param-value> - </init-param> - <init-param> - <param-name>redirectWelcome</param-name> - <param-value>false</param-value> - </init-param> - <init-param> - <param-name>maxCacheSize</param-name> - <param-value>256000000</param-value> - </init-param> - <init-param> - <param-name>maxCachedFileSize</param-name> - <param-value>10000000</param-value> - </init-param> - <init-param> - <param-name>maxCachedFiles</param-name> - <param-value>1000</param-value> - </init-param> - <init-param> - <param-name>cacheType</param-name> - <param-value>both</param-value> - </init-param> - <init-param> - <param-name>gzip</param-name> - <param-value>true</param-value> - </init-param> - <init-param> - <param-name>useFileMappedBuffer</param-name> - <param-value>false</param-value> - </init-param> - <!-- - <init-param> - <param-name>cacheControl</param-name> - <param-value>max-age=3600,public</param-value> - </init-param> - --> - <load-on-startup>0</load-on-startup> - </servlet> - - <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> - - - <!-- ==================================================================== --> - <!-- JSP Servlet --> - <!-- This is the jasper JSP servlet from the jakarta project --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- The JSP page compiler and execution servlet, which is the mechanism --> - <!-- used by Glassfish to support JSP pages. Traditionally, this servlet --> - <!-- is mapped to URL patterh "*.jsp". This servlet supports the --> - <!-- following initialization parameters (default values are in square --> - <!-- brackets): --> - <!-- --> - <!-- checkInterval If development is false and reloading is true, --> - <!-- background compiles are enabled. checkInterval --> - <!-- is the time in seconds between checks to see --> - <!-- if a JSP page needs to be recompiled. [300] --> - <!-- --> - <!-- compiler Which compiler Ant should use to compile JSP --> - <!-- pages. See the Ant documenation for more --> - <!-- information. [javac] --> - <!-- --> - <!-- classdebuginfo Should the class file be compiled with --> - <!-- debugging information? [true] --> - <!-- --> - <!-- classpath What class path should I use while compiling --> - <!-- generated servlets? [Created dynamically --> - <!-- based on the current web application] --> - <!-- Set to ? to make the container explicitly set --> - <!-- this parameter. --> - <!-- --> - <!-- development Is Jasper used in development mode (will check --> - <!-- for JSP modification on every access)? [true] --> - <!-- --> - <!-- enablePooling Determines whether tag handler pooling is --> - <!-- enabled [true] --> - <!-- --> - <!-- fork Tell Ant to fork compiles of JSP pages so that --> - <!-- a separate JVM is used for JSP page compiles --> - <!-- from the one Tomcat is running in. [true] --> - <!-- --> - <!-- ieClassId The class-id value to be sent to Internet --> - <!-- Explorer when using <jsp:plugin> tags. --> - <!-- [clsid:8AD9C840-044E-11D1-B3E9-00805F499D93] --> - <!-- --> - <!-- javaEncoding Java file encoding to use for generating java --> - <!-- source files. [UTF-8] --> - <!-- --> - <!-- keepgenerated Should we keep the generated Java source code --> - <!-- for each page instead of deleting it? [true] --> - <!-- --> - <!-- logVerbosityLevel The level of detailed messages to be produced --> - <!-- by this servlet. Increasing levels cause the --> - <!-- generation of more messages. Valid values are --> - <!-- FATAL, ERROR, WARNING, INFORMATION, and DEBUG. --> - <!-- [WARNING] --> - <!-- --> - <!-- mappedfile Should we generate static content with one --> - <!-- print statement per input line, to ease --> - <!-- debugging? [false] --> - <!-- --> - <!-- --> - <!-- reloading Should Jasper check for modified JSPs? [true] --> - <!-- --> - <!-- suppressSmap Should the generation of SMAP info for JSR45 --> - <!-- debugging be suppressed? [false] --> - <!-- --> - <!-- dumpSmap Should the SMAP info for JSR45 debugging be --> - <!-- dumped to a file? [false] --> - <!-- False if suppressSmap is true --> - <!-- --> - <!-- scratchdir What scratch directory should we use when --> - <!-- compiling JSP pages? [default work directory --> - <!-- for the current web application] --> - <!-- --> - <!-- tagpoolMaxSize The maximum tag handler pool size [5] --> - <!-- --> - <!-- xpoweredBy Determines whether X-Powered-By response --> - <!-- header is added by generated servlet [false] --> - <!-- --> - <!-- If you wish to use Jikes to compile JSP pages: --> - <!-- Set the init parameter "compiler" to "jikes". Define --> - <!-- the property "-Dbuild.compiler.emacs=true" when starting Jetty --> - <!-- to cause Jikes to emit error messages in a format compatible with --> - <!-- Jasper. --> - <!-- If you get an error reporting that jikes can't use UTF-8 encoding, --> - <!-- try setting the init parameter "javaEncoding" to "ISO-8859-1". --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <servlet id="jsp"> - <servlet-name>jsp</servlet-name> - <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> - <init-param> - <param-name>logVerbosityLevel</param-name> - <param-value>DEBUG</param-value> - </init-param> - <init-param> - <param-name>fork</param-name> - <param-value>false</param-value> - </init-param> - <init-param> - <param-name>xpoweredBy</param-name> - <param-value>false</param-value> - </init-param> - <!-- - <init-param> - <param-name>classpath</param-name> - <param-value>?</param-value> - </init-param> - --> - <load-on-startup>0</load-on-startup> - </servlet> - - <servlet-mapping> - <servlet-name>jsp</servlet-name> - <url-pattern>*.jsp</url-pattern> - <url-pattern>*.jspf</url-pattern> - <url-pattern>*.jspx</url-pattern> - <url-pattern>*.xsp</url-pattern> - <url-pattern>*.JSP</url-pattern> - <url-pattern>*.JSPF</url-pattern> - <url-pattern>*.JSPX</url-pattern> - <url-pattern>*.XSP</url-pattern> - </servlet-mapping> - - <!-- ==================================================================== --> - <!-- Dynamic Servlet Invoker. --> - <!-- This servlet invokes anonymous servlets that have not been defined --> - <!-- in the web.xml or by other means. The first element of the pathInfo --> - <!-- of a request passed to the envoker is treated as a servlet name for --> - <!-- an existing servlet, or as a class name of a new servlet. --> - <!-- This servlet is normally mapped to /servlet/* --> - <!-- This servlet support the following initParams: --> - <!-- --> - <!-- nonContextServlets If false, the invoker can only load --> - <!-- servlets from the contexts classloader. --> - <!-- This is false by default and setting this --> - <!-- to true may have security implications. --> - <!-- --> - <!-- verbose If true, log dynamic loads --> - <!-- --> - <!-- * All other parameters are copied to the --> - <!-- each dynamic servlet as init parameters --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- Uncomment for dynamic invocation - <servlet> - <servlet-name>invoker</servlet-name> - <servlet-class>org.eclipse.jetty.servlet.Invoker</servlet-class> - <init-param> - <param-name>verbose</param-name> - <param-value>false</param-value> - </init-param> - <init-param> - <param-name>nonContextServlets</param-name> - <param-value>false</param-value> - </init-param> - <init-param> - <param-name>dynamicParam</param-name> - <param-value>anyValue</param-value> - </init-param> - <load-on-startup>0</load-on-startup> - </servlet> - - <servlet-mapping> <servlet-name>invoker</servlet-name> <url-pattern>/servlet/*</url-pattern> </servlet-mapping> - --> - - - - <!-- ==================================================================== --> - <session-config> - <session-timeout>30</session-timeout> - </session-config> - - <!-- ==================================================================== --> - <!-- Default MIME mappings --> - <!-- The default MIME mappings are provided by the mime.properties --> - <!-- resource in the org.eclipse.jetty.server.jar file. Additional or modified --> - <!-- mappings may be specified here --> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- UNCOMMENT TO ACTIVATE - <mime-mapping> - <extension>mysuffix</extension> - <mime-type>mymime/type</mime-type> - </mime-mapping> - --> - - <!-- ==================================================================== --> - <welcome-file-list> - <welcome-file>index.html</welcome-file> - <welcome-file>index.htm</welcome-file> - <welcome-file>index.jsp</welcome-file> - </welcome-file-list> - - <!-- ==================================================================== --> - <locale-encoding-mapping-list> - <locale-encoding-mapping><locale>ar</locale><encoding>ISO-8859-6</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>be</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>bg</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>ca</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>cs</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>da</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>de</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>el</locale><encoding>ISO-8859-7</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>en</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>es</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>et</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>fi</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>fr</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>hr</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>hu</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>is</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>it</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>iw</locale><encoding>ISO-8859-8</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>ja</locale><encoding>Shift_JIS</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>ko</locale><encoding>EUC-KR</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>lt</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>lv</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>mk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>nl</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>no</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>pl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>pt</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>ro</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>ru</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>sh</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>sk</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>sl</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>sq</locale><encoding>ISO-8859-2</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>sr</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>sv</locale><encoding>ISO-8859-1</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>tr</locale><encoding>ISO-8859-9</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>uk</locale><encoding>ISO-8859-5</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>zh</locale><encoding>GB2312</encoding></locale-encoding-mapping> - <locale-encoding-mapping><locale>zh_TW</locale><encoding>Big5</encoding></locale-encoding-mapping> - </locale-encoding-mapping-list> - - <security-constraint> - <web-resource-collection> - <web-resource-name>Disable TRACE</web-resource-name> - <url-pattern>/</url-pattern> - <http-method>TRACE</http-method> - </web-resource-collection> - <auth-constraint/> - </security-constraint> - -</web-app> -
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/WEB-INF/web.xml b/chrome/common/extensions/docs/examples/extensions/irc/servlet/WEB-INF/web.xml deleted file mode 100644 index 151b76d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/WEB-INF/web.xml +++ /dev/null
@@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="ISO-8859-1"?> -<web-app - xmlns="http://java.sun.com/xml/ns/javaee" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" - version="2.5"> - <display-name>IRC-Proxy</display-name> - <context-param> - <param-name>org.eclipse.jetty.server.context.ManagedAttributes</param-name> - <param-value>org.eclipse.jetty.servlets.ProxyServlet.Logger,org.eclipse.jetty.servlets.ProxyServlet.ThreadPool,org.eclipse.jetty.servlets.ProxyServlet.HttpClient</param-value> - </context-param> - <servlet> - <servlet-name>irc-proxy</servlet-name> - <servlet-class>org.chromium.IRCProxyWebSocket</servlet-class> - <load-on-startup>1</load-on-startup> - </servlet> - <servlet-mapping> - <servlet-name>irc-proxy</servlet-name> - <url-pattern>/ws/*</url-pattern> - </servlet-mapping> -</web-app> - -
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/addChannel.html b/chrome/common/extensions/docs/examples/extensions/irc/servlet/addChannel.html deleted file mode 100644 index c72cfab..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/addChannel.html +++ /dev/null
@@ -1,61 +0,0 @@ -<html> - <head> - <link rel="stylesheet" type="text/css" href="styles.css"> - <script src="jstemplate/util.js" type="text/javascript"></script> - <script src="jstemplate/jsevalcontext.js" type="text/javascript"></script> - <script src="jstemplate/jstemplate.js" type="text/javascript"></script> - <script src="util.js" type="text/javascript"></script> - <script> -function addChannel() { - try { - var servers = JSON.parse(localStorage.servers || "[]"); - var channelName = $F('channel'); - var serverName = $F('serverSelect') - servers.forEach(function(server) { - if (server.name == serverName) { - server.channels = server.channels || []; - server.channels.forEach(function(channel) { - if (channel == channelName) { - throw channelName + " is already open"; - } - }); - server.channels.push(channelName); - } - }); - - localStorage.servers = JSON.stringify(servers); - window.opener.syncChannelList(); - window.opener.joinChannel(serverName, channelName); - window.close(); - } catch (ex) { - alert(ex); - } -} - -window.onload = function() { - var servers = JSON.parse(localStorage.servers || "[]"); - if (servers.length == 0) { - alert("You must first add a server connection"); - close(); - } - - jstProcess(new JsEvalContext(servers), $('serverSelect')); -} - - </script> - </head> - <body> - <div> - <select id="serverSelect"> - <option jsselect="$this" jscontent="name"></option> - </select> - <input id="channel" type="text" value="#channel"> - </div> - <div> - </div> - <div> - <input type="button" value="Add New Channel" - onclick="addChannel();"> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/addServer.html b/chrome/common/extensions/docs/examples/extensions/irc/servlet/addServer.html deleted file mode 100644 index dd6ed2e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/addServer.html +++ /dev/null
@@ -1,54 +0,0 @@ -<html> - <head> - <link rel="stylesheet" type="text/css" href="styles.css"> - <script src="util.js" type="text/javascript"></script> - <script> -function addServer() { - try { - var servers = JSON.parse(localStorage.servers || "[]"); - var serverName = $F('serverText'); - - servers.forEach(function(server) { - if (server.name == serverName) { - throw "Connection to " + serverName + " already established"; - } - }); - - var portValue = parseInt($F('serverPort')); - if (isNaN(portValue)) { - throw $F('serverPort') + " is not a valid port value"; - } - - var nickValue = $F('nick'); - var newServer = { - name: serverName, - port: portValue, - nick: nickValue, - channels: [] - }; - - servers.push(newServer); - - localStorage.servers = JSON.stringify(servers); - window.opener.addServerConnection(newServer); - close(); - } catch (ex) { - alert(ex); - } -} - </script> - </head> - <body> - <div> - <input id="serverText" type="text" value="irc.freenode.net"> - <input id="serverPort" type="text" value="6667"> - </div> - <div> - <input id="nick" type="text" value="nick"> - </div> - <div> - <input type="button" value="Add New Server" - onclick="addServer();"> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/index.html b/chrome/common/extensions/docs/examples/extensions/irc/servlet/index.html deleted file mode 100644 index 8b817da7..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/index.html +++ /dev/null
@@ -1,408 +0,0 @@ -<html> - <head> - <title>ChromiumIRC</title> - <link rel="stylesheet" type="text/css" href="styles.css"> - <script src="jstemplate/util.js" type="text/javascript"></script> - <script src="jstemplate/jsevalcontext.js" type="text/javascript"></script> - <script src="jstemplate/jstemplate.js" type="text/javascript"></script> - <script src="util.js" type="text/javascript"></script> - <script lang="JavaScript" src="irc.js"></script> - <script> - -var ircConnections = {}; - -// The server & channel configutation data is stored in localStorage.servers. -// These are setters and getters for this structure. -function servers() { - return JSON.parse(localStorage.servers || "[]"); -} -function setServers(servers) { - localStorage.servers = JSON.stringify(servers); -} - -// Channel list is a sorted list of "server#channel" strings. This maps to -// channel slides as represented in the UI. -function channelList() { - var channelList = []; - servers().forEach(function(server) { - server.channels = server.channels || []; - server.channels.forEach(function(channel) { - channelList.push(server.name + channel); - }); - }); - - channelList.sort(); - return channelList; -} - -window.onload = function() { - // Setup notifications. - window.onfocus = function() { - windowHasFocus = true; - clearNotifications(); - } - window.onblur = function() { - windowHasFocus = false; - } - - syncChannelList(); - - // Setup channel navigation and message entry. - function handleBodyKeyDown(event) { - switch (event.keyCode) { - case 37: // left arrow - slideTo(-1); - break; - case 39: // right arrow - slideTo(1); - break; - } - } - document.body.addEventListener('keydown', handleBodyKeyDown, false); - - // We don't want left & right arrow inside the text entry to move the channel - // slides. - $('typingDiv').addEventListener('keydown', function(event) { - event.stopPropagation(); - }); - $('entryText').addEventListener('keydown', function(event) { - if (event.keyCode == 13) { // RETURN key. - processEntryMessage(); - } - }); - - servers().forEach(addServerConnection); -}; - -window.onunload = function() { - ircConnections.forEach(function(irc) { - irc.disconnect(); - }); -} - -function addServerConnection(server) { - var ws = new WebSocket("ws://" + location.host + "/ws"); - var irc = new IRCConnection(server.name, server.port, server.nick, - ws.send.bind(ws), // sendFunc - ws.close.bind(ws)); // closeFunc - ws.onopen = irc.onOpened.bind(irc); - ws.onclose = irc.onClosed.bind(irc); - ws.onmessage = function(message) { - irc.onMessage(message.data); - }; - irc.onConnect = function(message) { - server.channels.forEach(function(channel) { - ircConnections[server.name].joinChannel(channel); - }); - }; - irc.onDisconnect = function(message) { - }; - irc.onText = function(channel, nick, message) { - checkForNickReference(server, channel, nick, message); - addMessage(server.name, channel, nick, new Date(), message); - }; - - ircConnections[server.name] = irc; -} - -function joinChannel(serverName, channelName) { - ircConnections[serverName].joinChannel(channelName); -} - -function removeChannelListener(channelName) { - return function(event) { - event.stopPropagation(); - - var servers = servers(); - servers.forEach(function(server) { - if (channelName.indexOf(server.name) == 0) { - for (var i = 0; server.channels.length; i++) { - if (channelName == server.name + server.channels[i]) { - ircConnections[server.name].quitChannel(server.channels[i]); - server.channels.splice(i, 1); - break; - } - } - } - }); - - setServers(servers); - syncChannelList(); - }; -} - -function syncChannelList() { - var channels = channelList(); - var channelSlides = $('channelSlides'); - var channelSlideProto = $('channelSlideProto'); - - var channelIndex = 0; - var slideIndex = 0; - - while(channelIndex < channels.length || - channels.length != channelSlides.children.length) { - var channel = channels[channelIndex]; - var slide = channelSlides.children[slideIndex]; - - if (slideIndex == channelSlides.children.length || - channel < slideChannel(slide)) { - // Add a new slide. - var newSlide = channelSlideProto.cloneNode(true); - jstProcess(new JsEvalContext({ name: channel }), newSlide); - newSlide.setAttribute("id", "channel-" + channel); - newSlide.style.display = ""; - if (slideIndex == channelSlides.children.length) { - channelSlides.appendChild(newSlide); - } else { - channelSlides.insertBefore(newSlide, slide); - } - newSlide.addEventListener('click', onClickMoveSlide); - childNodeWithClass(newSlide, "removeButton") - .addEventListener('click', removeChannelListener(channel)); - - slide = newSlide; - } else if (!channel || channel > slideChannel(slide)) { - // Delete a removed slide. - - // If the removed slide is the current slide, we have to pick a new - // current slide. - if (localStorage.currentSlide == slideChannel(slide)) { - if (slide.nextSibling) { - localStorage.currentSlide = slideChannel(slide.nextSibling); - } else if (channels.length == 0) { - localStorage.currentSlide = ""; - } else if (slideIndex < channelSlides.children.length) { - localStorage.currentSlide = - slideChannel(channelSlides.children[slideIndex - 1]); - } - } - channelSlides.removeChild(slide); - } else { - channelIndex++; - slideIndex++; - } - - slide.setAttribute("slide", "" + slideIndex - 1); - } - - slideTo(); -} - -function processEntryMessage() { - var message = $('entryText').value; - $('entryText').value = ""; - - if (!localStorage.currentSlide) { - alert('No current channel'); - return; - } - - var server; - var channel; - var nick; - servers().forEach(function(s) { - if (localStorage.currentSlide.indexOf(s.name) == 0) { - server = s.name; - nick = s.nick; - s.channels.forEach(function(c) { - if (localStorage.currentSlide == s.name + c) { - channel = c; - } - }); - } - }); - - addMessage(server, channel, nick, new Date(), message); - ircConnections[server].sendMessage([channel], message); -} - -function addMessage(server, channel, nick, time, body) { - messageLine = childNodeWithClass($('channelSlideProto'), "messageLine"); - var newMessageLine = messageLine.cloneNode(true); - - jstProcess(new JsEvalContext({ - 'nick': nick, - 'time': time, - 'body': body - }), newMessageLine); - newMessageLine.style.display = ""; - - var messageList = - childNodeWithClass($("channel-" + server + channel), "messageList"); - messageList.appendChild(newMessageLine); -} - -function formatTime(time) { - return ""; -} - -/** - * Slide Navigation. - */ - -// Returns the server#channel string value for a given |slide| element. -function slideChannel(slide) { - return childNodeWithClass(slide, "channel").innerText; -} - -// Handler for clicking on the visible portions of the previous & next slides. -function onClickMoveSlide() { - if (localStorage.currentSlide != slideChannel(this)) { - localStorage.currentSlide = slideChannel(this); - slideTo(); - } -} - -// Handles navigating between the channel slides. If |slideDelta| is given, -// it should specify the number of slides to move left (negative value) or right -// positive value. If |slideDelta| is not provided, It ensures that -// |localStorage.currentSlide| is navigated to. -function slideTo(slideDelta) { - var slide; - var slideNumber; - - if (localStorage.currentSlide) { - slide = document.getElementById("channel-" + localStorage.currentSlide); - if (slide) { - slideNumber = parseInt(slide.getAttribute("slide")); - } - } - if (isNaN(slideNumber) || !slide) { - slideNumber = 0; - } - if (typeof(slideDelta) == "number") { - slideNumber += slideDelta; - } - - var slides = document.getElementsByClassName("channelSlide"); - if (slideNumber < 0 || slideNumber == slides.length - 1) { - return; - } - - for (var i = 0; i < slides.length; i++) { - var slide = slides[i]; - var slideIndex = parseInt(slide.getAttribute("slide")) - slideNumber; - - if (slideIndex <= -2) { - slide.className = "channelSlide far-left"; - } - if (slideIndex >= 2) { - slide.className = "channelSlide far-right"; - } - - switch(slideIndex) { - case -1: - slide.className = "channelSlide left"; - break; - case 0: - slide.className = "channelSlide center"; - localStorage.currentSlide = slideChannel(slide); - break; - case 1: - slide.className = "channelSlide right"; - break; - } - } - - clearNotifications(); -} - -/** - * Notifications - */ -var windowHasFocus = false; -var notifications = {}; - -function clearNotifications() { - for (property in notifications) { - notifications[property].cancel(); - } - - notifications = {}; -} - -function checkForNickReference(server, channel, nick, message) { - if (windowHasFocus || !message || message.indexOf(server.nick) < 0) { - return; - } - - // Notifications will be enabled by the app install. Otherwise, don't notity. - if (Notification.permission != "granted") { - return; - } - - // Remove a previous notification from the same channel. Show the newer one. - if (notifications[server.name + channel]) { - notifications[server.name + channel].close(); - } - - var n = new Notification("On " + server.name + channel, { - icon: "https://www.google.com/favicon.ico", - body: nick + ": " + message, - }); - - n.onshow = function() {}; - n.onclose = function() { - delete notifications[server.name + channel]; - }; - - notifications[server.name + channel] = n; -} - </script> - </head> - <body> - <!-- TEMPLATES --> - <div id="channelSlideProto" style="display:none" class="channelSlide"> - <div class="channelControls"> - <div jscontent="name" class="channel"> - </div> - <div class="removeButton"> - x - </div> - </div> - <div class="channelSlideContainer"> - <div class="messageListContainer"> - <div class="messageList"> - <div jsselect="messages"> - <div class="messageLine"> - <div jscontent="nick" class="messageSender"></div>: - <div jscontent="body" class="messageBody"></div> - </div> - </div> - </div> - </div> - <div class="messageListSpacer">.</div> - </div> - </div> - - <div id="pageContainer"> - <div id="headerContainer"> - <div id="pageControls"> - <div onclick="window.open('addServer.html');"> - <div class="addControlLabel"> - add server - </div> - <div class="addButton"> - + - </div> - </div> - <div onclick=" window.open('addChannel.html');"> - <div class="addControlLabel"> - add channel - </div> - <div class="addButton"> - + - </div> - </div> - </div> - </div> - <div id="slideContainer"> - <div id="typingDiv"> - <input type="text" id="entryText" value=""> - </div> - <div style="" id="channelSlides"> - </div> - </div> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/irc.js b/chrome/common/extensions/docs/examples/extensions/irc/servlet/irc.js deleted file mode 100644 index 05cae96..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/irc.js +++ /dev/null
@@ -1,188 +0,0 @@ -/* - * IRCConnection is a simple implementation of the IRC protocol. A small - * subset of the IRC commands are implemented. To be functional, IRCConnection - * needs some mechanism of transport to be hooked up by: - * -Passing in |sendFunc| and |closeFunc| which an IRCConnection to use to send - * an IRC message command and to close the connection respectively. - * -Connecting the in-bound functions |onOpened|, |onMessage|, and |onClosed|, - * to the transport so that the IRCConnection can respond to the connection - * being opened, a message being received and the connection being closed. - */ - -function NoOp() {}; -function log(message) { console.log(message); }; - -function IRCConnection(server, port, nick, sendFunc, closeFunc) { - this.server = server; - this.port = port; - this.nick = nick; - this.connected = false; - - var that = this; - - /** - * Client API - */ - this.onConnect = NoOp; - this.onDisconnect = NoOp; - this.onText = NoOp; - this.onNotice = NoOp; - this.onNickReferenced = NoOp; - - this.joinChannel = function(channel) { - sendCommand(commands.JOIN, [channel], ""); - }; - - this.sendMessage = function(recipient, message) { - sendCommand(commands.PRIVMSG, [recipient], message); - }; - - this.quitChannel = function(channel) { - sendCommand(commands.PART, [channel], ""); - } - - this.disconnect = function(message) { - sendCommand(commands.QUIT, [], message); - closeFunc(); - } - - /** - * Transport Interface - * Whatever transport is used must provide and connect to the following - * in-bound events. - */ - this.onOpened = function() { - sendFunc(that.server + ":" + that.port); - sendCommand(commands.NICK, [this.nick], ""); - sendCommand(commands.USER, - ["chromium-irc-lib", "chromium-ircproxy", "*"], - "indigo"); - }; - - this.onMessage = function(message) { - log("<< " + message); - if (!message || !message.length) { - return; - } - - var parsed = parseMessage(message); - - // Respond to PING command. - if (parsed.command == commands.PING) { - sendCommand(commands.PONG, [], parsed.body); - return; - } - - // Process PRIVMSG. - if (parsed.command == commands.PRIVMSG) { - if (parsed.body.charCodeAt(0) == 1) { - // Ignore CTCP. - return; - } - that.onText(parsed.parameters[0], - parsed.prefix.split("!")[0], - parsed.body); - return; - } - - // TODO: Other IRC commands. - var commandCode = parseInt(parsed.command); - if (commandCode == NaN) { - return; - } - - switch(commandCode) { - case 001: // Server welcome message. - that.connected = true; - that.onConnect(parsed.body); - break; - case 002: - case 003: - case 004: - case 005: - if (!that.connected) { - that.connected = true; - that.onConnect(); - } - break; - case 433: // TODO(rafaelw): Nickname in use. - throw "NOT IMPLEMENTED"; - break; - default: - break; - } - } - - this.onClosed = function() { - that.connected = false; - that.onDisconnect(); - }; - - /** - * IRC Implementation - * What follows in a minimal implementation of the IRC protocol. - * Only |commands| are currently implemented. - */ - var commands = { - JOIN: "JOIN", - NICK: "NICK", - NOTICE: "NOTICE", - PART: "PART", - PING: "PING", - PONG: "PONG", - PRIVMSG: "PRIVMSG", - QUIT: "QUIT", - USER: "USER" - }; - - function parseMessage(message) { - var parsed = {}; - parsed.prefix = ""; - parsed.command = ""; - parsed.parameters = []; - parsed.body = ""; - - // Trim trailing CRLF. - var crlfIndex = message.indexOf("\r\n"); - if(crlfIndex >= 0) { - message = message.substring(0, crlfIndex); - } - - // If leading character is ':', the message starts with a prefix. - if (message.indexOf(':') == 0) { - parsed.prefix = message.substring(1, message.indexOf(" ")); - message = message.substring(parsed.prefix.length + 2); - - // Forward past extra whitespace. - while(message.indexOf(" ") == 0) { - message = message.substring(1); - } - } - - // If there is still a ':', then the message has trailing body. - var bodyMarker = message.indexOf(':'); - if (bodyMarker >= 0) { - parsed.body = message.substring(bodyMarker + 1); - message = message.substring(0, bodyMarker); - } - - parsed.parameters = message.split(" "); - parsed.command = parsed.parameters.shift(); // First param is the command. - - return parsed; - } - - function sendCommand(command, params, message) { - var line = command; - if (params && params.length > 0) { - line += " " + params.join(" "); - } - if (message && message.length > 0) { - line += " :" + message; - } - - log(">> " + line); - line += "\r\n"; - sendFunc(line); - }; -};
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/jsevalcontext.js b/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/jsevalcontext.js deleted file mode 100644 index e3abe78..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/jsevalcontext.js +++ /dev/null
@@ -1,409 +0,0 @@ -// Copyright 2006 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied. See the License for the specific language governing -// permissions and limitations under the License. -/** - * Author: Steffen Meschkat <mesch@google.com> - * - * @fileoverview This class is used to evaluate expressions in a local - * context. Used by JstProcessor. - */ - - -/** - * Names of special variables defined by the jstemplate evaluation - * context. These can be used in js expression in jstemplate - * attributes. - */ -var VAR_index = '$index'; -var VAR_count = '$count'; -var VAR_this = '$this'; -var VAR_context = '$context'; -var VAR_top = '$top'; - - -/** - * The name of the global variable which holds the value to be returned if - * context evaluation results in an error. - * Use JsEvalContext.setGlobal(GLOB_default, value) to set this. - */ -var GLOB_default = '$default'; - - -/** - * Un-inlined literals, to avoid object creation in IE6. TODO(mesch): - * So far, these are only used here, but we could use them thoughout - * the code and thus move them to constants.js. - */ -var CHAR_colon = ':'; -var REGEXP_semicolon = /\s*;\s*/; - - -/** - * See constructor_() - * @param {Object|null} opt_data - * @param {Object} opt_parent - * @constructor - */ -function JsEvalContext(opt_data, opt_parent) { - this.constructor_.apply(this, arguments); -} - -/** - * Context for processing a jstemplate. The context contains a context - * object, whose properties can be referred to in jstemplate - * expressions, and it holds the locally defined variables. - * - * @param {Object|null} opt_data The context object. Null if no context. - * - * @param {Object} opt_parent The parent context, from which local - * variables are inherited. Normally the context object of the parent - * context is the object whose property the parent object is. Null for the - * context of the root object. - */ -JsEvalContext.prototype.constructor_ = function(opt_data, opt_parent) { - var me = this; - - /** - * The context for variable definitions in which the jstemplate - * expressions are evaluated. Other than for the local context, - * which replaces the parent context, variable definitions of the - * parent are inherited. The special variable $this points to data_. - * - * If this instance is recycled from the cache, then the property is - * already initialized. - * - * @type {Object} - */ - if (!me.vars_) { - me.vars_ = {}; - } - if (opt_parent) { - // If there is a parent node, inherit local variables from the - // parent. - copyProperties(me.vars_, opt_parent.vars_); - } else { - // If a root node, inherit global symbols. Since every parent - // chain has a root with no parent, global variables will be - // present in the case above too. This means that globals can be - // overridden by locals, as it should be. - copyProperties(me.vars_, JsEvalContext.globals_); - } - - /** - * The current context object is assigned to the special variable - * $this so it is possible to use it in expressions. - * @type Object - */ - me.vars_[VAR_this] = opt_data; - - /** - * The entire context structure is exposed as a variable so it can be - * passed to javascript invocations through jseval. - */ - me.vars_[VAR_context] = me; - - /** - * The local context of the input data in which the jstemplate - * expressions are evaluated. Notice that this is usually an Object, - * but it can also be a scalar value (and then still the expression - * $this can be used to refer to it). Notice this can even be value, - * undefined or null. Hence, we have to protect jsexec() from using - * undefined or null, yet we want $this to reflect the true value of - * the current context. Thus we assign the original value to $this, - * above, but for the expression context we replace null and - * undefined by the empty string. - * - * @type {Object|null} - */ - me.data_ = getDefaultObject(opt_data, STRING_empty); - - if (!opt_parent) { - // If this is a top-level context, create a variable reference to the data - // to allow for accessing top-level properties of the original context - // data from child contexts. - me.vars_[VAR_top] = me.data_; - } -}; - - -/** - * A map of globally defined symbols. Every instance of JsExprContext - * inherits them in its vars_. - * @type Object - */ -JsEvalContext.globals_ = {} - - -/** - * Sets a global symbol. It will be available like a variable in every - * JsEvalContext instance. This is intended mainly to register - * immutable global objects, such as functions, at load time, and not - * to add global data at runtime. I.e. the same objections as to - * global variables in general apply also here. (Hence the name - * "global", and not "global var".) - * @param {string} name - * @param {Object|null} value - */ -JsEvalContext.setGlobal = function(name, value) { - JsEvalContext.globals_[name] = value; -}; - - -/** - * Set the default value to be returned if context evaluation results in an - * error. (This can occur if a non-existent value was requested). - */ -JsEvalContext.setGlobal(GLOB_default, null); - - -/** - * A cache to reuse JsEvalContext instances. (IE6 perf) - * - * @type Array<JsEvalContext> - */ -JsEvalContext.recycledInstances_ = []; - - -/** - * A factory to create a JsEvalContext instance, possibly reusing - * one from recycledInstances_. (IE6 perf) - * - * @param {Object} opt_data - * @param {JsEvalContext} opt_parent - * @return {JsEvalContext} - */ -JsEvalContext.create = function(opt_data, opt_parent) { - if (jsLength(JsEvalContext.recycledInstances_) > 0) { - var instance = JsEvalContext.recycledInstances_.pop(); - JsEvalContext.call(instance, opt_data, opt_parent); - return instance; - } else { - return new JsEvalContext(opt_data, opt_parent); - } -}; - - -/** - * Recycle a used JsEvalContext instance, so we can avoid creating one - * the next time we need one. (IE6 perf) - * - * @param {JsEvalContext} instance - */ -JsEvalContext.recycle = function(instance) { - for (var i in instance.vars_) { - // NOTE(mesch): We avoid object creation here. (IE6 perf) - delete instance.vars_[i]; - } - instance.data_ = null; - JsEvalContext.recycledInstances_.push(instance); -}; - - -/** - * Executes a function created using jsEvalToFunction() in the context - * of vars, data, and template. - * - * @param {Function} exprFunction A javascript function created from - * a jstemplate attribute value. - * - * @param {Element} template DOM node of the template. - * - * @return {Object|null} The value of the expression from which - * exprFunction was created in the current js expression context and - * the context of template. - */ -JsEvalContext.prototype.jsexec = function(exprFunction, template) { - try { - return exprFunction.call(template, this.vars_, this.data_); - } catch (e) { - log('jsexec EXCEPTION: ' + e + ' at ' + template + - ' with ' + exprFunction); - return JsEvalContext.globals_[GLOB_default]; - } -}; - - -/** - * Clones the current context for a new context object. The cloned - * context has the data object as its context object and the current - * context as its parent context. It also sets the $index variable to - * the given value. This value usually is the position of the data - * object in a list for which a template is instantiated multiply. - * - * @param {Object} data The new context object. - * - * @param {number} index Position of the new context when multiply - * instantiated. (See implementation of jstSelect().) - * - * @param {number} count The total number of contexts that were multiply - * instantiated. (See implementation of jstSelect().) - * - * @return {JsEvalContext} - */ -JsEvalContext.prototype.clone = function(data, index, count) { - var ret = JsEvalContext.create(data, this); - ret.setVariable(VAR_index, index); - ret.setVariable(VAR_count, count); - return ret; -}; - - -/** - * Binds a local variable to the given value. If set from jstemplate - * jsvalue expressions, variable names must start with $, but in the - * API they only have to be valid javascript identifier. - * - * @param {string} name - * - * @param {Object?} value - */ -JsEvalContext.prototype.setVariable = function(name, value) { - this.vars_[name] = value; -}; - - -/** - * Returns the value bound to the local variable of the given name, or - * undefined if it wasn't set. There is no way to distinguish a - * variable that wasn't set from a variable that was set to - * undefined. Used mostly for testing. - * - * @param {string} name - * - * @return {Object?} value - */ -JsEvalContext.prototype.getVariable = function(name) { - return this.vars_[name]; -}; - - -/** - * Evaluates a string expression within the scope of this context - * and returns the result. - * - * @param {string} expr A javascript expression - * @param {Element} opt_template An optional node to serve as "this" - * - * @return {Object?} value - */ -JsEvalContext.prototype.evalExpression = function(expr, opt_template) { - var exprFunction = jsEvalToFunction(expr); - return this.jsexec(exprFunction, opt_template); -}; - - -/** - * Uninlined string literals for jsEvalToFunction() (IE6 perf). - */ -var STRING_a = 'a_'; -var STRING_b = 'b_'; -var STRING_with = 'with (a_) with (b_) return '; - - -/** - * Cache for jsEvalToFunction results. - * @type Object - */ -JsEvalContext.evalToFunctionCache_ = {}; - - -/** - * Evaluates the given expression as the body of a function that takes - * vars and data as arguments. Since the resulting function depends - * only on expr, we cache the result so we save some Function - * invocations, and some object creations in IE6. - * - * @param {string} expr A javascript expression. - * - * @return {Function} A function that returns the value of expr in the - * context of vars and data. - */ -function jsEvalToFunction(expr) { - if (!JsEvalContext.evalToFunctionCache_[expr]) { - try { - // NOTE(mesch): The Function constructor is faster than eval(). - JsEvalContext.evalToFunctionCache_[expr] = - new Function(STRING_a, STRING_b, STRING_with + expr); - } catch (e) { - log('jsEvalToFunction (' + expr + ') EXCEPTION ' + e); - } - } - return JsEvalContext.evalToFunctionCache_[expr]; -} - - -/** - * Evaluates the given expression to itself. This is meant to pass - * through string attribute values. - * - * @param {string} expr - * - * @return {string} - */ -function jsEvalToSelf(expr) { - return expr; -} - - -/** - * Parses the value of the jsvalues attribute in jstemplates: splits - * it up into a map of labels and expressions, and creates functions - * from the expressions that are suitable for execution by - * JsEvalContext.jsexec(). All that is returned as a flattened array - * of pairs of a String and a Function. - * - * @param {string} expr - * - * @return {Array} - */ -function jsEvalToValues(expr) { - // TODO(mesch): It is insufficient to split the values by simply - // finding semi-colons, as the semi-colon may be part of a string - // constant or escaped. - var ret = []; - var values = expr.split(REGEXP_semicolon); - for (var i = 0, I = jsLength(values); i < I; ++i) { - var colon = values[i].indexOf(CHAR_colon); - if (colon < 0) { - continue; - } - var label = stringTrim(values[i].substr(0, colon)); - var value = jsEvalToFunction(values[i].substr(colon + 1)); - ret.push(label, value); - } - return ret; -} - - -/** - * Parses the value of the jseval attribute of jstemplates: splits it - * up into a list of expressions, and creates functions from the - * expressions that are suitable for execution by - * JsEvalContext.jsexec(). All that is returned as an Array of - * Function. - * - * @param {string} expr - * - * @return {Array<Function>} - */ -function jsEvalToExpressions(expr) { - var ret = []; - var values = expr.split(REGEXP_semicolon); - for (var i = 0, I = jsLength(values); i < I; ++i) { - if (values[i]) { - var value = jsEvalToFunction(values[i]); - ret.push(value); - } - } - return ret; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/jstemplate.js b/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/jstemplate.js deleted file mode 100644 index 4024892..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/jstemplate.js +++ /dev/null
@@ -1,1017 +0,0 @@ -// Copyright 2006 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied. See the License for the specific language governing -// permissions and limitations under the License. -/** - * Author: Steffen Meschkat <mesch@google.com> - * - * @fileoverview A simple formatter to project JavaScript data into - * HTML templates. The template is edited in place. I.e. in order to - * instantiate a template, clone it from the DOM first, and then - * process the cloned template. This allows for updating of templates: - * If the templates is processed again, changed values are merely - * updated. - * - * NOTE(mesch): IE DOM doesn't have importNode(). - * - * NOTE(mesch): The property name "length" must not be used in input - * data, see comment in jstSelect_(). - */ - - -/** - * Names of jstemplate attributes. These attributes are attached to - * normal HTML elements and bind expression context data to the HTML - * fragment that is used as template. - */ -var ATT_select = 'jsselect'; -var ATT_instance = 'jsinstance'; -var ATT_display = 'jsdisplay'; -var ATT_values = 'jsvalues'; -var ATT_vars = 'jsvars'; -var ATT_eval = 'jseval'; -var ATT_transclude = 'transclude'; -var ATT_content = 'jscontent'; -var ATT_skip = 'jsskip'; - - -/** - * Name of the attribute that caches a reference to the parsed - * template processing attribute values on a template node. - */ -var ATT_jstcache = 'jstcache'; - - -/** - * Name of the property that caches the parsed template processing - * attribute values on a template node. - */ -var PROP_jstcache = '__jstcache'; - - -/** - * ID of the element that contains dynamically loaded jstemplates. - */ -var STRING_jsts = 'jsts'; - - -/** - * Un-inlined string literals, to avoid object creation in - * IE6. - */ -var CHAR_asterisk = '*'; -var CHAR_dollar = '$'; -var CHAR_period = '.'; -var CHAR_ampersand = '&'; -var STRING_div = 'div'; -var STRING_id = 'id'; -var STRING_asteriskzero = '*0'; -var STRING_zero = '0'; - - -/** - * HTML template processor. Data values are bound to HTML templates - * using the attributes transclude, jsselect, jsdisplay, jscontent, - * jsvalues. The template is modifed in place. The values of those - * attributes are JavaScript expressions that are evaluated in the - * context of the data object fragment. - * - * @param {JsEvalContext} context Context created from the input data - * object. - * - * @param {Element} template DOM node of the template. This will be - * processed in place. After processing, it will still be a valid - * template that, if processed again with the same data, will remain - * unchanged. - * - * @param {boolean} opt_debugging Optional flag to collect debugging - * information while processing the template. Only takes effect - * in MAPS_DEBUG. - */ -function jstProcess(context, template, opt_debugging) { - var processor = new JstProcessor; - if (MAPS_DEBUG && opt_debugging) { - processor.setDebugging(opt_debugging); - } - JstProcessor.prepareTemplate_(template); - - /** - * Caches the document of the template node, so we don't have to - * access it through ownerDocument. - * @type Document - */ - processor.document_ = ownerDocument(template); - - processor.run_(bindFully(processor, processor.jstProcessOuter_, - context, template)); - if (MAPS_DEBUG && opt_debugging) { - log('jstProcess:' + '\n' + processor.getLogs().join('\n')); - } -} - - -/** - * Internal class used by jstemplates to maintain context. This is - * necessary to process deep templates in Safari which has a - * relatively shallow maximum recursion depth of 100. - * @class - * @constructor - */ -function JstProcessor() { - if (MAPS_DEBUG) { - /** - * An array of logging messages. These are collected during processing - * and dumped to the console at the end. - * @type Array<string> - */ - this.logs_ = []; - } -} - - -/** - * Counter to generate node ids. These ids will be stored in - * ATT_jstcache and be used to lookup the preprocessed js attributes - * from the jstcache_. The id is stored in an attribute so it - * suvives cloneNode() and thus cloned template nodes can share the - * same cache entry. - * @type number - */ -JstProcessor.jstid_ = 0; - - -/** - * Map from jstid to processed js attributes. - * @type Object - */ -JstProcessor.jstcache_ = {}; - -/** - * The neutral cache entry. Used for all nodes that don't have any - * jst attributes. We still set the jsid attribute on those nodes so - * we can avoid to look again for all the other jst attributes that - * aren't there. Remember: not only the processing of the js - * attribute values is expensive and we thus want to cache it. The - * access to the attributes on the Node in the first place is - * expensive too. - */ -JstProcessor.jstcache_[0] = {}; - - -/** - * Map from concatenated attribute string to jstid. - * The key is the concatenation of all jst atributes found on a node - * formatted as "name1=value1&name2=value2&...", in the order defined by - * JST_ATTRIBUTES. The value is the id of the jstcache_ entry that can - * be used for this node. This allows the reuse of cache entries in cases - * when a cached entry already exists for a given combination of attribute - * values. (For example when two different nodes in a template share the same - * JST attributes.) - * @type Object - */ -JstProcessor.jstcacheattributes_ = {}; - - -/** - * Map for storing temporary attribute values in prepareNode_() so they don't - * have to be retrieved twice. (IE6 perf) - * @type Object - */ -JstProcessor.attributeValues_ = {}; - - -/** - * A list for storing non-empty attributes found on a node in prepareNode_(). - * The array is global since it can be reused - this way there is no need to - * construct a new array object for each invocation. (IE6 perf) - * @type Array - */ -JstProcessor.attributeList_ = []; - - -/** - * Prepares the template: preprocesses all jstemplate attributes. - * - * @param {Element} template - */ -JstProcessor.prepareTemplate_ = function(template) { - if (!template[PROP_jstcache]) { - domTraverseElements(template, function(node) { - JstProcessor.prepareNode_(node); - }); - } -}; - - -/** - * A list of attributes we use to specify jst processing instructions, - * and the functions used to parse their values. - * - * @type Array<Array> - */ -var JST_ATTRIBUTES = [ - [ ATT_select, jsEvalToFunction ], - [ ATT_display, jsEvalToFunction ], - [ ATT_values, jsEvalToValues ], - [ ATT_vars, jsEvalToValues ], - [ ATT_eval, jsEvalToExpressions ], - [ ATT_transclude, jsEvalToSelf ], - [ ATT_content, jsEvalToFunction ], - [ ATT_skip, jsEvalToFunction ] -]; - - -/** - * Prepares a single node: preprocesses all template attributes of the - * node, and if there are any, assigns a jsid attribute and stores the - * preprocessed attributes under the jsid in the jstcache. - * - * @param {Element} node - * - * @return {Object} The jstcache entry. The processed jst attributes - * are properties of this object. If the node has no jst attributes, - * returns an object with no properties (the jscache_[0] entry). - */ -JstProcessor.prepareNode_ = function(node) { - // If the node already has a cache property, return it. - if (node[PROP_jstcache]) { - return node[PROP_jstcache]; - } - - // If it is not found, we always set the PROP_jstcache property on the node. - // Accessing the property is faster than executing getAttribute(). If we - // don't find the property on a node that was cloned in jstSelect_(), we - // will fall back to check for the attribute and set the property - // from cache. - - // If the node has an attribute indexing a cache object, set it as a property - // and return it. - var jstid = domGetAttribute(node, ATT_jstcache); - if (jstid != null) { - return node[PROP_jstcache] = JstProcessor.jstcache_[jstid]; - } - - var attributeValues = JstProcessor.attributeValues_; - var attributeList = JstProcessor.attributeList_; - attributeList.length = 0; - - // Look for interesting attributes. - for (var i = 0, I = jsLength(JST_ATTRIBUTES); i < I; ++i) { - var name = JST_ATTRIBUTES[i][0]; - var value = domGetAttribute(node, name); - attributeValues[name] = value; - if (value != null) { - attributeList.push(name + "=" + value); - } - } - - // If none found, mark this node to prevent further inspection, and return - // an empty cache object. - if (attributeList.length == 0) { - domSetAttribute(node, ATT_jstcache, STRING_zero); - return node[PROP_jstcache] = JstProcessor.jstcache_[0]; - } - - // If we already have a cache object corresponding to these attributes, - // annotate the node with it, and return it. - var attstring = attributeList.join(CHAR_ampersand); - if (jstid = JstProcessor.jstcacheattributes_[attstring]) { - domSetAttribute(node, ATT_jstcache, jstid); - return node[PROP_jstcache] = JstProcessor.jstcache_[jstid]; - } - - // Otherwise, build a new cache object. - var jstcache = {}; - for (var i = 0, I = jsLength(JST_ATTRIBUTES); i < I; ++i) { - var att = JST_ATTRIBUTES[i]; - var name = att[0]; - var parse = att[1]; - var value = attributeValues[name]; - if (value != null) { - jstcache[name] = parse(value); - if (MAPS_DEBUG) { - jstcache.jstAttributeValues = jstcache.jstAttributeValues || {}; - jstcache.jstAttributeValues[name] = value; - } - } - } - - jstid = STRING_empty + ++JstProcessor.jstid_; - domSetAttribute(node, ATT_jstcache, jstid); - JstProcessor.jstcache_[jstid] = jstcache; - JstProcessor.jstcacheattributes_[attstring] = jstid; - - return node[PROP_jstcache] = jstcache; -}; - - -/** - * Runs the given function in our state machine. - * - * It's informative to view the set of all function calls as a tree: - * - nodes are states - * - edges are state transitions, implemented as calls to the pending - * functions in the stack. - * - pre-order function calls are downward edges (recursion into call). - * - post-order function calls are upward edges (return from call). - * - leaves are nodes which do not recurse. - * We represent the call tree as an array of array of calls, indexed as - * stack[depth][index]. Here [depth] indexes into the call stack, and - * [index] indexes into the call queue at that depth. We require a call - * queue so that a node may branch to more than one child - * (which will be called serially), typically due to a loop structure. - * - * @param {Function} f The first function to run. - */ -JstProcessor.prototype.run_ = function(f) { - var me = this; - - /** - * A stack of queues of pre-order calls. - * The inner arrays (constituent queues) are structured as - * [ arg2, arg1, method, arg2, arg1, method, ...] - * ie. a flattened array of methods with 2 arguments, in reverse order - * for efficient push/pop. - * - * The outer array is a stack of such queues. - * - * @type Array<Array> - */ - var calls = me.calls_ = []; - - /** - * The index into the queue for each depth. NOTE: Alternative would - * be to maintain the queues in reverse order (popping off of the - * end) but the repeated calls to .pop() consumed 90% of this - * function's execution time. - * @type Array<number> - */ - var queueIndices = me.queueIndices_ = []; - - /** - * A pool of empty arrays. Minimizes object allocation for IE6's benefit. - * @type Array<Array> - */ - var arrayPool = me.arrayPool_ = []; - - f(); - var queue, queueIndex; - var method, arg1, arg2; - var temp; - while (calls.length) { - queue = calls[calls.length - 1]; - queueIndex = queueIndices[queueIndices.length - 1]; - if (queueIndex >= queue.length) { - me.recycleArray_(calls.pop()); - queueIndices.pop(); - continue; - } - - // Run the first function in the queue. - method = queue[queueIndex++]; - arg1 = queue[queueIndex++]; - arg2 = queue[queueIndex++]; - queueIndices[queueIndices.length - 1] = queueIndex; - method.call(me, arg1, arg2); - } -}; - - -/** - * Pushes one or more functions onto the stack. These will be run in sequence, - * interspersed with any recursive calls that they make. - * - * This method takes ownership of the given array! - * - * @param {Array} args Array of method calls structured as - * [ method, arg1, arg2, method, arg1, arg2, ... ] - */ -JstProcessor.prototype.push_ = function(args) { - this.calls_.push(args); - this.queueIndices_.push(0); -}; - - -/** - * Enable/disable debugging. - * @param {boolean} debugging New state - */ -JstProcessor.prototype.setDebugging = function(debugging) { - if (MAPS_DEBUG) { - this.debugging_ = debugging; - } -}; - - -JstProcessor.prototype.createArray_ = function() { - if (this.arrayPool_.length) { - return this.arrayPool_.pop(); - } else { - return []; - } -}; - - -JstProcessor.prototype.recycleArray_ = function(array) { - arrayClear(array); - this.arrayPool_.push(array); -}; - -/** - * Implements internals of jstProcess. This processes the two - * attributes transclude and jsselect, which replace or multiply - * elements, hence the name "outer". The remainder of the attributes - * is processed in jstProcessInner_(), below. That function - * jsProcessInner_() only processes attributes that affect an existing - * node, but doesn't create or destroy nodes, hence the name - * "inner". jstProcessInner_() is called through jstSelect_() if there - * is a jsselect attribute (possibly for newly created clones of the - * current template node), or directly from here if there is none. - * - * @param {JsEvalContext} context - * - * @param {Element} template - */ -JstProcessor.prototype.jstProcessOuter_ = function(context, template) { - var me = this; - - var jstAttributes = me.jstAttributes_(template); - if (MAPS_DEBUG && me.debugging_) { - me.logState_('Outer', template, jstAttributes.jstAttributeValues); - } - - var transclude = jstAttributes[ATT_transclude]; - if (transclude) { - var tr = jstGetTemplate(transclude); - if (tr) { - domReplaceChild(tr, template); - var call = me.createArray_(); - call.push(me.jstProcessOuter_, context, tr); - me.push_(call); - } else { - domRemoveNode(template); - } - return; - } - - var select = jstAttributes[ATT_select]; - if (select) { - me.jstSelect_(context, template, select); - } else { - me.jstProcessInner_(context, template); - } -}; - - -/** - * Implements internals of jstProcess. This processes all attributes - * except transclude and jsselect. It is called either from - * jstSelect_() for nodes that have a jsselect attribute so that the - * jsselect attribute will not be processed again, or else directly - * from jstProcessOuter_(). See the comment on jstProcessOuter_() for - * an explanation of the name. - * - * @param {JsEvalContext} context - * - * @param {Element} template - */ -JstProcessor.prototype.jstProcessInner_ = function(context, template) { - var me = this; - - var jstAttributes = me.jstAttributes_(template); - if (MAPS_DEBUG && me.debugging_) { - me.logState_('Inner', template, jstAttributes.jstAttributeValues); - } - - // NOTE(mesch): See NOTE on ATT_content why this is a separate - // attribute, and not a special value in ATT_values. - var display = jstAttributes[ATT_display]; - if (display) { - var shouldDisplay = context.jsexec(display, template); - if (MAPS_DEBUG && me.debugging_) { - me.logs_.push(ATT_display + ': ' + shouldDisplay + '<br/>'); - } - if (!shouldDisplay) { - displayNone(template); - return; - } - displayDefault(template); - } - - // NOTE(mesch): jsvars is evaluated before jsvalues, because it's - // more useful to be able to use var values in attribute value - // expressions than vice versa. - var values = jstAttributes[ATT_vars]; - if (values) { - me.jstVars_(context, template, values); - } - - values = jstAttributes[ATT_values]; - if (values) { - me.jstValues_(context, template, values); - } - - // Evaluate expressions immediately. Useful for hooking callbacks - // into jstemplates. - // - // NOTE(mesch): Evaluation order is sometimes significant, e.g. when - // the expression evaluated in jseval relies on the values set in - // jsvalues, so it needs to be evaluated *after* - // jsvalues. TODO(mesch): This is quite arbitrary, it would be - // better if this would have more necessity to it. - var expressions = jstAttributes[ATT_eval]; - if (expressions) { - for (var i = 0, I = jsLength(expressions); i < I; ++i) { - context.jsexec(expressions[i], template); - } - } - - var skip = jstAttributes[ATT_skip]; - if (skip) { - var shouldSkip = context.jsexec(skip, template); - if (MAPS_DEBUG && me.debugging_) { - me.logs_.push(ATT_skip + ': ' + shouldSkip + '<br/>'); - } - if (shouldSkip) return; - } - - // NOTE(mesch): content is a separate attribute, instead of just a - // special value mentioned in values, for two reasons: (1) it is - // fairly common to have only mapped content, and writing - // content="expr" is shorter than writing values="content:expr", and - // (2) the presence of content actually terminates traversal, and we - // need to check for that. Display is a separate attribute for a - // reason similar to the second, in that its presence *may* - // terminate traversal. - var content = jstAttributes[ATT_content]; - if (content) { - me.jstContent_(context, template, content); - - } else { - // Newly generated children should be ignored, so we explicitly - // store the children to be processed. - var queue = me.createArray_(); - for (var c = template.firstChild; c; c = c.nextSibling) { - if (c.nodeType == DOM_ELEMENT_NODE) { - queue.push(me.jstProcessOuter_, context, c); - } - } - if (queue.length) me.push_(queue); - } -}; - - -/** - * Implements the jsselect attribute: evalutes the value of the - * jsselect attribute in the current context, with the current - * variable bindings (see JsEvalContext.jseval()). If the value is an - * array, the current template node is multiplied once for every - * element in the array, with the array element being the context - * object. If the array is empty, or the value is undefined, then the - * current template node is dropped. If the value is not an array, - * then it is just made the context object. - * - * @param {JsEvalContext} context The current evaluation context. - * - * @param {Element} template The currently processed node of the template. - * - * @param {Function} select The javascript expression to evaluate. - * - * @notypecheck FIXME(hmitchell): See OCL6434950. instance and value need - * type checks. - */ -JstProcessor.prototype.jstSelect_ = function(context, template, select) { - var me = this; - - var value = context.jsexec(select, template); - - // Enable reprocessing: if this template is reprocessed, then only - // fill the section instance here. Otherwise do the cardinal - // processing of a new template. - var instance = domGetAttribute(template, ATT_instance); - - var instanceLast = false; - if (instance) { - if (instance.charAt(0) == CHAR_asterisk) { - instance = parseInt10(instance.substr(1)); - instanceLast = true; - } else { - instance = parseInt10(/** @type string */(instance)); - } - } - - // The expression value instanceof Array is occasionally false for - // arrays, seen in Firefox. Thus we recognize an array as an object - // which is not null that has a length property. Notice that this - // also matches input data with a length property, so this property - // name should be avoided in input data. - var multiple = isArray(value); - var count = multiple ? jsLength(value) : 1; - var multipleEmpty = (multiple && count == 0); - - if (multiple) { - if (multipleEmpty) { - // For an empty array, keep the first template instance and mark - // it last. Remove all other template instances. - if (!instance) { - domSetAttribute(template, ATT_instance, STRING_asteriskzero); - displayNone(template); - } else { - domRemoveNode(template); - } - - } else { - displayDefault(template); - // For a non empty array, create as many template instances as - // are needed. If the template is first processed, as many - // template instances are needed as there are values in the - // array. If the template is reprocessed, new template instances - // are only needed if there are more array values than template - // instances. Those additional instances are created by - // replicating the last template instance. - // - // When the template is first processed, there is no jsinstance - // attribute. This is indicated by instance === null, except in - // opera it is instance === "". Notice also that the === is - // essential, because 0 == "", presumably via type coercion to - // boolean. - if (instance === null || instance === STRING_empty || - (instanceLast && instance < count - 1)) { - // A queue of calls to push. - var queue = me.createArray_(); - - var instancesStart = instance || 0; - var i, I, clone; - for (i = instancesStart, I = count - 1; i < I; ++i) { - var node = domCloneNode(template); - domInsertBefore(node, template); - - jstSetInstance(/** @type Element */(node), value, i); - clone = context.clone(value[i], i, count); - - queue.push(me.jstProcessInner_, clone, node, - JsEvalContext.recycle, clone, null); - - } - // Push the originally present template instance last to keep - // the order aligned with the DOM order, because the newly - // created template instances are inserted *before* the - // original instance. - jstSetInstance(template, value, i); - clone = context.clone(value[i], i, count); - queue.push(me.jstProcessInner_, clone, template, - JsEvalContext.recycle, clone, null); - me.push_(queue); - } else if (instance < count) { - var v = value[instance]; - - jstSetInstance(template, value, instance); - var clone = context.clone(v, instance, count); - var queue = me.createArray_(); - queue.push(me.jstProcessInner_, clone, template, - JsEvalContext.recycle, clone, null); - me.push_(queue); - } else { - domRemoveNode(template); - } - } - } else { - if (value == null) { - displayNone(template); - } else { - displayDefault(template); - var clone = context.clone(value, 0, 1); - var queue = me.createArray_(); - queue.push(me.jstProcessInner_, clone, template, - JsEvalContext.recycle, clone, null); - me.push_(queue); - } - } -}; - - -/** - * Implements the jsvars attribute: evaluates each of the values and - * assigns them to variables in the current context. Similar to - * jsvalues, except that all values are treated as vars, independent - * of their names. - * - * @param {JsEvalContext} context Current evaluation context. - * - * @param {Element} template Currently processed template node. - * - * @param {Array} values Processed value of the jsvalues attribute: a - * flattened array of pairs. The second element in the pair is a - * function that can be passed to jsexec() for evaluation in the - * current jscontext, and the first element is the variable name that - * the value returned by jsexec is assigned to. - */ -JstProcessor.prototype.jstVars_ = function(context, template, values) { - for (var i = 0, I = jsLength(values); i < I; i += 2) { - var label = values[i]; - var value = context.jsexec(values[i+1], template); - context.setVariable(label, value); - } -}; - - -/** - * Implements the jsvalues attribute: evaluates each of the values and - * assigns them to variables in the current context (if the name - * starts with '$', javascript properties of the current template node - * (if the name starts with '.'), or DOM attributes of the current - * template node (otherwise). Since DOM attribute values are always - * strings, the value is coerced to string in the latter case, - * otherwise it's the uncoerced javascript value. - * - * @param {JsEvalContext} context Current evaluation context. - * - * @param {Element} template Currently processed template node. - * - * @param {Array} values Processed value of the jsvalues attribute: a - * flattened array of pairs. The second element in the pair is a - * function that can be passed to jsexec() for evaluation in the - * current jscontext, and the first element is the label that - * determines where the value returned by jsexec is assigned to. - */ -JstProcessor.prototype.jstValues_ = function(context, template, values) { - for (var i = 0, I = jsLength(values); i < I; i += 2) { - var label = values[i]; - var value = context.jsexec(values[i+1], template); - - if (label.charAt(0) == CHAR_dollar) { - // A jsvalues entry whose name starts with $ sets a local - // variable. - context.setVariable(label, value); - - } else if (label.charAt(0) == CHAR_period) { - // A jsvalues entry whose name starts with . sets a property of - // the current template node. The name may have further dot - // separated components, which are translated into namespace - // objects. This specifically allows to set properties on .style - // using jsvalues. NOTE(mesch): Setting the style attribute has - // no effect in IE and hence should not be done anyway. - var nameSpaceLabel = label.substr(1).split(CHAR_period); - var nameSpaceObject = template; - var nameSpaceDepth = jsLength(nameSpaceLabel); - for (var j = 0, J = nameSpaceDepth - 1; j < J; ++j) { - var jLabel = nameSpaceLabel[j]; - if (!nameSpaceObject[jLabel]) { - nameSpaceObject[jLabel] = {}; - } - nameSpaceObject = nameSpaceObject[jLabel]; - } - nameSpaceObject[nameSpaceLabel[nameSpaceDepth - 1]] = value; - - } else if (label) { - // Any other jsvalues entry sets an attribute of the current - // template node. - if (typeof value == TYPE_boolean) { - // Handle boolean values that are set as attributes specially, - // according to the XML/HTML convention. - if (value) { - domSetAttribute(template, label, label); - } else { - domRemoveAttribute(template, label); - } - } else { - domSetAttribute(template, label, STRING_empty + value); - } - } - } -}; - - -/** - * Implements the jscontent attribute. Evalutes the expression in - * jscontent in the current context and with the current variables, - * and assigns its string value to the content of the current template - * node. - * - * @param {JsEvalContext} context Current evaluation context. - * - * @param {Element} template Currently processed template node. - * - * @param {Function} content Processed value of the jscontent - * attribute. - */ -JstProcessor.prototype.jstContent_ = function(context, template, content) { - // NOTE(mesch): Profiling shows that this method costs significant - // time. In jstemplate_perf.html, it's about 50%. I tried to replace - // by HTML escaping and assignment to innerHTML, but that was even - // slower. - var value = STRING_empty + context.jsexec(content, template); - // Prevent flicker when refreshing a template and the value doesn't - // change. - if (template.innerHTML == value) { - return; - } - while (template.firstChild) { - domRemoveNode(template.firstChild); - } - var t = domCreateTextNode(this.document_, value); - domAppendChild(template, t); -}; - - -/** - * Caches access to and parsing of template processing attributes. If - * domGetAttribute() is called every time a template attribute value - * is used, it takes more than 10% of the time. - * - * @param {Element} template A DOM element node of the template. - * - * @return {Object} A javascript object that has all js template - * processing attribute values of the node as properties. - */ -JstProcessor.prototype.jstAttributes_ = function(template) { - if (template[PROP_jstcache]) { - return template[PROP_jstcache]; - } - - var jstid = domGetAttribute(template, ATT_jstcache); - if (jstid) { - return template[PROP_jstcache] = JstProcessor.jstcache_[jstid]; - } - - return JstProcessor.prepareNode_(template); -}; - - -/** - * Helps to implement the transclude attribute, and is the initial - * call to get hold of a template from its ID. - * - * If the ID is not present in the DOM, and opt_loadHtmlFn is specified, this - * function will call that function and add the result to the DOM, before - * returning the template. - * - * @param {string} name The ID of the HTML element used as template. - * @param {Function} opt_loadHtmlFn A function which, when called, will return - * HTML that contains an element whose ID is 'name'. - * - * @return {Element|null} The DOM node of the template. (Only element nodes - * can be found by ID, hence it's a Element.) - */ -function jstGetTemplate(name, opt_loadHtmlFn) { - var doc = document; - var section; - if (opt_loadHtmlFn) { - section = jstLoadTemplateIfNotPresent(doc, name, opt_loadHtmlFn); - } else { - section = domGetElementById(doc, name); - } - if (section) { - JstProcessor.prepareTemplate_(section); - var ret = domCloneElement(section); - domRemoveAttribute(ret, STRING_id); - return ret; - } else { - return null; - } -} - -/** - * This function is the same as 'jstGetTemplate' but, if the template - * does not exist, throw an exception. - * - * @param {string} name The ID of the HTML element used as template. - * @param {Function} opt_loadHtmlFn A function which, when called, will return - * HTML that contains an element whose ID is 'name'. - * - * @return {Element} The DOM node of the template. (Only element nodes - * can be found by ID, hence it's a Element.) - */ -function jstGetTemplateOrDie(name, opt_loadHtmlFn) { - var x = jstGetTemplate(name, opt_loadHtmlFn); - check(x !== null); - return /** @type Element */(x); -} - - -/** - * If an element with id 'name' is not present in the document, call loadHtmlFn - * and insert the result into the DOM. - * - * @param {Document} doc - * @param {string} name - * @param {Function} loadHtmlFn A function that returns HTML to be inserted - * into the DOM. - * @param {string} opt_target The id of a DOM object under which to attach the - * HTML once it's inserted. An object with this id is created if it does not - * exist. - * @return {Element} The node whose id is 'name' - */ -function jstLoadTemplateIfNotPresent(doc, name, loadHtmlFn, opt_target) { - var section = domGetElementById(doc, name); - if (section) { - return section; - } - // Load any necessary HTML and try again. - jstLoadTemplate_(doc, loadHtmlFn(), opt_target || STRING_jsts); - var section = domGetElementById(doc, name); - if (!section) { - log("Error: jstGetTemplate was provided with opt_loadHtmlFn, " + - "but that function did not provide the id '" + name + "'."); - } - return /** @type Element */(section); -} - - -/** - * Loads the given HTML text into the given document, so that - * jstGetTemplate can find it. - * - * We append it to the element identified by targetId, which is hidden. - * If it doesn't exist, it is created. - * - * @param {Document} doc The document to create the template in. - * - * @param {string} html HTML text to be inserted into the document. - * - * @param {string} targetId The id of a DOM object under which to attach the - * HTML once it's inserted. An object with this id is created if it does not - * exist. - */ -function jstLoadTemplate_(doc, html, targetId) { - var existing_target = domGetElementById(doc, targetId); - var target; - if (!existing_target) { - target = domCreateElement(doc, STRING_div); - target.id = targetId; - displayNone(target); - positionAbsolute(target); - domAppendChild(doc.body, target); - } else { - target = existing_target; - } - var div = domCreateElement(doc, STRING_div); - target.appendChild(div); - div.innerHTML = html; -} - - -/** - * Sets the jsinstance attribute on a node according to its context. - * - * @param {Element} template The template DOM node to set the instance - * attribute on. - * - * @param {Array} values The current input context, the array of - * values of which the template node will render one instance. - * - * @param {number} index The index of this template node in values. - */ -function jstSetInstance(template, values, index) { - if (index == jsLength(values) - 1) { - domSetAttribute(template, ATT_instance, CHAR_asterisk + index); - } else { - domSetAttribute(template, ATT_instance, STRING_empty + index); - } -} - - -/** - * Log the current state. - * @param {string} caller An identifier for the caller of .log_. - * @param {Element} template The template node being processed. - * @param {Object} jstAttributeValues The jst attributes of the template node. - */ -JstProcessor.prototype.logState_ = function( - caller, template, jstAttributeValues) { - if (MAPS_DEBUG) { - var msg = '<table>'; - msg += '<caption>' + caller + '</caption>'; - msg += '<tbody>'; - if (template.id) { - msg += '<tr><td>' + 'id:' + '</td><td>' + template.id + '</td></tr>'; - } - if (template.name) { - msg += '<tr><td>' + 'name:' + '</td><td>' + template.name + '</td></tr>'; - } - if (jstAttributeValues) { - msg += '<tr><td>' + 'attr:' + - '</td><td>' + jsToSource(jstAttributeValues) + '</td></tr>'; - } - msg += '</tbody></table><br/>'; - this.logs_.push(msg); - } -}; - - -/** - * Retrieve the processing logs. - * @return {Array<string>} The processing logs. - */ -JstProcessor.prototype.getLogs = function() { - return this.logs_; -};
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/util.js b/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/util.js deleted file mode 100644 index f6c1f46..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/jstemplate/util.js +++ /dev/null
@@ -1,470 +0,0 @@ -// Copyright 2006 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -// implied. See the License for the specific language governing -// permissions and limitations under the License. -/** - * @fileoverview Miscellaneous constants and functions referenced in - * the main source files. - * - * @author Steffen Meschkat (mesch@google.com) - */ - -var MAPS_DEBUG = false; - -function log(msg) {} - -// String literals defined globally and not to be inlined. (IE6 perf) -/** @const */ var STRING_empty = ''; - -/** @const */ var CSS_display = 'display'; -/** @const */ var CSS_position = 'position'; - -// Constants for possible values of the typeof operator. -var TYPE_boolean = 'boolean'; -var TYPE_number = 'number'; -var TYPE_object = 'object'; -var TYPE_string = 'string'; -var TYPE_function = 'function'; -var TYPE_undefined = 'undefined'; - - -/** - * Wrapper for the eval() builtin function to evaluate expressions and - * obtain their value. It wraps the expression in parentheses such - * that object literals are really evaluated to objects. Without the - * wrapping, they are evaluated as block, and create syntax - * errors. Also protects against other syntax errors in the eval()ed - * code and returns null if the eval throws an exception. - * - * @param {string} expr - * @return {Object|null} - */ -function jsEval(expr) { - try { - // NOTE(mesch): An alternative idiom would be: - // - // eval('(' + expr + ')'); - // - // Note that using the square brackets as below, "" evals to undefined. - // The alternative of using parentheses does not work when evaluating - // function literals in IE. - // e.g. eval("(function() {})") returns undefined, and not a function - // object, in IE. - return eval('[' + expr + '][0]'); - } catch (e) { - log('EVAL FAILED ' + expr + ': ' + e); - return null; - } -} - -function jsLength(obj) { - return obj.length; -} - -function assert(obj) {} - -/** - * Copies all properties from second object to the first. Modifies to. - * - * @param {Object} to The target object. - * @param {Object} from The source object. - */ -function copyProperties(to, from) { - for (var p in from) { - to[p] = from[p]; - } -} - - -/** - * @param {Object|null|undefined} value The possible value to use. - * @param {Object} defaultValue The default if the value is not set. - * @return {Object} The value, if it is - * defined and not null; otherwise the default - */ -function getDefaultObject(value, defaultValue) { - if (typeof value != TYPE_undefined && value != null) { - return /** @type Object */(value); - } else { - return defaultValue; - } -} - -/** - * Detect if an object looks like an Array. - * Note that instanceof Array is not robust; for example an Array - * created in another iframe fails instanceof Array. - * @param {Object|null} value Object to interrogate - * @return {boolean} Is the object an array? - */ -function isArray(value) { - return value != null && - typeof value == TYPE_object && - typeof value.length == TYPE_number; -} - - -/** - * Finds a slice of an array. - * - * @param {Array} array Array to be sliced. - * @param {number} start The start of the slice. - * @param {number} opt_end The end of the slice (optional). - * @return {Array} array The slice of the array from start to end. - */ -function arraySlice(array, start, opt_end) { - // Use - // return Function.prototype.call.apply(Array.prototype.slice, arguments); - // instead of the simpler - // return Array.prototype.slice.call(array, start, opt_end); - // here because of a bug in the FF and IE implementations of - // Array.prototype.slice which causes this function to return an empty list - // if opt_end is not provided. - return Function.prototype.call.apply(Array.prototype.slice, arguments); -} - - -/** - * Jscompiler wrapper for parseInt() with base 10. - * - * @param {string} s string repersentation of a number. - * - * @return {number} The integer contained in s, converted on base 10. - */ -function parseInt10(s) { - return parseInt(s, 10); -} - - -/** - * Clears the array by setting the length property to 0. This usually - * works, and if it should turn out not to work everywhere, here would - * be the place to implement the browser specific workaround. - * - * @param {Array} array Array to be cleared. - */ -function arrayClear(array) { - array.length = 0; -} - - -/** - * Prebinds "this" within the given method to an object, but ignores all - * arguments passed to the resulting function. - * I.e. var_args are all the arguments that method is invoked with when - * invoking the bound function. - * - * @param {Object|null} object The object that the method call targets. - * @param {Function} method The target method. - * @return {Function} Method with the target object bound to it and curried by - * the provided arguments. - */ -function bindFully(object, method, var_args) { - var args = arraySlice(arguments, 2); - return function() { - return method.apply(object, args); - } -} - -// Based on <http://www.w3.org/TR/2000/ REC-DOM-Level-2-Core-20001113/ -// core.html#ID-1950641247>. -var DOM_ELEMENT_NODE = 1; -var DOM_ATTRIBUTE_NODE = 2; -var DOM_TEXT_NODE = 3; -var DOM_CDATA_SECTION_NODE = 4; -var DOM_ENTITY_REFERENCE_NODE = 5; -var DOM_ENTITY_NODE = 6; -var DOM_PROCESSING_INSTRUCTION_NODE = 7; -var DOM_COMMENT_NODE = 8; -var DOM_DOCUMENT_NODE = 9; -var DOM_DOCUMENT_TYPE_NODE = 10; -var DOM_DOCUMENT_FRAGMENT_NODE = 11; -var DOM_NOTATION_NODE = 12; - - - -function domGetElementById(document, id) { - return document.getElementById(id); -} - -/** - * Creates a new node in the given document - * - * @param {Document} doc Target document. - * @param {string} name Name of new element (i.e. the tag name).. - * @return {Element} Newly constructed element. - */ -function domCreateElement(doc, name) { - return doc.createElement(name); -} - -/** - * Traverses the element nodes in the DOM section underneath the given - * node and invokes the given callback as a method on every element - * node encountered. - * - * @param {Element} node Parent element of the subtree to traverse. - * @param {Function} callback Called on each node in the traversal. - */ -function domTraverseElements(node, callback) { - var traverser = new DomTraverser(callback); - traverser.run(node); -} - -/** - * A class to hold state for a dom traversal. - * @param {Function} callback Called on each node in the traversal. - * @constructor - * @class - */ -function DomTraverser(callback) { - this.callback_ = callback; -} - -/** - * Processes the dom tree in breadth-first order. - * @param {Element} root The root node of the traversal. - */ -DomTraverser.prototype.run = function(root) { - var me = this; - me.queue_ = [ root ]; - while (jsLength(me.queue_)) { - me.process_(me.queue_.shift()); - } -} - -/** - * Processes a single node. - * @param {Element} node The current node of the traversal. - */ -DomTraverser.prototype.process_ = function(node) { - var me = this; - - me.callback_(node); - - for (var c = node.firstChild; c; c = c.nextSibling) { - if (c.nodeType == DOM_ELEMENT_NODE) { - me.queue_.push(c); - } - } -} - -/** - * Get an attribute from the DOM. Simple redirect, exists to compress code. - * - * @param {Element} node Element to interrogate. - * @param {string} name Name of parameter to extract. - * @return {string|null} Resulting attribute. - */ -function domGetAttribute(node, name) { - return node.getAttribute(name); - // NOTE(mesch): Neither in IE nor in Firefox, HTML DOM attributes - // implement namespaces. All items in the attribute collection have - // null localName and namespaceURI attribute values. In IE, we even - // encounter DIV elements that don't implement the method - // getAttributeNS(). -} - - -/** - * Set an attribute in the DOM. Simple redirect to compress code. - * - * @param {Element} node Element to interrogate. - * @param {string} name Name of parameter to set. - * @param {string|number} value Set attribute to this value. - */ -function domSetAttribute(node, name, value) { - node.setAttribute(name, value); -} - -/** - * Remove an attribute from the DOM. Simple redirect to compress code. - * - * @param {Element} node Element to interrogate. - * @param {string} name Name of parameter to remove. - */ -function domRemoveAttribute(node, name) { - node.removeAttribute(name); -} - -/** - * Clone a node in the DOM. - * - * @param {Node} node Node to clone. - * @return {Node} Cloned node. - */ -function domCloneNode(node) { - return node.cloneNode(true); - // NOTE(mesch): we never so far wanted to use cloneNode(false), - // hence the default. -} - -/** - * Clone a element in the DOM. - * - * @param {Element} element Element to clone. - * @return {Element} Cloned element. - */ -function domCloneElement(element) { - return /** @type {Element} */(domCloneNode(element)); -} - -/** - * Returns the document owner of the given element. In particular, - * returns window.document if node is null or the browser does not - * support ownerDocument. If the node is a document itself, returns - * itself. - * - * @param {Node|null|undefined} node The node whose ownerDocument is required. - * @returns {Document} The owner document or window.document if unsupported. - */ -function ownerDocument(node) { - if (!node) { - return document; - } else if (node.nodeType == DOM_DOCUMENT_NODE) { - return /** @type Document */(node); - } else { - return node.ownerDocument || document; - } -} - -/** - * Creates a new text node in the given document. - * - * @param {Document} doc Target document. - * @param {string} text Text composing new text node. - * @return {Text} Newly constructed text node. - */ -function domCreateTextNode(doc, text) { - return doc.createTextNode(text); -} - -/** - * Appends a new child to the specified (parent) node. - * - * @param {Element} node Parent element. - * @param {Node} child Child node to append. - * @return {Node} Newly appended node. - */ -function domAppendChild(node, child) { - return node.appendChild(child); -} - -/** - * Sets display to default. - * - * @param {Element} node The dom element to manipulate. - */ -function displayDefault(node) { - node.style[CSS_display] = ''; -} - -/** - * Sets display to none. Doing this as a function saves a few bytes for - * the 'style.display' property and the 'none' literal. - * - * @param {Element} node The dom element to manipulate. - */ -function displayNone(node) { - node.style[CSS_display] = 'none'; -} - - -/** - * Sets position style attribute to absolute. - * - * @param {Element} node The dom element to manipulate. - */ -function positionAbsolute(node) { - node.style[CSS_position] = 'absolute'; -} - - -/** - * Inserts a new child before a given sibling. - * - * @param {Node} newChild Node to insert. - * @param {Node} oldChild Sibling node. - * @return {Node} Reference to new child. - */ -function domInsertBefore(newChild, oldChild) { - return oldChild.parentNode.insertBefore(newChild, oldChild); -} - -/** - * Replaces an old child node with a new child node. - * - * @param {Node} newChild New child to append. - * @param {Node} oldChild Old child to remove. - * @return {Node} Replaced node. - */ -function domReplaceChild(newChild, oldChild) { - return oldChild.parentNode.replaceChild(newChild, oldChild); -} - -/** - * Removes a node from the DOM. - * - * @param {Node} node The node to remove. - * @return {Node} The removed node. - */ -function domRemoveNode(node) { - return domRemoveChild(node.parentNode, node); -} - -/** - * Remove a child from the specified (parent) node. - * - * @param {Element} node Parent element. - * @param {Node} child Child node to remove. - * @return {Node} Removed node. - */ -function domRemoveChild(node, child) { - return node.removeChild(child); -} - - -/** - * Trim whitespace from begin and end of string. - * - * @see testStringTrim(); - * - * @param {string} str Input string. - * @return {string} Trimmed string. - */ -function stringTrim(str) { - return stringTrimRight(stringTrimLeft(str)); -} - -/** - * Trim whitespace from beginning of string. - * - * @see testStringTrimLeft(); - * - * @param {string} str Input string. - * @return {string} Trimmed string. - */ -function stringTrimLeft(str) { - return str.replace(/^\s+/, ""); -} - -/** - * Trim whitespace from end of string. - * - * @see testStringTrimRight(); - * - * @param {string} str Input string. - * @return {string} Trimmed string. - */ -function stringTrimRight(str) { - return str.replace(/\s+$/, ""); -} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/notification.html b/chrome/common/extensions/docs/examples/extensions/irc/servlet/notification.html deleted file mode 100644 index e068873..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/notification.html +++ /dev/null
@@ -1,62 +0,0 @@ -<html> - <head> - <script src="util.js" type="text/javascript"></script> - <style> -body { - margin: 0px; - padding: 0px; - -webkit-user-select: none; -} - -#notification { - width: 300px; - height: 50px; - position: fixed; - overflow: hidden; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-box-align: stretch; -} - -#title { - display: -webkit-box; - -webkit-box-flex: 0; - padding: 2px 4px 2px 4px; - background-color: #AAAAAA; - color: white; - font-family: Verdana, sans-serif; - font-size: 10px; -} - -#content { - display: -webkit-box; - -webkit-box-flex: 1; - color: #444444; - font-family: "Lucida Console", Monospace; - font-size: 12px; - padding: 4px; - text-overflow: ellipsis; -} - </style> - <script> -window.onload = function() { - var argString = location.search.substring(location.search.indexOf("?") + 1); - var tokens = argString.split("&"); - var args = {}; - tokens.forEach(function(token) { - var keyVal = token.split("="); - args[keyVal[0]] = decodeURIComponent(keyVal[1]); - }); - - $('title').innerText = args.title; - $('content').innerText = args.content; -} - </script> - </head> - <body onclick="window.close();"> - <div id="notification"> - <div id="title"></div> - <div id="content"></div> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/src/org/chromium/IRCProxyWebSocket.java b/chrome/common/extensions/docs/examples/extensions/irc/servlet/src/org/chromium/IRCProxyWebSocket.java deleted file mode 100644 index 688e422..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/src/org/chromium/IRCProxyWebSocket.java +++ /dev/null
@@ -1,116 +0,0 @@ -package org.chromium; - -import org.eclipse.jetty.websocket.WebSocket; -import org.eclipse.jetty.websocket.WebSocketServlet; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; - -import javax.net.SocketFactory; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -public class IRCProxyWebSocket extends WebSocketServlet { - - private static final long serialVersionUID = 1L; - - private final Set<ChatWebSocket> members_ = - new CopyOnWriteArraySet<ChatWebSocket>(); - - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException ,IOException { - getServletContext().getNamedDispatcher("default").forward(request,response); - } - - protected WebSocket doWebSocketConnect(HttpServletRequest request, - String protocol) { - return new ChatWebSocket(); - } - - class ChatWebSocket implements WebSocket, Runnable { - Outbound outbound_; - Socket socket_ = null; - OutputStreamWriter out_; - BufferedReader in_; - Thread thread_; - byte frame_ = 0; - - public void onConnect(Outbound outbound) { - outbound_= outbound; - } - - public void onMessage(byte frame, byte[] data,int offset, int length) {} - - public void onMessage(byte frame, String data) { - try { - if (socket_ == null) { - try { - // We assume the client is going to connect and initiate a - // connection with the message "server:port". - String tokens[] = data.split(":"); - socket_ = SocketFactory.getDefault().createSocket(tokens[0], - Integer.parseInt(tokens[1])); - out_ = new OutputStreamWriter(socket_.getOutputStream()); - InputStreamReader in = new InputStreamReader( - socket_.getInputStream()); - in_ = new BufferedReader(in); - - members_.add(this); - thread_ = new Thread(this); - thread_.start(); - - } catch (UnknownHostException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } else { - System.out.print(">> " + data); - out_.write(data); - out_.flush(); - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - public void onDisconnect() { - try { - socket_.close(); - thread_.stop(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - members_.remove(this); - } - - @Override - public void run() { - while(true) { - try { - if (in_.ready()) { - String line = in_.readLine(); - System.out.println("<< " + line); - outbound_.sendMessage(frame_, line + "\r\n"); - - } else { - Thread.sleep(100); - } - } catch (IOException e) { - } catch (InterruptedException e) { - } - } - } - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/styles.css b/chrome/common/extensions/docs/examples/extensions/irc/servlet/styles.css deleted file mode 100644 index fc854c19..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/styles.css +++ /dev/null
@@ -1,159 +0,0 @@ -body { - margin: 0; - padding: 0; -} - -#pageContainer { - display: -webkit-box; - position: fixed; - -webkit-box-orient: vertical; - -webkit-box-align: stretch; - height: 100%; - width: 100%; - } - - #headerContainer { - display: -webkit-box; - height: 32px; - -webkit-box-orient: horizontal; - -webkit-box-align: stretch; - } - -#pageControls { - position: absolute; - right: 0px; - font-family: Verdana, sans-serif; - font-size: 16px; - color: #aaaaaa; - padding: 8px; -} - -#pageControls *, .removeButton, .channel, .messageLine * { - display: inline-block; -} - -.addControlLabel { - margin-left: 20px; -} - -.addButton { - background-color: #aaaaaa; - color: white; -} - -#slideContainer { - display: -webkit-box; - -webkit-box-flex: 1; - position: relative; -} - -#channelSlides { - position: absolute; - width: 100%; - height: 100%; -} - -.channelSlide { - position: absolute; - width: 80%; - height: 100%; - background: -webkit-linear-gradient(#aaa, white); - transition: margin 0.25s ease-in-out; -} - -.channelSlide.far-left { - margin-left: -160%; -} - -.channelSlide.left { - margin-left: -75%; -} - -.channelSlide.center { - margin-left: 10%; -} - -.channelSlide.right { - margin-left: 95%; -} - -.channelSlide.far-right { - margin-left: 180%; -} - -.channelControls { - position: absolute; - z-index: 1; - right: 0px; - top:0px; - color: white; - text-align: right; - padding: 8px; - font-family: "Verdana", sans-serif; - font-size: 20px; -} - -.channelControls .removeButton { - background-color: white; - color: #999999; - padding: 0px 6px 4px 6px; - height: -} - -.channelSlideContainer { - position: relative; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-box-align: stretch; - height: 100%; - width: 100%; -} - -.messageListContainer { - overflow: hidden; - position: relative; - display: -webkit-box; - -webkit-box-flex: 1; -} - -.messageListSpacer { - display: -webkit-box; - -webkit-box-flex: 0; - height: 40px; - width: 100%; -} - -.messageLine { - margin: 6px; - color: #999999; - font-family: "Lucida Console", Monospace; - font-size: 14px; -} - -.messageList { - position: absolute; - bottom: 0; -} - -#typingDiv { - position: fixed; - z-index: 4; - width: 80%; - height: 30px; - margin: 10px; - margin-left: 10%; - bottom: 0px; - -webkit-box-shadow: 3px 3px 5px #888; -} - -#entryText { - width: 100%; - border: 0px; - height: 100%; - padding-left: 8px; - padding-right: 8px; - font-family: "Lucida Console", Monospace; - color: white; - border: 0px; - background: #777777; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/irc/servlet/util.js b/chrome/common/extensions/docs/examples/extensions/irc/servlet/util.js deleted file mode 100644 index f654d2c1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/irc/servlet/util.js +++ /dev/null
@@ -1,19 +0,0 @@ -function $(el) { - return document.getElementById(el); -} - -function $F(el) { - return $(el).value; -} - -function bind(obj, func) { - return function() { - return func.apply(obj, arguments); - }; -} - -function childNodeWithClass(node, className) { - var expression = ".//*[@class='" + className + "']"; - return document.evaluate(expression, node, - null, XPathResult.ANY_TYPE, null).iterateNext(); -} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/_locales/en/messages.json deleted file mode 100644 index 958f786..0000000 --- a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/_locales/en/messages.json +++ /dev/null
@@ -1,10 +0,0 @@ -{ - "extName": { - "message": "Managed Bookmarks", - "description": "The extension name." - }, - "extDescription": { - "message": "Adds bookmarks configured by your system administrator to Chrome.", - "description": "The extension description." - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/background.js b/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/background.js deleted file mode 100644 index 0778b7f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/background.js +++ /dev/null
@@ -1,365 +0,0 @@ -// Copyright 2013 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. - -/** - * Maps policy names to the root node that they affect. - */ -var policyToNodeId = { - 'Bookmarks Bar': '1', - 'Other Bookmarks': '2' -}; - -/** - * A function that fixes a URL. Turns e.g. "google.com" into - * "http://google.com/". This is used to correctly match against the - * canonicalized URLs stored in bookmarks created with the bookmarks API. - */ -var fixURL = (function() { - // An "a" element is used to parse the given URL and build the fixed version. - var a = document.createElement('a'); - return function(url) { - // Preserve null, undefined, etc. - if (!url) - return url; - a.href = url; - // Handle cases like "google.com", which will be relative to the extension. - if (a.protocol === 'chrome-extension:' && - url.substr(0, 17) !== 'chrome-extension:') { - a.href = 'http://' + url; - } - return a.href; - } -})(); - -/** - * A CallbackChain can be used to wrap other callbacks and perform a list of - * actions at the end, once all the wrapped callbacks have been invoked. - */ -var CallbackChain = function() { - this._count = 0; - this._callbacks = []; -} - -CallbackChain.prototype.push = function(callback) { - this._callbacks.push(callback); -} - -CallbackChain.prototype.wrap = function(callback) { - var self = this; - self._count++; - return function() { - if (callback) - callback.apply(null, arguments); - self._count--; - if (self._count == 0) { - for (var i = 0; i < self._callbacks.length; ++i) - self._callbacks[i](); - } - } -} - -/** - * Represents a managed bookmark. - */ -var Node = function(nodesMap, id, title, url) { - this._nodesMap = nodesMap; - this._id = id; - this._title = title; - if (url !== undefined) - this._url = url; - else - this._children = []; - if (id) - this._nodesMap[id] = this; -} - -Node.prototype.isRoot = function() { - return this._id in [ '0', '1', '2' ]; -} - -Node.prototype.getIndex = function() { - return this._nodesMap[this._parentId]._children.indexOf(this); -} - -Node.prototype.appendChild = function(node) { - node._parentId = this._id; - this._children.push(node); -} - -Node.prototype.droppedFromParent = function() { - // Remove |this| and its children from the |nodesMap|. - var nodesMap = this._nodesMap; - var removeFromNodesMap = function(node) { - delete nodesMap[node._id]; - (node._children || []).forEach(removeFromNodesMap); - } - removeFromNodesMap(this); - - if (this._children) - chrome.bookmarks.removeTree(this._id); - else - chrome.bookmarks.remove(this._id); -} - -Node.prototype.matches = function(bookmark) { - return this._title === bookmark.title && - this._url === bookmark.url && - typeof this._children === typeof bookmark.children; -} - -/** - * Makes this node's children match |wantedChildren|. - */ -Node.prototype.updateChildren = function(wantedChildren, callbackChain) { - // Rebuild the list of children to match |wantedChildren|. - var currentChildren = this._children; - this._children = []; - for (var i = 0; i < wantedChildren.length; ++i) { - var currentChild = currentChildren[i]; - var wantedChild = wantedChildren[i]; - wantedChild.url = fixURL(wantedChild.url); - - if (currentChild && currentChild.matches(wantedChild)) { - this.appendChild(currentChild); - if (wantedChild.children) - currentChild.updateChildren(wantedChild.children, callbackChain); - } else { - // This child is either missing, invalid or misplaced; drop it and - // generate it again. Note that the actual dropping is delayed so that - // bookmarks.onRemoved is triggered after the changes have been persisted. - if (currentChild) - callbackChain.push(currentChild.droppedFromParent.bind(currentChild)); - // The "id" comes with the callback from bookmarks.create() but the Node - // is created now so that the child is placed at the right position. - var newChild = new Node( - this._nodesMap, undefined, wantedChild.title, wantedChild.url); - this.appendChild(newChild); - chrome.bookmarks.create({ - 'parentId': this._id, - 'title': newChild._title, - 'url': newChild._url, - 'index': i - }, callbackChain.wrap((function(wantedChild, newChild, createdNode) { - newChild._id = createdNode.id; - newChild._nodesMap[newChild._id] = newChild; - if (wantedChild.children) - newChild.updateChildren(wantedChild.children, callbackChain); - }).bind(null, wantedChild, newChild))); - } - } - - // Drop all additional bookmarks past the end that are not wanted anymore. - if (currentChildren.length > wantedChildren.length) { - var chainCounter = callbackChain.wrap(); - currentChildren.slice(wantedChildren.length).forEach(function(child) { - callbackChain.push(child.droppedFromParent.bind(child)); - }); - // This wrapped nop makes sure that the callbacks appended to the chain - // execute if nothing else was wrapped. - chainCounter(); - } -} - -/** - * Creates new nodes in the bookmark model to represent this Node and its - * children. - */ -Node.prototype.regenerate = function(parentId, index, callbackChain) { - var self = this; - chrome.bookmarks.create({ - 'parentId': parentId, - 'title': self._title, - 'url': self._url, - 'index': index - }, callbackChain.wrap(function(newNode) { - delete self._nodesMap[self._id]; - self._id = newNode.id; - self._parentId = newNode.parentId; - self._nodesMap[self._id] = self; - (self._children || []).forEach(function(child, i) { - child.regenerate(self._id, i, callbackChain); - }); - })); -} - -/** - * Moves this node to the correct position in the model. - * |currentParentId| and |currentIndex| indicate the current position in - * the model, which may not match the expected position. - */ -Node.prototype.moveInModel = function(currentParentId, currentIndex, callback) { - var index = this.getIndex(); - if (currentParentId == this._parentId) { - if (index == currentIndex) { - // Nothing to do. - callback(); - return; - } else if (index > currentIndex) { - // A bookmark moved is inserted at the new position before it is removed - // from the previous position. So when moving forward in the same parent, - // the index must be adjusted by one from the desired index. - ++index; - } - } - chrome.bookmarks.move(this._id, { - 'parentId': this._parentId, - 'index': index - }, callback); -} - -/** - * Moves any misplaced child nodes into their expected positions. - */ -Node.prototype.reorderChildren = function() { - var self = this; - chrome.bookmarks.getChildren(self._id, function(currentOrder) { - for (var i = 0; i < currentOrder.length; ++i) { - var node = currentOrder[i]; - var child = self._nodesMap[node.id]; - if (child && child.getIndex() != i) { - // Check again after moving this child. - child.moveInModel( - node.parentId, node.index, self.reorderChildren.bind(self)); - return; - } - } - }); -} - -var serializeNode = function(node) { - var result = { - 'id': node._id, - 'title': node._title - } - if (node._url) - result['url'] = node._url; - else - result['children'] = node._children.map(serializeNode); - return result; -} - -var unserializeNode = function(nodesMap, node) { - var result = new Node(nodesMap, node['id'], node['title'], node['url']); - if (node.children) { - node.children.forEach(function(child) { - result.appendChild(unserializeNode(nodesMap, child)); - }); - } - return result; -} - -/** - * Tracks all the managed bookmarks, and persists the known state so that - * managed bookmarks can be updated after restarts. - */ -var ManagedBookmarkTree = function() { - // Maps a string id to its Node. Used to lookup an entry by ID. - this._nodesMap = {}; - this._root = new Node(this._nodesMap, '0', ''); - this._root.appendChild(new Node(this._nodesMap, '1', 'Bookmarks Bar')); - this._root.appendChild(new Node(this._nodesMap, '2', 'Other Bookmarks')); -} - -ManagedBookmarkTree.prototype.store = function() { - chrome.storage.local.set({ - 'ManagedBookmarkTree': serializeNode(this._root) - }); -} - -ManagedBookmarkTree.prototype.load = function(callback) { - var self = this; - chrome.storage.local.get('ManagedBookmarkTree', function(result) { - if (result.hasOwnProperty('ManagedBookmarkTree')) { - self._nodesMap = {}; - self._root = unserializeNode(self._nodesMap, - result['ManagedBookmarkTree']); - } - callback(); - }); -} - -ManagedBookmarkTree.prototype.getById = function(id) { - return this._nodesMap[id]; -} - -ManagedBookmarkTree.prototype.update = function(rootNodeId, currentPolicy) { - // Note that the |callbackChain| is only invoked if a callback is wrapped, - // otherwise its callbacks are never invoked. So store() is called only if - // bookmarks.create() is actually used. - var callbackChain = new CallbackChain(); - callbackChain.push(this.store.bind(this)); - this._nodesMap[rootNodeId].updateChildren(currentPolicy || [], callbackChain); -} - -var tree = new ManagedBookmarkTree(); - -chrome.runtime.onInstalled.addListener(function() { - // Enforce the initial policy. - // This load() should be empty on the first install, but is useful during - // development to handle reloads. - tree.load(function() { - chrome.storage.managed.get(function(policy) { - Object.keys(policyToNodeId).forEach(function(policyName) { - tree.update(policyToNodeId[policyName], policy[policyName]); - }); - }); - }); -}); - -// Start observing policy changes. The tree is reloaded since this may be -// called back while the page was inactive. -chrome.storage.onChanged.addListener(function(changes, namespace) { - if (namespace !== 'managed') - return; - tree.load(function() { - Object.keys(changes).forEach(function(policyName) { - tree.update(policyToNodeId[policyName], changes[policyName].newValue); - }); - }); -}); - -// Observe bookmark modifications and revert any modifications made to managed -// bookmarks. The tree is always reloaded in case the events happened while the -// page was inactive. - -chrome.bookmarks.onMoved.addListener(function(id, info) { - tree.load(function() { - var managedNode = tree.getById(id); - if (managedNode && !managedNode.isRoot()) { - managedNode.moveInModel(info.parentId, info.index, function(){}); - } else { - // Check if the parent node has managed children that need to move. - // Example: moving a non-managed bookmark in front of the managed - // bookmarks. - var parentNode = tree.getById(info.parentId); - if (parentNode) - parentNode.reorderChildren(); - } - }); -}); - -chrome.bookmarks.onChanged.addListener(function(id, info) { - tree.load(function() { - var managedNode = tree.getById(id); - if (!managedNode || managedNode.isRoot()) - return; - chrome.bookmarks.update(id, { - 'title': managedNode._title, - 'url': managedNode._url - }); - }); -}); - -chrome.bookmarks.onRemoved.addListener(function(id, info) { - tree.load(function() { - var managedNode = tree.getById(id); - if (!managedNode || managedNode.isRoot()) - return; - // A new tree.store() is needed at the end because the regenerated nodes - // will have new IDs. - var callbackChain = new CallbackChain(); - callbackChain.push(tree.store.bind(tree)); - managedNode.regenerate(info.parentId, info.index, callbackChain); - }); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/manifest.json b/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/manifest.json deleted file mode 100644 index 6ee3f29b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "name": "__MSG_extName__", - "description": "__MSG_extDescription__", - "default_locale": "en", - "version": "1.0", - "manifest_version": 2, - "minimum_chrome_version": "33", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "permissions": [ - "bookmarks" - ], - "storage": { - "managed_schema": "schema.json" - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/schema.json b/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/schema.json deleted file mode 100644 index 11e7aeb5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/managed_bookmarks/schema.json +++ /dev/null
@@ -1,36 +0,0 @@ -{ - "type": "object", - "properties": { - "Bookmarks Bar": { - "title": "Bookmarks in the Bookmarks Bar", - "description": "Configures bookmarks that will appear in the Bookmarks Bar and can't be removed by the user.", - "type": "array", - "id": "ListOfBookmarks", - "items": { - "type": "object", - "properties": { - "title": { - "title": "Bookmark name", - "description": "The name that appears on the bookmark.", - "type": "string" - }, - "url": { - "title": "Bookmark URL", - "description": "The URL for the bookmark. If a URL is not set then this bookmark will be a folder.", - "type": "string" - }, - "children": { - "title": "Contents of this bookmark folder", - "description": "A list of bookmarks that will be inside this bookmark folder. If this is set then the URL for this bookmark will be ignored.", - "$ref": "ListOfBookmarks" - } - } - } - }, - "Other Bookmarks": { - "title": "Bookmarks in the Other Bookmarks folder", - "description": "Configures bookmarks that will appear in the Other Bookmarks folder and can't be removed by the user.", - "$ref": "ListOfBookmarks" - } - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/background.js b/chrome/common/extensions/docs/examples/extensions/mappy/background.js deleted file mode 100644 index 959e7bd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/background.js +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright (c) 2011 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. - -'use strict' - -chrome.runtime.onMessage.addListener(function(req, sender) { - chrome.storage.local.set({address: req.address}) - chrome.pageAction.show(sender.tab.id); - chrome.pageAction.setTitle({tabId: sender.tab.id, title: req.address}); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/icon.png b/chrome/common/extensions/docs/examples/extensions/mappy/icon.png deleted file mode 100644 index 7086d919c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json b/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json deleted file mode 100644 index 2cacda9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/manifest.json +++ /dev/null
@@ -1,28 +0,0 @@ -{ - "name": "Mappy", - "version": "1.0", - "description": "Finds addresses in the web page you're on and pops up a map window.", - "icons": { "128": "icon.png" }, - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "content_scripts": [ - { - "matches": ["http://*/*"], - "js": ["mappy_content_script.js"] - } - ], - "permissions": [ - "storage", - "https://maps.google.com/*", - "https://maps.googleapis.com/*" - ], - "page_action": { - "default_name": "Display Map", - "default_icon": "marker.png", - "default_popup": "popup.html" - }, - "manifest_version": 2, - "content_security_policy": "default-src 'none'; style-src 'self'; script-src 'self'; connect-src https://maps.googleapis.com; img-src https://maps.googleapis.com" -}
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js b/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js deleted file mode 100644 index 8bdf56ee..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/mappy_content_script.js +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright (c) 2011 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. - -// Search the text nodes for a US-style mailing address. - -let findAddress = function() { - let found; - let re = /(\d+\s+[':.,\s\w]*,\s*[A-Za-z]+\s*\d{5}(-\d{4})?)/m; - let node = document.body.textContent.match(re); - if (document.body.textContent.match(re)) { - found = node; - } - if (found) { - let text = node; - let match = re.exec(text); - if (match && match.length) { - console.log('found: ' + match[0]); - let trim = /\s{2,}/g; - let address = match[0].replace(trim, ' ') - chrome.runtime.sendMessage({'address': address}) - } else { - console.log('bad initial match: ' + found.textContent); - console.log('no match in: ' + text); - } - } -} - -findAddress();
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/marker.png b/chrome/common/extensions/docs/examples/extensions/mappy/marker.png deleted file mode 100644 index 2bb34a18..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/marker.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/popup.css b/chrome/common/extensions/docs/examples/extensions/mappy/popup.css deleted file mode 100644 index 8091788..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/popup.css +++ /dev/null
@@ -1,15 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -body { - margin: 0px; - padding: 0px; -} - -#map { - width: 512px; - height: 512px; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/popup.html b/chrome/common/extensions/docs/examples/extensions/mappy/popup.html deleted file mode 100644 index c5d27fb0..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/popup.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!doctype html> -<html> - <head> - <title>Popup</title> - <link href="popup.css" rel="stylesheet" type="text/css"> - </head> - <body> - <img id="map"> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/mappy/popup.js b/chrome/common/extensions/docs/examples/extensions/mappy/popup.js deleted file mode 100644 index 20486956..0000000 --- a/chrome/common/extensions/docs/examples/extensions/mappy/popup.js +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright (c) 2011 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. - -'use strict' - -const kMaps_key = 'AIzaSyBa5aieunaIp3Obco-dNVYMdbnTZGAVkKQ'; - -function gclient_geocode(address) { - let url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + - encodeURIComponent(address) + '&sensor=false'; - let request = new XMLHttpRequest(); - - request.open('GET', url, true); - console.log(url); - request.onreadystatechange = function (e) { - console.log(request, e); - if (request.readyState == 4) { - if (request.status == 200) { - let json = JSON.parse(request.responseText); - let latlng = json.results[0].geometry.location; - latlng = latlng.lat + ',' + latlng.lng; - let src = 'https://maps.googleapis.com/maps/api/staticmap?center=' + - latlng + '&markers=' + latlng + '&zoom=14' + - '&size=512x512&sensor=false&key=' + kMaps_key; - let map = document.getElementById('map'); - map.src = src; - map.addEventListener('click', function () { - window.close(); - }); - } else { - console.log('Unable to resolve address into lat/lng'); - } - } - }; - request.send(null); -} - -function map() { - chrome.storage.local.get(['address'], function(value){ - gclient_geocode(value.address); - }) -} - -window.onload = map;
diff --git a/chrome/common/extensions/docs/examples/extensions/maps_app/128.png b/chrome/common/extensions/docs/examples/extensions/maps_app/128.png deleted file mode 100644 index a89b5c39..0000000 --- a/chrome/common/extensions/docs/examples/extensions/maps_app/128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/maps_app/24.png b/chrome/common/extensions/docs/examples/extensions/maps_app/24.png deleted file mode 100644 index 2fdbf44..0000000 --- a/chrome/common/extensions/docs/examples/extensions/maps_app/24.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/maps_app/manifest.json b/chrome/common/extensions/docs/examples/extensions/maps_app/manifest.json deleted file mode 100644 index bb1f2e8..0000000 --- a/chrome/common/extensions/docs/examples/extensions/maps_app/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "Google Maps", - "version": "3", - "icons": { "24": "24.png", "128": "128.png" }, - "app": { - "urls": [ - "http://maps.google.com/" - ], - "launch": { - "web_url": "http://maps.google.com/" - } - }, - "permissions": ["geolocation"], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json deleted file mode 100644 index 97e07c1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/_locales/en/messages.json +++ /dev/null
@@ -1,102 +0,0 @@ -{ - "extName": { - "message": "News Reader (by Google)" - }, - "extDesc": { - "message": "Displays the latest stories from Google News in a popup." - }, - "ext_default_title": { - "message": "Google News" - }, - - "1": { - "message": "Top Stories" - }, - "n": { - "message": "Nation" - }, - "w": { - "message": "World" - }, - "b": { - "message": "Business" - }, - "t": { - "message": "Science/Technology" - }, - "e": { - "message": "Entertainment" - }, - "s": { - "message": "Sports" - }, - "m": { - "message": "Health" - }, - "po": { - "message": "Most Popular" - }, - - "options": { - "message": "Options" - }, - "more_stories": { - "message": "More stories" - }, - - "direction": { - "message": "ltr" - }, - - "country": { - "message": "Country:" - }, - "topic": { - "message": "Topics:" - }, - "save": { - "message": "Save" - }, - "saveStatus": { - "message": "Options saved" - }, - "storyCount": { - "message": "Number of stories:" - }, - "newsOption": { - "message": "Google News Options" - }, - "customText": { - "message": "Custom Topics:" - }, - "maximumTopics": { - "message": "(Maximum $count$)", - "placeholders": { - "count": { - "content": "$1" - } - } - }, - "submitButton": { - "message": "Add" - }, - "deleteTitle": { - "message": "Delete" - }, - "invalidChars": { - "message": "Invalid character(s)" - }, - "noTopic": { - "message": "At least one Topic must be selected" - }, - - "fetchError": { - "message": "Error: Failed to fetch news stories." - }, - "wrongTopic": { - "message": "Error: Not a valid feed." - }, - "noStory": { - "message": "No story right now" - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news/css/feed.css b/chrome/common/extensions/docs/examples/extensions/news/css/feed.css deleted file mode 100644 index 8206fb2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/css/feed.css +++ /dev/null
@@ -1,101 +0,0 @@ -/** - * Copyright (c) 2010 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. - * - * Sets style of different elements in pop-up page. - * - * Author: navneetg@google.com (Navneet Goel). - */ - -body { - font-family: arial, sans-serif; - font-size: 12px; - min-width: 500px; - overflow: visible; -} -a { - color: #0000CC; - cursor: pointer; - text-decoration: underline; -} -#noStories { - background-color: rgb(255, 238, 136); - font-size: 13px; - font-weight: bold; - margin-left: 140px; - margin-right: 140px; - text-align: center; -} -.open_box { - background-image: url(/images/sprite_arrows.gif); - background-position: 0px -24px; - clear: left; - cursor: pointer; - display: block; - height: 12px; - margin-top: 2px; - overflow: hidden; - width: 12px; - float: left; -} -.opened .open_box { - background-position: -12px -24px; -} -.item { - padding: 2px 0; -} -.item_title { - cursor: pointer; - display: block; - min-width: 300px; - padding: 0 0 0 17px; -} -.item_desc { - border: none; - display: block; - height: 0; - margin: 0; - min-width: 500px; - padding: 0; - transition: height 0.2s ease-out; -} -#title { - display: block; -} -.error { - background-color: rgb(255, 238, 136); - font-size: 13px; - font-weight: bold; - margin-left: 125px; - margin-right: 125px; - text-align: center; - white-space: nowrap; -} -.more { - color: #88C; - display: block; - margin-left: 385px; - padding-right: 10px; - padding-top: 5px; - text-align: right; -} -.topicsLTR { - direction: ltr; - font-size: 13px; - padding-left: 5px; -} -.topicsRTL { - direction: rtl; - font-size: 13px; - padding-right: 5px; -} -body.rtl #feed { - direction: rtl; -} -body.rtl .open_box { - float: right; -} -body.rtl .item_title { - padding: 0 17px 0 0; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news/css/options.css b/chrome/common/extensions/docs/examples/extensions/news/css/options.css deleted file mode 100644 index 91aff7ed..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/css/options.css +++ /dev/null
@@ -1,121 +0,0 @@ -/** - * Copyright (c) 2010 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. - * - * Sets style of different elements in options page. - * - * Author: navneetg@google.com (Navneet Goel). - */ - -@CHARSET "UTF-8"; -body { - background-color: rgb(235, 239, 249); - font-family: arial , sans-serif; - font-size: 13px; -} -.suppr { - background-image: url(/images/delete-icon.png); - background-repeat: no-repeat; - cursor: pointer; - display: inline; - float: left; - height: 17px; - margin-top: 3px; - overflow: hidden; - width: 14px; -} -.checkBoxTopic { - float: left; - padding-left: 2px; - padding-top: 1px; -} -.checkBox { - float: left; -} -.boxAndTopic { - overflow: auto; - padding-bottom: 5px; -} -#invalid_status, #save_status { - background-color: rgb(255, 241, 168); - font-weight: bold; - margin-left: 10px; - opacity: 0; - padding-bottom: 3px; - padding-left: 7px; - padding-right: 7px; - padding-top: 3px; -} -#all_content { - background-color: white; - border-bottom-left-radius: 12px 12px; - border-bottom-right-radius: 12px 12px; - border-color: #B5C7DE; - border-style: solid; - border-top-left-radius: 12px 12px; - border-top-right-radius: 12px 12px; - border-width: 4px; - margin: 40px auto 20px; - padding: 12px; - width: 600px; -} -.col2 { - padding-left: 20px; -} -body.rtl .col1, body.rtl .col2 { - text-align: right; -} -body.rtl { - direction: rtl; -} -body.rtl .col2 { - padding-right: 20px; -} -body.rtl .checkBox, body.rtl .checkBoxTopic { - float: right; -} -body.rtl table.contentTable { - margin:0 55px 0 0; -} -body.rtl #save_div{ - margin: 0 220px 0 0; -} -body.rtl #countryList{ - margin:0 5px 0 0; -} -.col1 { - padding-top: 3px; - width: 115px; -} -.all_rows { - height: 35px; - vertical-align: top; -} -body.rtl .cusTopicsClass { - float: right; -} -.cusTopicsClass { - float: left; - width: 225px; -} -#save_div { - margin-left: 220px; -} -#countryList { - padding-left: 5px; -} -#logo { - font-size: 15px; - font-weight: bold; - text-align: center; -} -.noborder { - border: 0; - font-family: arial, sans-serif; - height: 15px; - outline: none; - overflow: hidden; - resize: none; - width:205px; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/buzz.png b/chrome/common/extensions/docs/examples/extensions/news/images/buzz.png deleted file mode 100644 index 09b446e9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/buzz.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/delete-icon.png b/chrome/common/extensions/docs/examples/extensions/news/images/delete-icon.png deleted file mode 100644 index 36a86fd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/delete-icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/fb.png b/chrome/common/extensions/docs/examples/extensions/news/images/fb.png deleted file mode 100644 index df35813..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/fb.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/news.gif b/chrome/common/extensions/docs/examples/extensions/news/images/news.gif deleted file mode 100644 index 2d8df793..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/news.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/news_action.png b/chrome/common/extensions/docs/examples/extensions/news/images/news_action.png deleted file mode 100644 index e5ae7b13..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/news_action.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/news_icon.png b/chrome/common/extensions/docs/examples/extensions/news/images/news_icon.png deleted file mode 100644 index aa864d98..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/news_icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/sprite_arrows.gif b/chrome/common/extensions/docs/examples/extensions/news/images/sprite_arrows.gif deleted file mode 100644 index 4560faf4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/sprite_arrows.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/images/twitter.png b/chrome/common/extensions/docs/examples/extensions/news/images/twitter.png deleted file mode 100644 index 31bd0e3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/images/twitter.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js b/chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js deleted file mode 100644 index f4cc99a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/javascript/feed.js +++ /dev/null
@@ -1,388 +0,0 @@ -/** - * Copyright (c) 2010 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. - */ - -/** - * @fileoverview This file retrieves news feed and shows news in pop-up - * page according to country, topics and no. of stories selected in the - * option page. - */ - -// Store value retrieved from locale. -var moreStoriesLocale = chrome.i18n.getMessage('more_stories') + ' \u00BB '; -var directionLocale = chrome.i18n.getMessage('direction'); - -// Feed URL. -var feedUrl = DEFAULT_NEWS_URL; - -//The XMLHttpRequest object that tries to load and parse the feed. -var req; - -/** - * Sends request to Google News server - */ -function main() { - req = new XMLHttpRequest(); - req.onload = handleResponse; - req.onerror = handleError; - req.open('GET', feedUrl, true); - req.send(null); -} - -/** - * Handles feed parsing errors. - * @param {String} error The localized error message. - */ -function handleFeedParsingFailed(error) { - var feed = $('feed'); - $('noStories').style.display = 'none'; - feed.className = 'error'; - feed.innerText = error; -} - -/** - * Handles errors during the XMLHttpRequest. - */ -function handleError() { - handleFeedParsingFailed(chrome.i18n.getMessage('fetchError')); - $('topics').style.display = 'none'; -} - -/** - * Parses the feed response. - */ -function handleResponse() { - var doc = req.responseXML; - if (!doc) { - handleFeedParsingFailed(chrome.i18n.getMessage('wrongTopic')); - var img = $('title'); - if(!img.src) { - img.src = "/images/news.gif"; - } - - document.querySelector('body').style.minHeight = 0; - return; - } - buildPreview(doc); -} - -// Stores no. of stories selected in options page. -var maxFeedItems = (window.localStorage.getItem('count')) ? - window.localStorage.getItem('count') : 5; - -// Where the more stories link should navigate to. -var moreStoriesUrl; - -/** - * Generates news iframe in pop-up page by parsing retrieved feed. - * @param {HTMLDocument} doc HTML Document received in feed. - */ -function buildPreview(doc) { - // Get the link to the feed source. - var link = doc.querySelector('link'); - var parentTag = link.parentNode.tagName; - if (parentTag != 'item' && parentTag != 'entry') { - moreStoriesUrl = link.textContent; - } - - // Setup the title image. - var image = doc.querySelector('image'); - var titleImg; - - // Stores whether language script is Right to Left or not for setting style - // of share buttons(Facebook, Twitter and Google Buzz) in iframe. - var isRtl = 'lTR'; - - if (image) { - var url = image.querySelector('url'); - if (url) { - titleImg = url.textContent; - - // Stores URL of title image to be shown on pop-up page. - var titleImgUrl = titleImg; - var pattern = /ar_/gi; - var result = titleImgUrl.match(pattern); - if (result != null || titleImgUrl == ISRAEL_IMAGE_URL) { - isRtl = 'rTL'; - } - } - } - - var img = $('title'); - if (titleImg) { - img.src = titleImg; - if (moreStoriesUrl) { - $('title_a').addEventListener('click', moreStories); - } - } else { - img.style.display = 'none'; - } - - // Construct the iframe's HTML. - var iframe_src = '<!doctype html><html><head><script>' + - $('iframe_script').textContent + '<' + - '/script><style> ' + - '.rTL {margin-right: 102px; text-align: right;} ' + - '.lTR {margin-left: 102px; text-align: left;} ' + - '</style></head><body onload="frameLoaded();" ' + - 'style="padding:0px;margin:0px;">'; - - var feed = $('feed'); - feed.className = ''; - var entries = doc.getElementsByTagName('entry'); - if (entries.length == 0) { - entries = doc.getElementsByTagName('item'); - } - var count = Math.min(entries.length, maxFeedItems); - - // Stores required height by pop-up page. - var minHeight = 19; - minHeight = (minHeight * (count - 1)) + 100; - document.querySelector('body').style.minHeight = minHeight + 'px'; - $('feed').innerHTML = ''; - - for (var i = 0; i < count; i++) { - item = entries.item(i); - - // Grab the title for the feed item. - var itemTitle = item.querySelector('title'); - if (itemTitle) { - itemTitle = itemTitle.textContent; - } else { - itemTitle = 'Unknown title'; - } - - // Grab the description. - var itemDesc = item.querySelector('description'); - if (!itemDesc) { - itemDesc = item.querySelector('summary'); - if (!itemDesc) { - itemDesc = item.querySelector('content'); - } - } - if (itemDesc) { - itemDesc = itemDesc.childNodes[0].nodeValue; - - } else { - itemDesc = ''; - } - var itemLink = item.querySelector('link'); - if (itemLink) { - itemLink = itemLink.textContent; - } else { - itemLink = 'Unknown itemLink'; - } - var item = document.createElement('div'); - item.className = 'item'; - var box = document.createElement('div'); - box.className = 'open_box'; - box.addEventListener('click', showDesc); - item.appendChild(box); - - var title = document.createElement('a'); - title.className = 'item_title'; - title.innerText = itemTitle; - title.addEventListener('click', showDesc); - item.appendChild(title); - - var desc = document.createElement('iframe'); - desc.scrolling = 'no'; - desc.className = 'item_desc'; - item.appendChild(desc); - feed.appendChild(item); - - // Adds share buttons images(Facebook, Twitter and Google Buzz). - itemDesc += "<div class = '" + isRtl + "'>"; - itemDesc += "<a style='cursor: pointer' id='fb' " + - "onclick='openNewsShareWindow(this.id,\"" + itemLink + "\")'>" + - "<img src='" + chrome.extension.getURL('/images/fb.png') + "'/></a>"; - itemDesc += " <a style='cursor: pointer' id='twitter' " + - "onclick='openNewsShareWindow(this.id,\"" + itemLink + "\")'>" + - "<img src='" + chrome.extension.getURL('/images/twitter.png') + "'/></a>"; - itemDesc += " <a style='cursor: pointer' id='buzz' " + - "onclick='openNewsShareWindow(this.id,\"" + itemLink + "\")'>" + - "<img src='" + chrome.extension.getURL('/images/buzz.png') + "'/></a>"; - itemDesc += '</div>'; - - // The story body is created as an iframe with a data: URL in order to - // isolate it from this page and protect against XSS. As a data URL, it - // has limited privileges and must communicate back using postMessage(). - desc.src = 'data:text/html;charset=utf-8,' + iframe_src + itemDesc + - '</body></html>'; - } - if (moreStoriesUrl && entries.length != 0) { - var more = document.createElement('a'); - more.className = 'more'; - more.innerText = moreStoriesLocale; - more.addEventListener('click', moreStories); - feed.appendChild(more); - } - setStyleByLang(titleImgUrl); - - // Checks whether feed retrieved has news story or not. If not, then shows - // error message accordingly. - if (entries.length == 0) { - $('noStories').innerText = chrome.i18n.getMessage('noStory'); - $('noStories').style.display = 'block'; - } else { - $('noStories').style.display = 'none'; - } -} - -/** - * Show |url| in a new tab. - * @param {String} url The news URL. - */ -function showUrl(url) { - // Only allow http and https URLs. - if (url.indexOf('http:') != 0 && url.indexOf('https:') != 0) { - return; - } - chrome.tabs.create({url: url}); -} - -/** - * Redirects to Google news site for more stories. - * @param {Object} event Onclick event. - */ -function moreStories(event) { - showUrl(moreStoriesUrl); -} - -/** - * Shows description of the news when users clicks on news title. - * @param {Object} event Onclick event. - */ -function showDesc(event) { - var item_ = event.currentTarget.parentNode; - var items = document.getElementsByClassName('item'); - for (var i = 0, item; item = items[i]; i++) { - var iframe = item.querySelector('.item_desc'); - if (item == item_ && item.className == 'item') { - item.className = 'item opened'; - iframe.contentWindow.postMessage('reportHeight', '*'); - } else { - item.className = 'item'; - iframe.style.height = '0px'; - } - } -} - -/** - * Handles messages between different iframes and sets the display of iframe. - * @param {Object} e Onmessage event. - */ -function iframeMessageHandler(e) { - var iframes = document.getElementsByTagName('IFRAME'); - for (var i = 0, iframe; iframe = iframes[i]; i++) { - if (iframe.contentWindow == e.source) { - var msg = JSON.parse(e.data); - if (msg) { - if (msg.type == 'size') { - iframe.style.height = msg.size + 'px'; - } else if (msg.type == 'show') { - var url = msg.url; - if (url.indexOf('http://news.google.com') == 0) { - // If the URL is a redirect URL, strip of the destination and go to - // that directly. This is necessary because the Google news - // redirector blocks use of the redirects in this case. - var index = url.indexOf('&url='); - if (index >= 0) { - url = url.substring(index + 5); - index = url.indexOf('&'); - if (index >= 0) - url = url.substring(0, index); - } - } - showUrl(url); - } - } - return; - } - } -} - -/** - * Saves last viewed topic by user in local storage on unload of pop-up page. - */ -function saveLastTopic() { - var topicVal = $('topics').value; - window.localStorage.setItem('lastTopic', topicVal); -} - -/** - * Sets the URL according to selected topic(or default topic), then retrieves - * feed and sets pop-up page. - */ -function getNewsByTitle() { - var country = window.localStorage.getItem('country'); - country = (country == 'noCountry' || !country) ? '' : country; - - // Sets direction of topics showed under dropdown in pop-up page according - // to set language in browser. - $('topics').className = (directionLocale == 'rtl') ? 'topicsRTL' : - 'topicsLTR'; - - var topicVal = $('topics').value; - - // Sets Feed URL in case of custom topic selected. - var keywords = JSON.parse(window.localStorage.getItem('keywords')); - var isFound = false; - if (keywords) { - for (i = 0; i < keywords.length; i++) { - if (topicVal == keywords[i]) { - isFound = true; - feedUrl = DEFAULT_NEWS_URL + '&cf=all&ned=' + country + '&q=' + topicVal + - '&hl=' + country; - break; - } - } - } - if (!isFound) { - feedUrl = DEFAULT_NEWS_URL + '&cf=all&ned=' + country + - '&topic=' + topicVal; - } - main(); -} - -/** - * Shows topic list retrieved from local storage(if any),else shows - * default topics list. - */ -function getTopics() { - var topics = JSON.parse(window.localStorage.getItem('topics')); - var keywords = JSON.parse(window.localStorage.getItem('keywords')); - var element = $('topics'); - - // Sets all topics as default list if no list is found from local storage. - if (!topics && !keywords) { - topics = [' ','n','w','b','t','e','s','m','po']; - } - - if (topics) { - for (var i = 0; i < (topics.length); i++) { - var val = (topics[i] == ' ') ? '1' : topics[i]; - element.options[element.options.length] = new Option( - chrome.i18n.getMessage(val), topics[i]); - } - } - - // Shows custom topics in list(if any). - if (keywords) { - for (i = 0; i < (keywords.length); i++) { - element.options[element.options.length] = new Option(keywords[i], - keywords[i]); - } - } - - $('option_link').innerText = chrome.i18n.getMessage('options'); - - var topicVal = window.localStorage.getItem('lastTopic'); - if (topicVal) { - $('topics').value = topicVal; - } -} - -window.addEventListener('message', iframeMessageHandler);
diff --git a/chrome/common/extensions/docs/examples/extensions/news/javascript/options.js b/chrome/common/extensions/docs/examples/extensions/news/javascript/options.js deleted file mode 100644 index d030b367b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/javascript/options.js +++ /dev/null
@@ -1,395 +0,0 @@ -/** - * Copyright (c) 2010 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. - */ - -/** - * @fileoverview Includes the country selection, topics selection and - * selection of no. of news stories to be shown. Include default settings also. - * @author navneetg@google.com (Navneet Goel). - */ - -/** - * Stores number of selected topics on the options page. - */ -var checkCount = 0; - -/** - * Stores maximum count of custom topics. - */ -var MAX_CUS_TOPICS = 10; - -/** - * Stores temporary added custom topics which are not yet saved. - */ -var tempCusTopics = []; - -/** - * Checks whether ENTER key is pressed or not. - */ -function addCustomTopic() { - if (window.event.keyCode == 13) { - addCusTopic(); - } -} - -/** - * Retrieves and sets last saved country from local storage(if found), - * else sets country retrieved from feed. - */ -function setCountry() { - var country = window.localStorage.getItem('country'); - - // If country is not found in localstorage or default value is selected in - // drop down menu. - if ((!country) || country == 'noCountry') { - // XMLHttpRequest object that tries to load the feed for the purpose of - // retrieving the country value out of feed. - var req = new XMLHttpRequest(); - req.onload = handleResponse; - req.onerror = handleError; - req.open('GET', DEFAULT_NEWS_URL, true); - req.send(null); - - // Sets country to default Country in dropdown menu. - function handleError() { - $('countryList').value = 'noCountry'; - }; - - // Handles parsing the feed data got back from XMLHttpRequest. - function handleResponse() { - // Feed document retrieved from URL. - var doc = req.responseXML; - if (!doc) { - handleError(); - return; - } - var imageLink = doc.querySelector('image link'); - if (imageLink) { - // Stores link to set value of country. - var newsUrl = imageLink.textContent; - } - - // Stores country value - $('countryList').value = newsUrl.substring(newsUrl.indexOf('&ned=') + 5, - newsUrl.indexOf('&hl=')); - }; - } else { - $('countryList').value = country; - } -} - -/** - * Displays various messages to user based on user input. - * @param {String} id Id of status element. - * @param {Number} timeOut Timeout value of message shown. - * @param {String} message Message to be shown. - */ -function showUserMessages(id, timeOut, message) { - $(id).style.setProperty('transition', - 'opacity 0s ease-in'); - $(id).style.opacity = 1; - $(id).innerText = chrome.i18n.getMessage(message); - window.setTimeout(function() { - $(id).style.setProperty( - 'transition', 'opacity' + timeOut + 's ease-in'); - $(id).style.opacity = 0; - }, 1E3 - ); -} - -/** - * Sets options page CSS according to the browser language(if found), else sets - * to default locale. - */ -function setOptionPageCSS() { - if (chrome.i18n.getMessage('direction') == 'rtl') { - document.querySelector('body').className = 'rtl'; - } -} - -/** - * Initializes the options page by retrieving country, topics and count of - * stories from local storage if present, else sets to default settings. - */ -function initialize() { - setOptionPageCSS(); - setCountry(); - setCountAndTopicList(); - setLocalizedTopicList(); - - // Adds a custom topic on press of Enter key. - $('newKeyword').onkeypress = addCustomTopic; -} - -/** - * Retrieves locale values from locale file. - */ -function setLocalizedTopicList() { - var getI18nMsg = chrome.i18n.getMessage; - - $('top').innerText = getI18nMsg('1'); - $('nation').innerText = getI18nMsg('n'); - $('world').innerText = getI18nMsg('w'); - $('business').innerText = getI18nMsg('b'); - $('science').innerText = getI18nMsg('t'); - $('entertainment').innerText = getI18nMsg('e'); - $('sports').innerText = getI18nMsg('s'); - $('health').innerText = getI18nMsg('m'); - $('most').innerText = getI18nMsg('po'); - $('select_country').innerText = getI18nMsg('country'); - $('topic').innerText = getI18nMsg('topic'); - $('save_button').innerText = getI18nMsg('save'); - $('story_count').innerText = getI18nMsg('storyCount'); - $('logo').innerHTML = $('logo').innerHTML + getI18nMsg('newsOption'); - $('custom_text').innerHTML = getI18nMsg('customText') + '<br/>' + - getI18nMsg('maximumTopics',[MAX_CUS_TOPICS]); - $('submit_button').value = getI18nMsg('submitButton'); -} - -/** - * Sets topic list and number of stories retrieved from localstorage(if any) - * otherwise sets to default. - */ -function setCountAndTopicList() { - var topicLists = document.getElementsByClassName('checkBox'); - - // Retrieves topics list from localStorage. - var topics = JSON.parse(window.localStorage.getItem('topics')); - - // Runs if retrieved topic list from local storage contains topics. - if (topics) { - for (var x = 0, topicList; topicList = topicLists[x]; x++) { - - // Saves whether checkbox is checked or not. - var isPresent = false; - for (var y = 0; y < topics.length; y++) { - if (topics[y] == topicList.value) { - topicList.checked = true; - isPresent = true; - checkCount++; - break; - } - } - if (!isPresent) { - topicList.checked = false; - } - } - } - - // Retrieves list of custom topics from localstorage(if any) and shows it - // in option page. - var keywords = JSON.parse(window.localStorage.getItem('keywords')); - if (keywords) { - - // Template to store custom topics in a table. - var template = []; - var title = chrome.i18n.getMessage('deleteTitle'); - for (var i = 0; i < keywords.length; i++) { - checkCount++; - - template.push('<tr style = "height: 22px;">'); - template.push('<td id = "keyword_value" class = "cusTopicsClass">'); - template.push('<textarea class="noborder" readonly>'); - template.push(keywords[i]); - template.push('</textarea>'); - template.push('<td class = "suppr" onclick = "delCusTopic(this)" '); - template.push('title="'); - template.push(title); - template.push('">'); - template.push('</td>'); - template.push('</tr>'); - } - $('custom_topics').innerHTML = template.join(''); - if (keywords.length == MAX_CUS_TOPICS) { - $('submit_button').disabled = true; - $('newKeyword').readOnly = 'readonly'; - } - } - // Check all checkboxes(default settings) if no custom topic list and - // checkbox topic list from local storage is found. - if (!keywords && !topics) { - for (var x = 0, topicList; topicList = topicLists[x]; x++) { - topicList.checked = true; - checkCount++; - } - } - - // Retrieves saved value of number of stories. - var count = window.localStorage.getItem('count'); - - // Sets number of stories in dropdown. - if (count) { - $('storyCount').value = count; - } -} - -/** - * Saves checked topic list(if any), Custom topics(if any), number of - * stories and country value in local storage. - */ -function saveTopicsCountry() { - var country = $('countryList').value; - var topicLists = document.getElementsByClassName('checkBox'); - - // Contains selected number of stories. - var count = $('storyCount').value; - - // Stores checked topics list. - var topicArr = []; - for (var i = 0, topicList; topicList = topicLists[i]; i++) { - if (topicList.checked) { - topicArr.push(topicList.value); - } - } - var keywords = JSON.parse(window.localStorage.getItem('keywords')); - - // Saves custom topics to local storage(if any). - if (tempCusTopics.length > 0) { - if (keywords) { - keywords = keywords.concat(tempCusTopics); - window.localStorage.setItem('keywords', JSON.stringify(keywords)); - } else { - window.localStorage.setItem('keywords', JSON.stringify(tempCusTopics)); - } - tempCusTopics.splice(0, tempCusTopics.length); - } - - // Saves checkbox topics(if any). - if (topicArr.length > 0) { - window.localStorage.setItem('topics', JSON.stringify(topicArr)); - } else { - window.localStorage.removeItem('topics'); - } - - window.localStorage.setItem('count', count); - window.localStorage.setItem('country', country); - - showUserMessages('save_status', 0.5, 'saveStatus'); - $('save_button').disabled = true; -} - -/** - * Disables the save button on options page if no topic is selected by the user. - * @param {String} id Id of checkbox checked or unchecked. - */ -function manageCheckCount(id) { - checkCount = ($(id).checked) ? (checkCount + 1) : (checkCount - 1); - $('save_button').disabled = (checkCount == 0) ? true : false; -} - -/** - * Enables save button if at least one topic is selected. - */ -function enableSaveButton() { - if (checkCount != 0) { - $('save_button').disabled = false; - } -} - -/** - * Adds new entered custom topic. - */ -function addCusTopic() { - // Retrieves custom topic list from local storage(if any), else create new - // array list. - var keywords = JSON.parse(window.localStorage.getItem('keywords') || "[]"); - - // Adds topic only if total number of added custom topics are less than 10. - if (keywords.length + tempCusTopics.length <= (MAX_CUS_TOPICS - 1)) { - - // Stores new entered value in input textbox. - var val = $('newKeyword').value; - if (val) { - val = val.trim(); - if (val.length > 0) { - var pattern = /,/g; - - // Runs if comma(,) is not present in topic entered. - if (val.match(pattern) == null) { - checkCount++; - tempCusTopics.push(val); - - // Template to store custom topics in a table. - var template = []; - var title = chrome.i18n.getMessage('deleteTitle'); - - template.push('<tr style = "height: 22px;">'); - template.push('<td id = "keyword_value" class = "cusTopicsClass">'); - template.push('<textarea class="noborder" readonly>'); - template.push(val); - template.push('</textarea>'); - template.push('<td class = "suppr" onclick = "delCusTopic(this)" '); - template.push('title="'); - template.push(title); - template.push('">'); - template.push('</td>'); - template.push('</tr>'); - - $('custom_topics').innerHTML += template.join(''); - enableSaveButton(); - } else { - showUserMessages('invalid_status', 2.5, 'invalidChars'); - } - } - $('newKeyword').value = ''; - } - } - - if ((keywords.length + tempCusTopics.length) == (MAX_CUS_TOPICS)) { - $('submit_button').disabled = true; - $('newKeyword').readOnly = 'readonly'; - } -} - -/** - * Delete custom topic whenever users click on delete icon. - * @param {HTMLTableColElement} obj HTML table column element to be deleted. - */ -function delCusTopic(obj) { - // Deletes only if total number of topics are greater than 1, else shows - // error message. - if (checkCount > 1) { - var value; - - // Extract custom topic value. - value = obj.parentNode.querySelector('.cusTopicsClass textarea').value; - - // Removes custom topic element from UI. - $('custom_topics').removeChild(obj.parentNode); - - // Removes custom topic element either from temporary array(if topic is - // not yet saved) or from saved topic list and saves new list to - // local storage. - var flag = 0; - for (var i = 0; i < tempCusTopics.length; i++) { - if (tempCusTopics[i] == value) { - tempCusTopics.splice(i, 1); - flag = 1; - break; - } - } - - if (flag == 0) { - var keywords = JSON.parse(window.localStorage.getItem('keywords')); - for (i = 0; i < keywords.length; i++) { - if (keywords[i] == value) { - keywords.splice(i, 1); - break; - } - } - if (keywords.length > 0) { - window.localStorage.setItem('keywords', JSON.stringify(keywords)); - } else { - window.localStorage.removeItem('keywords'); - } - } - - checkCount--; - $('submit_button').disabled = false; - } else { - showUserMessages('save_status', 2.5, 'noTopic'); - } - $('newKeyword').readOnly = false; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news/javascript/util.js b/chrome/common/extensions/docs/examples/extensions/news/javascript/util.js deleted file mode 100644 index f8e3880..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/javascript/util.js +++ /dev/null
@@ -1,29 +0,0 @@ -/** - * Copyright (c) 2010 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. - */ - -/** - * @fileoverview Defines the constants and most commonly used functions. - * @author navneetg@google.com (Navneet Goel). - */ - -/** - * Default feed news URL. - */ -var DEFAULT_NEWS_URL = 'http://news.google.com/news?output=rss'; - -/** - * Image URL of Israel country. - */ -var ISRAEL_IMAGE_URL = 'http://www.gstatic.com/news/img/logo/iw_il/news.gif'; - -/** - * Alias for getElementById. - * @param {String} elementId Element id of the HTML element to be fetched. - * @return {Element} Element corresponding to the element id. - */ -function $(elementId) { - return document.getElementById(elementId); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news/manifest.json b/chrome/common/extensions/docs/examples/extensions/news/manifest.json deleted file mode 100644 index a64df9c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/manifest.json +++ /dev/null
@@ -1,20 +0,0 @@ -{ - "name": "__MSG_extName__", - "version": "2.0", - "description": "__MSG_extDesc__", - "icons": { "128": "images/news_icon.png" }, - "default_locale":"en", - "browser_action": { - "default_title": "__MSG_ext_default_title__", - "default_icon": "images/news_action.png", - "default_popup": "views/feed.html" - }, - "permissions": [ - "tabs", - "http://news.google.com/*" - ], - "options_page": "views/options.html", - "background": { - "page": "views/background.html" - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news/views/background.html b/chrome/common/extensions/docs/examples/extensions/news/views/background.html deleted file mode 100644 index c97e9776f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/views/background.html +++ /dev/null
@@ -1,27 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. ---> - -<!-- -@fileoverview Contains script for running at the background to open up the -options page when the extension is reloaded. ---> - -<html> - <body> - <script> - //Retrieves value from local storage(if found). - var newsFlag = window.localStorage.getItem('newsFlag'); - - //Runs if extension installation is done. - if(!newsFlag) { - var optionsPageURL = chrome.extension.getURL('/views/options.html'); - chrome.tabs.create({url: optionsPageURL}); - window.localStorage.setItem('newsFlag','1'); - } - </script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/news/views/feed.html b/chrome/common/extensions/docs/examples/extensions/news/views/feed.html deleted file mode 100644 index 43d147b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/views/feed.html +++ /dev/null
@@ -1,146 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. ---> - -<!-- -@fileoverview This file serves as the pop-up page for showing news -according to the settings saved in options page otherwise shows default -settings. -@author navneetg@google.com (Navneet Goel). ---> - -<html> -<head> -<script src = "/javascript/util.js"></script> -<link rel = "stylesheet" href = "/css/feed.css"/> - -<script id = "iframe_script"> - -/** - * Facebook share URL. - */ -var FB_SHARE_URL = "http://www.facebook.com/sharer.php?u="; - -/** - * Twitter share URL. - */ -var TWITTER_SHARE_URL = "http://twitter.com/share?&url="; - -/** - * Buzz share URL. - */ -var BUZZ_SHARE_URL = "http://www.google.com/buzz/post?&url="; - -/** - * Opens new window either of facebook, twitter or google buzz. - * @param {String} id Specifies whether to share news on Facebook, Google Buzz - * or Twitter. - * @param {String} url Contains URL of the News to be shared. - */ -function openNewsShareWindow(id, url) { - var newsUrl = url.substring(url.indexOf('&url=') + 5); - var openUrl; - switch (id) { - case 'fb': - openUrl = FB_SHARE_URL; - break; - case 'buzz': - openUrl = BUZZ_SHARE_URL; - break; - case 'twitter': - openUrl = TWITTER_SHARE_URL; - break; - } - window.open(openUrl + newsUrl, '_blank', - 'resizable=0,scrollbars=0,width=690,height=415'); -} - -/** - * Checks language in image url retrieved from feed and sets style of - * title and openbox in pop-up page(if url is found), otherwise sets - * to default styling. - */ -function setStyleByLang(titleImgUrl) { - var openBoxes = document.getElementsByClassName('open_box'); - var itemTitles = document.getElementsByClassName('item_title'); - - if (titleImgUrl != 'NULL') { - var pattern = /ar_/gi; - var result = titleImgUrl.match(pattern); - if (result != null || titleImgUrl == ISRAEL_IMAGE_URL) { - document.querySelector('body').className = 'rtl'; - } - } -} - -/** - * Reports the height. - */ -function reportHeight() { - var msg = JSON.stringify({type:"size", size:document.body.offsetHeight}); - parent.postMessage(msg, "*"); -} - -/** - * Initialize the iframe body. - */ -function frameLoaded() { - var links = document.getElementsByTagName("A"); - for (var i = 0, link; link = links[i]; i++) { - var class = link.className; - if (class != "item_title" && class != "open_box") { - link.addEventListener("click", showStory); - } - } - window.addEventListener("message", messageHandler); -} - -/** - * Redirects to Google news site according to clicked URL. - * @param {Object} event Onclick event. - */ -function showStory(event) { - var href = event.currentTarget.href; - parent.postMessage(JSON.stringify({type:"show", url:href}), "*"); - event.preventDefault(); -} - -/** - * Handles message. - * @param {Object} event Onmessage event. - */ -function messageHandler(event) { - reportHeight(); -} -</script> -<script src = "/javascript/feed.js"></script> -</head> - -<body onload = "getTopics();getNewsByTitle();" onunload = "saveLastTopic();"> - -<div style = "margin-bottom: 15px;"> - <div style = "float: right;"> - <div style = "float: right; font-size: 11px"> - <a id = "option_link" onclick = "chrome.tabs.create({url: '/views/options.html', selected: true})"> - </a> - </div> - <div style = "margin-top: 27px"> - <select id = "topics" onchange = "getNewsByTitle();" style = "display: inline;"> - </select> - </div> - </div> - <a id = "title_a"> - <img id = "title" style = "padding-top: 5px;"> - </a> -</div> - -<div id = "feed"> -</div> - -<div id = "noStories"> -</div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/news/views/options.html b/chrome/common/extensions/docs/examples/extensions/news/views/options.html deleted file mode 100644 index 6bf99b3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news/views/options.html +++ /dev/null
@@ -1,166 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2010 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. ---> - -<!-- -@fileoverview This file serves as the option page of the extension for -customizing the settings such as setting country, topics and number of -news stories to be shown. -@author navneetg@google.com (Navneet Goel). ---> - -<html> - <head> - <script src = "/javascript/util.js"></script> - <meta http-equiv = "Content-Type" content = "text/html; charset = UTF-8"> - <link rel = "stylesheet" href = "/css/options.css"/> - <script src = "/javascript/options.js"></script> - </head> - <body onload = "initialize();"> - <div id = "all_content"> - <div id = "logo"> - <img id = "title_image" src = "/images/news.gif"/> - <br/> - </div> - <br/><br/> - - <table class = "contentTable" style = "margin-left: 55px;" width = "96%"> - <tr class = "all_rows"> - <td class = "col1"><b id = "select_country"></b></td> - <td class = "col2"> - <select id = "countryList" onchange = "enableSaveButton();"> - <option value = "noCountry">-Select-</option> - <option value = "es_ar">Argentina</option> - <option value = "au">Australia</option> - <option value = "nl_be">België</option> - <option value = "fr_be">Belgique</option> - <option value = "en_bw">Botswana</option> - <option value = "pt-BR_br">Brasil</option> - <option value = "ca">Canada English</option> - <option value = "fr_ca">Canada Français</option> - <option value = "cs_cz">Česká republika</option> - <option value = "es_cl">Chile</option> - <option value = "es_co">Colombia</option> - <option value = "es_cu">Cuba</option> - <option value = "de">Deutschland</option> - <option value = "es">España</option> - <option value = "es_us">Estados Unidos</option> - <option value = "en_et">Ethiopia</option> - <option value = "fr">France</option> - <option value = "en_gh">Ghana</option> - <option value = "in">India</option> - <option value = "en_ie">Ireland</option> - <option value = "en_il">Israel English</option> - <option value = "it">Italia</option> - <option value = "en_ke">Kenya</option> - <option value = "hu_hu">Magyarország</option> - <option value = "en_my">Malaysia</option> - <option value = "es_mx">México</option> - <option value = "en_na">Namibia</option> - <option value = "nl_nl">Nederland</option> - <option value = "nz">New Zealand</option> - <option value = "en_ng">Nigeria</option> - <option value = "no_no">Norge</option> - <option value = "de_at">Österreich</option> - <option value = "en_pk">Pakistan</option> - <option value = "es_pe">Perú</option> - <option value = "en_ph">Philippines</option> - <option value = "pl_pl">Polska</option> - <option value = "pt-PT_pt">Portugal</option> - <option value = "de_ch">Schweiz</option> - <option value = "fr_sn">Sénégal</option> - <option value = "en_sg">Singapore</option> - <option value = "en_za">South Africa</option> - <option value = "fr_ch">Suisse</option> - <option value = "sv_se">Sverige</option> - <option value = "en_tz">Tanzania</option> - <option value = "tr_tr">Türkiye</option> - <option value = "uk">U.K.</option> - <option value = "us">U.S.</option> - <option value = "en_ug">Uganda</option> - <option value = "es_ve">Venezuela</option> - <option value = "vi_vn">Việt Nam (Vietnam)</option> - <option value = "en_zw">Zimbabwe</option> - <option value = "el_gr">Ελλάδα (Greece)</option> - <option value = "ru_ru">Россия (Russia)</option> - <option value = "ru_ua">Украина / русский (Ukraine)</option> - <option value = "uk_ua">Україна / українська (Ukraine)</option> - <option value = "iw_il">ישראל (Israel)</option> - <option value = "ar_ae">الإمارات (UAE)</option> - <option value = "ar_sa">السعودية (KSA)</option> - <option value = "ar_me">العالم العربي (Arabic)</option> - <option value = "ar_lb">لبنان (Lebanon)</option> - <option value = "ar_eg">مصر (Egypt)</option> - <option value = "hi_in">हिन्दी (India)</option> - <option value = "ta_in">தமிழ்(India)</option> - <option value = "te_in">తెలుగు (India)</option> - <option value = "ml_in">മലയാളം (India)</option> - <option value = "kr">한국 (Korea)</option> - <option value = "cn">中国版 (China)</option> - <option value = "tw">台灣版 (Taiwan)</option> - <option value = "jp">日本 (Japan)</option> - <option value = "hk">香港版 (Hong Kong)</option> - </select> - </td> - </tr> - <tr class = "all_rows"> - <td class = "col1"><b id = "story_count"></b></td> - <td class = "col2"> - <select id = "storyCount" style = "padding-left: 3px;" onchange = "enableSaveButton();"> - <option value = "1">1</option> - <option value = "2">2</option> - <option value = "3">3</option> - <option value = "4">4</option> - <option value = "5" selected = "selected">5</option> - <option value = "6">6</option> - <option value = "7">7</option> - <option value = "8">8</option> - <option value = "9">9</option> - <option value = "10">10</option> - </select> - </td> - </tr> - <tr class = "all_rows"> - <td class = "col1"> - <div id = "topic" style = "font-weight: bold;"></div> - </td> - <td class = "col2"> - <div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = " " id = "check11" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "top"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "n" id = "check13" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "nation"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "w" id = "check14" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "world"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "b" id = "check15" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "business"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "t" id = "check16" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "science"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "e" id = "check17" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "entertainment"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "s" id = "check18" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "sports"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "m" id = "check19" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "health"></div><br/></div> - <div class = "boxAndTopic"><input class = "checkBox" type = "checkbox" value = "po" id = "check20" onchange = "manageCheckCount(this.id)"/><div class = "checkBoxTopic" id = "most"></div><br/></div> - </div> - </td> - </tr> - <tr class = "all_rows"> - <td class = "col1"> - <div id = "custom_text" style = "font-weight: bold;"></div> - </td> - <td class = "col2"> - <input id = "newKeyword" type = "text" maxlength = "20" style = "width: 205px;"> - <input id = "submit_button" type = "submit" onclick = "addCusTopic()" style = "width: 45px;"> - <span id = "invalid_status"></span> - <table> - <tbody id = "custom_topics"></tbody> - </table> - </td> - </tr> - </table> - <br/> - <div id = "save_div"> - <button id = "save_button" type = "button" disabled = "disabled" onclick = "saveTopicsCountry()" style = "width: 80px;"> - </button> - <span id = "save_status"></span> - </div> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.css b/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.css deleted file mode 100644 index ede6f47..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.css +++ /dev/null
@@ -1,74 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -body { - font-family: helvetica, arial, sans-serif; - font-size: 12px; - overflow: hidden; -} - -a { - color:#0000CC; - text-decoration: underline; - cursor: pointer; -} - -.open_box { - display: block; - overflow: hidden; - margin-right: 4px; - margin-top: 2px; - height: 12px; - width: 12px; - float: left; - clear: left; - background-image: url(sprite_arrows.gif); - background-position: 0px -24px; - cursor: pointer; -} - -.opened .open_box { - background-position:-12px -24px; -} - -.item { - padding: 2px 0px; -} - -.item_title { - display: block; - min-width: 300px; - padding-left: 15px; - cursor: pointer; -} - -.item_desc { - min-width: 500px; - height: 0px; - display: block; - border: none; - padding: 0px; - margin: 0px; - transition: height 0.2s ease-out; -} - -#title { - display: block; - margin-left: auto; -} - -.error { - white-space: nowrap; - color: red; -} - -.more { - display: block; - text-align: right; - padding-top: 20px; - padding-right: 10px; - color: #88C; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.html b/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.html deleted file mode 100644 index 4451240..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <link href="feed.css" rel="stylesheet" type="text/css"> - <script src="feed.js"></script> - </head> - <body> - <a id="title_a" tabIndex="0"><img id='title' alt="Google News logo"></a> - <div id="feed"></div> - </body> -</html> -
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.js b/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.js deleted file mode 100644 index 9c45bce..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed.js +++ /dev/null
@@ -1,277 +0,0 @@ -// Copyright (c) 2011 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. - -// Feed -var feedUrl = 'http://news.google.com/?output=rss'; - -// The XMLHttpRequest object that tries to load and parse the feed. -var req; - -function main() { - req = new XMLHttpRequest(); - req.onload = handleResponse; - req.onerror = handleError; - req.open('GET', feedUrl, true); - req.send(null); -} - -// Handles feed parsing errors. -function handleFeedParsingFailed(error) { - var feed = document.getElementById('feed'); - feed.className = 'error'; - feed.innerText = 'Error: ' + error; -} - -// Handles errors during the XMLHttpRequest. -function handleError() { - handleFeedParsingFailed('Failed to fetch RSS feed.'); -} - -// Handles parsing the feed data we got back from XMLHttpRequest. -function handleResponse() { - var doc = req.responseXML; - if (!doc) { - handleFeedParsingFailed('Not a valid feed.'); - return; - } - buildPreview(doc); -} - -// The maximum number of feed items to show in the preview. -var maxFeedItems = 5; - -// Where the more stories link should navigate to. -var moreStoriesUrl; - -function buildPreview(doc) { - // Get the link to the feed source. - var link = doc.getElementsByTagName('link'); - var parentTag = link[0].parentNode.tagName; - if (parentTag != 'item' && parentTag != 'entry') { - moreStoriesUrl = link[0].textContent; - } - - // Setup the title image. - var images = doc.getElementsByTagName('image'); - var titleImg; - if (images.length != 0) { - var urls = images[0].getElementsByTagName('url'); - if (urls.length != 0) { - titleImg = urls[0].textContent; - } - } - var img = document.getElementById('title'); - // Listen for mouse and key events - if (titleImg) { - img.src = titleImg; - if (moreStoriesUrl) { - document.getElementById('title_a').addEventListener('click', - moreStories); - document.getElementById('title_a').addEventListener('keydown', - function(event) { - if (event.keyCode == 13) { - moreStories(event); - }}); - } - } else { - img.style.display = 'none'; - } - - // Construct the iframe's HTML. - var iframe_src = '<!doctype html><html><head><script ' + - 'src="chrome-extension://ldglnfnokeifbcaeppacaejckagballg/' + - 'feed_iframe.js"><' + '/script><link href="chrome-extension://ldglnf' + - 'nokeifbcaeppacaejckagballg/feed_iframe.css" rel="stylesheet" ' + - 'type="text/css"></head><body>'; - - var feed = document.getElementById('feed'); - // Set ARIA role indicating the feed element has a tree structure - feed.setAttribute('role', 'tree'); - - var entries = doc.getElementsByTagName('entry'); - if (entries.length == 0) { - entries = doc.getElementsByTagName('item'); - } - var count = Math.min(entries.length, maxFeedItems); - for (var i = 0; i < count; i++) { - item = entries.item(i); - - // Grab the title for the feed item. - var itemTitle = item.getElementsByTagName('title')[0]; - if (itemTitle) { - itemTitle = itemTitle.textContent; - } else { - itemTitle = 'Unknown title'; - } - - // Grab the description. - var itemDesc = item.getElementsByTagName('description')[0]; - if (!itemDesc) { - itemDesc = item.getElementsByTagName('summary')[0]; - if (!itemDesc) { - itemDesc = item.getElementsByTagName('content')[0]; - } - } - if (itemDesc) { - itemDesc = itemDesc.childNodes[0].nodeValue; - } else { - itemDesc = ''; - } - - var item = document.createElement('div'); - item.className = 'item'; - var box = document.createElement('div'); - box.className = 'open_box'; - box.addEventListener('click', showDesc); - // Disable focusing on box image separately from rest of tree item - box.tabIndex = -1; - item.appendChild(box); - - var title = document.createElement('a'); - title.className = 'item_title'; - // Give title an ID for use with ARIA - title.id = 'item' + i; - title.innerText = itemTitle; - title.addEventListener('click', showDesc); - title.addEventListener('keydown', keyHandlerShowDesc); - // Update aria-activedescendant property in response to focus change - // within the tree - title.addEventListener('focus', function(event) { - feed.setAttribute( - 'aria-activedescendant', this.id); - }); - // Enable keyboard focus on the item title element - title.tabIndex = 0; - // Set ARIA role role indicating that the title element is a node in the - // tree structure - title.setAttribute('role', 'treeitem'); - // Set the ARIA state indicating this tree item is currently collapsed. - title.setAttribute('aria-expanded', 'false'); - // Set ARIA property indicating that all items are at the same hierarchical - // level (no nesting) - title.setAttribute('aria-level', '1'); - item.appendChild(title); - - var desc = document.createElement('iframe'); - desc.scrolling = 'no'; - desc.className = 'item_desc'; - // Disable keyboard focus on elements in iFrames that have not been - // displayed yet - desc.tabIndex = -1; - - // The story body is created as an iframe with a data: URL in order to - // isolate it from this page and protect against XSS. As a data URL, it - // has limited privileges and must communicate back using postMessage(). - desc.src='data:text/html,' + iframe_src + itemDesc + '</body></html>'; - - item.appendChild(desc); - feed.appendChild(item); - } - - if (moreStoriesUrl) { - var more = document.createElement('a'); - more.className = 'more'; - more.innerText = 'More stories \u00BB'; - more.tabIndex = 0; - more.addEventListener('click', moreStories); - more.addEventListener('keydown', function(event) { - if (event.keyCode == 13) { - moreStories(event); - }}); - feed.appendChild(more); - } -} - -// Show |url| in a new tab. -function showUrl(url) { - // Only allow http and https URLs. - if (!url.startsWith('http:') && !url.startsWith('https:')) - return; - - chrome.tabs.create({url: url}); -} - -function moreStories(event) { - showUrl(moreStoriesUrl); -} - -function keyHandlerShowDesc(event) { -// Display content under heading when spacebar or right-arrow pressed -// Hide content when spacebar pressed again or left-arrow pressed -// Move to next heading when down-arrow pressed -// Move to previous heading when up-arrow pressed - if (event.keyCode == 32) { - showDesc(event); - } else if ((this.parentNode.className == 'item opened') && - (event.keyCode == 37)) { - showDesc(event); - } else if ((this.parentNode.className == 'item') && (event.keyCode == 39)) { - showDesc(event); - } else if (event.keyCode == 40) { - if (this.parentNode.nextSibling) { - this.parentNode.nextSibling.children[1].focus(); - } - } else if (event.keyCode == 38) { - if (this.parentNode.previousSibling) { - this.parentNode.previousSibling.children[1].focus(); - } - } -} - -function showDesc(event) { - var item = event.currentTarget.parentNode; - var items = document.getElementsByClassName('item'); - for (var i = 0; i < items.length; i++) { - var iframe = items[i].getElementsByClassName('item_desc')[0]; - if (items[i] == item && items[i].className == 'item') { - items[i].className = 'item opened'; - iframe.contentWindow.postMessage('reportHeight', '*'); - // Set the ARIA state indicating the tree item is currently expanded. - items[i].getElementsByClassName('item_title')[0]. - setAttribute('aria-expanded', 'true'); - iframe.tabIndex = 0; - } else { - items[i].className = 'item'; - iframe.style.height = '0px'; - // Set the ARIA state indicating the tree item is currently collapsed. - items[i].getElementsByClassName('item_title')[0]. - setAttribute('aria-expanded', 'false'); - iframe.tabIndex = -1; - } - } -} - -function iframeMessageHandler(e) { - // Only listen to messages from one of our own iframes. - var iframes = document.getElementsByTagName('IFRAME'); - for (var i = 0; i < iframes.length; i++) { - if (iframes[i].contentWindow == e.source) { - var msg = JSON.parse(e.data); - if (msg) { - if (msg.type == 'size') { - iframes[i].style.height = msg.size + 'px'; - } else if (msg.type == 'show') { - var url = msg.url; - if (url.startsWith('http://news.google.com')) { - // If the URL is a redirect URL, strip of the destination and go to - // that directly. This is necessary because the Google news - // redirector blocks use of the redirects in this case. - var index = url.indexOf('&url='); - if (index >= 0) { - url = url.substring(index + 5); - index = url.indexOf('&'); - if (index >= 0) - url = url.substring(0, index); - } - } - showUrl(url); - } - } - return; - } - } -} - -window.addEventListener('message', iframeMessageHandler); -document.addEventListener('DOMContentLoaded', main);
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed_iframe.css b/chrome/common/extensions/docs/examples/extensions/news_a11y/feed_iframe.css deleted file mode 100644 index 159417ff..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed_iframe.css +++ /dev/null
@@ -1,10 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -body { - margin: 0; - padding: 0; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed_iframe.js b/chrome/common/extensions/docs/examples/extensions/news_a11y/feed_iframe.js deleted file mode 100644 index 0fcb590..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/feed_iframe.js +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright (c) 2011 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. - -function reportHeight() { - var msg = JSON.stringify({type:"size", size:document.body.offsetHeight}); - parent.postMessage(msg, "*"); -} - -function frameLoaded() { - var links = document.getElementsByTagName("A"); - for (i = 0; i < links.length; i++) { - var c = links[i].className; - if (c != "item_title" && c != "open_box") { - links[i].addEventListener("click", showStory); - } - } - window.addEventListener("message", messageHandler); -} - -function showStory(event) { - var href = event.currentTarget.href; - parent.postMessage(JSON.stringify({type:"show", url:href}), "*"); - event.preventDefault(); -} - -function messageHandler(event) { - reportHeight(); -} - -document.addEventListener('DOMContentLoaded', frameLoaded);
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/manifest.json b/chrome/common/extensions/docs/examples/extensions/news_a11y/manifest.json deleted file mode 100644 index 496ad4f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "News Reader", - "version": "1.1", - "description": "Displays the first 5 items from the 'Google News - top news' RSS feed in a popup.", - "icons": { "128": "news_icon.png" }, - "browser_action": { - "default_title": "Google News", - "default_icon": "news_action.png", - "default_popup": "feed.html" - }, - "permissions": [ - "tabs", - "http://news.google.com/*" - ], - "manifest_version": 2, - "content_security_policy": "img-src 'self' http://* https://*; script-src 'self'; connect-src http://news.google.com; frame-src data:" -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/news_action.png b/chrome/common/extensions/docs/examples/extensions/news_a11y/news_action.png deleted file mode 100644 index 7d6d9e08..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/news_action.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/news_icon.png b/chrome/common/extensions/docs/examples/extensions/news_a11y/news_icon.png deleted file mode 100644 index aa864d98..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/news_icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news_a11y/sprite_arrows.gif b/chrome/common/extensions/docs/examples/extensions/news_a11y/sprite_arrows.gif deleted file mode 100644 index 4560faf4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_a11y/sprite_arrows.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/en/messages.json deleted file mode 100644 index 9f5ea5d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/en/messages.json +++ /dev/null
@@ -1,63 +0,0 @@ -{ - "name": { - "message": "News Reader", - "description": "Extension name in manifest." - }, - "description": { - "message": "Displays the first 5 items from the '$Google$ News - top news' RSS feed in a popup.", - "description": "Extension description in manifest.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "default_title": { - "message": "$Google$ News", - "description": "Extension browser action tooltip text in manifest.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "unknown_title": { - "message": "Unknown title", - "description": "Unknown news title." - }, - "error": { - "message": "Error: $error$", - "description": "Generic error template. Expects error parameter to be passed in.", - "placeholders": { - "error": { - "content": "$1", - "example": "Failed to fetch RSS feed." - } - } - }, - "failed_to_fetch_rss": { - "message": "Failed to fetch RSS feed.", - "description": "User visible error message." - }, - "not_a_valid_feed": { - "message": "Not a valid feed.", - "description": "User visible error message." - }, - "more_stories": { - "message": "To $Google$ News \u00BB", - "description": "Link name to more Google News.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "newsUrl": { - "message": "http://news.google.com", - "description": "Url to Google News." - } -} -
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/es/messages.json b/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/es/messages.json deleted file mode 100644 index 2093149..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/es/messages.json +++ /dev/null
@@ -1,63 +0,0 @@ -{ - "name": { - "message": "Lector de noticias", - "description": "Nombre de la extensión en el manifiesto." - }, - "description": { - "message": "Muestra los primeros 5 eventos de '$Google$ noticias - destacados' RSS feed en una ventana.", - "description": "Descripción de la extensión en el manifiesto.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "default_title": { - "message": "$Google$ noticias", - "description": "Texto de la accion de menú de la extension en el manifiesto.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "unknown_title": { - "message": "Título desconocido", - "description": "Noticia con título desconocido." - }, - "error": { - "message": "Error: $error$", - "description": "Plantilla de error genérico. Hace falta pasar un parámetro de error.", - "placeholders": { - "error": { - "content": "$1", - "example": "Fallo al capturar el RSS feed." - } - } - }, - "failed_to_fetch_rss": { - "message": "Fallo al capturar el RSS feed.", - "description": "Mensaje de error visible para el usuario." - }, - "not_a_valid_feed": { - "message": "Feed no válido.", - "description": "Mensaje de error visible para el usuario." - }, - "more_stories": { - "message": "Ir a $Google$ noticias \u00BB", - "description": "Nombre del enlace a Google noticias.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "newsUrl": { - "message": "http://news.google.es", - "description": "Dirección de Google News." - } -} -
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/sr/messages.json b/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/sr/messages.json deleted file mode 100644 index 7d43d7a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/_locales/sr/messages.json +++ /dev/null
@@ -1,59 +0,0 @@ -{ - "name": { - "message": "Читач вести", - "description": "Назив екстензије у манифесту." - }, - "description": { - "message": "Приказује првих 5 вести са '$Google$ Вести - главне вести' у прозорчићу.", - "description": "Опис екстензије у манифесту.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "default_title": { - "message": "$Google$ Вести", - "description": "Назив дугмета екстензије.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - }, - "unknown_title": { - "message": "Непознат наслов", - "description": "Непознат наслов вести." - }, - "error": { - "message": "Грешка - $error$", - "description": "Општи облик грешке.", - "placeholders": { - "error": { - "content": "$1", - "example": "фид је недоступан." - } - } - }, - "failed_to_fetch_rss": { - "message": "фид је недоступан.", - "description": "Порука грешке коју види корисник када је фид недоступан." - }, - "not_a_valid_feed": { - "message": "неисправан фид.", - "description": "Порука грешке коју види корисник када је фид неисправан." - }, - "more_stories": { - "message": "Ка $Google$ Вестима \u00BB", - "description": "Назив везе ка још вести.", - "placeholders": { - "google": { - "content": "Google", - "example": "Google" - } - } - } -} -
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/feed.html b/chrome/common/extensions/docs/examples/extensions/news_i18n/feed.html deleted file mode 100644 index 07f54509..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/feed.html +++ /dev/null
@@ -1,310 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<style> -body { - font-family: helvetica, arial, sans-serif; - font-size: 12px; - overflow: hidden; -} - -a { - color:#0000CC; - text-decoration: underline; - cursor: pointer; -} - -.open_box { - display: block; - overflow: hidden; - margin-right: 4px; - margin-top: 2px; - height: 12px; - width: 12px; - float: left; - clear: left; - background-image: url(sprite_arrows.gif); - background-position: 0px -24px; - cursor: pointer; -} - -.opened .open_box { - background-position:-12px -24px; -} - -.item { - padding: 2px 0px; -} - -.item_title { - display: block; - min-width: 300px; - padding-left: 15px; - cursor: pointer; -} - -.item_desc { - min-width: 500px; - height: 0px; - display: block; - border: none; - padding: 0px; - margin: 0px; - transition: height 0.2s ease-out; -} - -#title { - display: block; - margin-left: auto; -} - -.error { - white-space: nowrap; - color: red; -} - -.more { - display: block; - text-align: right; - padding-top: 20px; - padding-right: 10px; - color: #88C; -} - -</style> -<script id="iframe_script"> -function reportHeight() { - var msg = JSON.stringify({type:"size", size:document.body.offsetHeight}); - parent.postMessage(msg, "*"); -} - -function frameLoaded() { - var links = document.getElementsByTagName("A"); - for (i = 0; i < links.length; i++) { - var class = links[i].className; - if (class != "item_title" && class != "open_box") { - links[i].addEventListener("click", showStory); - } - } - window.addEventListener("message", messageHandler); -} - -function showStory(event) { - var href = event.currentTarget.href; - parent.postMessage(JSON.stringify({type:"show", url:href}), "*"); - event.preventDefault(); -} - -function messageHandler(event) { - reportHeight(); -} - -</script> -<script> -// Feed URL. -var feedUrl = chrome.i18n.getMessage('newsUrl') + '/?output=rss'; - -// The XMLHttpRequest object that tries to load and parse the feed. -var req; - -function main() { - req = new XMLHttpRequest(); - req.onload = handleResponse; - req.onerror = handleError; - req.open("GET", feedUrl, true); - req.send(null); -} - -// Handles feed parsing errors. -function handleFeedParsingFailed(error) { - var feed = document.getElementById("feed"); - feed.className = "error"; - feed.innerText = chrome.i18n.getMessage("error", error); -} - -// Handles errors during the XMLHttpRequest. -function handleError() { - handleFeedParsingFailed(chrome.i18n.getMessage('failed_to_fetch_rss')); -} - -// Handles parsing the feed data we got back from XMLHttpRequest. -function handleResponse() { - var doc = req.responseXML; - if (!doc) { - handleFeedParsingFailed(chrome.i18n.getMessage('not_a_valid_feed')); - return; - } - buildPreview(doc); -} - -// The maximum number of feed items to show in the preview. -var maxFeedItems = 5; - -// Where the more stories link should navigate to. -var moreStoriesUrl; - -function buildPreview(doc) { - // Get the link to the feed source. - var link = doc.getElementsByTagName("link"); - var parentTag = link[0].parentNode.tagName; - if (parentTag != "item" && parentTag != "entry") { - moreStoriesUrl = link[0].textContent; - } - - // Setup the title image. - var images = doc.getElementsByTagName("image"); - var titleImg; - if (images.length != 0) { - var urls = images[0].getElementsByTagName("url"); - if (urls.length != 0) { - titleImg = urls[0].textContent; - } - } - var img = document.getElementById("title"); - if (titleImg) { - img.src = titleImg; - if (moreStoriesUrl) { - document.getElementById("title_a").addEventListener("click", moreStories); - } - } else { - img.style.display = "none"; - } - - // Construct the iframe's HTML. - var iframe_src = "<!doctype html><html><head><script>" + - document.getElementById("iframe_script").textContent + "<" + - "/script></head><body onload='frameLoaded();' " + - "style='padding:0px;margin:0px;'>"; - - var feed = document.getElementById("feed"); - var entries = doc.getElementsByTagName('entry'); - if (entries.length == 0) { - entries = doc.getElementsByTagName('item'); - } - var count = Math.min(entries.length, maxFeedItems); - for (var i = 0; i < count; i++) { - item = entries.item(i); - - // Grab the title for the feed item. - var itemTitle = item.getElementsByTagName('title')[0]; - if (itemTitle) { - itemTitle = itemTitle.textContent; - } else { - itemTitle = chrome.i18n.getMessage("unknown_title"); - } - - // Grab the description. - var itemDesc = item.getElementsByTagName('description')[0]; - if (!itemDesc) { - itemDesc = item.getElementsByTagName('summary')[0]; - if (!itemDesc) { - itemDesc = item.getElementsByTagName('content')[0]; - } - } - if (itemDesc) { - itemDesc = itemDesc.childNodes[0].nodeValue; - } else { - itemDesc = ''; - } - - var item = document.createElement("div"); - item.className = "item"; - var box = document.createElement("div"); - box.className = "open_box"; - box.addEventListener("click", showDesc); - item.appendChild(box); - - var title = document.createElement("a"); - title.className = "item_title"; - title.innerText = itemTitle; - title.addEventListener("click", showDesc); - item.appendChild(title); - - var desc = document.createElement("iframe"); - desc.scrolling = "no"; - desc.className = "item_desc"; - item.appendChild(desc); - feed.appendChild(item); - - // The story body is created as an iframe with a data: URL in order to - // isolate it from this page and protect against XSS. As a data URL, it - // has limited privileges and must communicate back using postMessage(). - desc.src="data:text/html," + iframe_src + itemDesc + "</body></html>"; - } - - if (moreStoriesUrl) { - var more = document.createElement("a"); - more.className = "more"; - more.innerText = chrome.i18n.getMessage("more_stories"); - more.addEventListener("click", moreStories); - feed.appendChild(more); - } -} - -// Show |url| in a new tab. -function showUrl(url) { - // Only allow http and https URLs. - if (url.indexOf("http:") != 0 && url.indexOf("https:") != 0) { - return; - } - chrome.tabs.create({url: url}); -} - -function moreStories(event) { - showUrl(moreStoriesUrl); -} - -function showDesc(event) { - var item = event.currentTarget.parentNode; - var items = document.getElementsByClassName("item"); - for (var i = 0; i < items.length; i++) { - var iframe = items[i].getElementsByClassName("item_desc")[0]; - if (items[i] == item && items[i].className == "item") { - items[i].className = "item opened"; - iframe.contentWindow.postMessage("reportHeight", "*"); - } else { - items[i].className = "item"; - iframe.style.height = "0px"; - } - } -} - -function iframeMessageHandler(e) { - // Only listen to messages from one of our own iframes. - var iframes = document.getElementsByTagName("IFRAME"); - for (var i = 0; i < iframes.length; i++) { - if (iframes[i].contentWindow == e.source) { - var msg = JSON.parse(e.data); - if (msg) { - if (msg.type == "size") { - iframes[i].style.height = msg.size + "px"; - } else if (msg.type == "show") { - var url = msg.url; - if (url.indexOf(chrome.i18n.getMessage('newsUrl')) == 0) { - // If the URL is a redirect URL, strip of the destination and go to - // that directly. This is necessary because the Google news - // redirector blocks use of the redirects in this case. - var index = url.indexOf("&url="); - if (index >= 0) { - url = url.substring(index + 5); - index = url.indexOf("&"); - if (index >= 0) - url = url.substring(0, index); - } - } - showUrl(url); - } - } - return; - } - } -} - -window.addEventListener("message", iframeMessageHandler); -</script> -</head> -<body onload="main();"> -<a id="title_a"><img id='title'></a> -<div id="feed"></div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/manifest.json b/chrome/common/extensions/docs/examples/extensions/news_i18n/manifest.json deleted file mode 100644 index 32b4cc0e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "__MSG_name__", - "version": "1.1", - "description": "__MSG_description__", - "icons": { "128": "news_icon.png" }, - "browser_action": { - "default_title": "__MSG_default_title__", - "default_icon": "news_action.png", - "default_popup": "feed.html" - }, - "permissions": [ - "tabs", - "http://news.google.com/*", - "http://news.google.es/*" - ], - "default_locale": "en" -}
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/news_action.png b/chrome/common/extensions/docs/examples/extensions/news_i18n/news_action.png deleted file mode 100644 index 7d6d9e08..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/news_action.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/news_icon.png b/chrome/common/extensions/docs/examples/extensions/news_i18n/news_icon.png deleted file mode 100644 index aa864d98..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/news_icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/news_i18n/sprite_arrows.gif b/chrome/common/extensions/docs/examples/extensions/news_i18n/sprite_arrows.gif deleted file mode 100644 index 4560faf4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/news_i18n/sprite_arrows.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/no_cookies/background.js b/chrome/common/extensions/docs/examples/extensions/no_cookies/background.js deleted file mode 100644 index a226533b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/no_cookies/background.js +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -// Simple extension to remove 'Cookie' request header and 'Set-Cookie' response -// header. - -function removeHeader(headers, name) { - for (var i = 0; i < headers.length; i++) { - if (headers[i].name.toLowerCase() == name) { - console.log('Removing "' + name + '" header.'); - headers.splice(i, 1); - break; - } - } -} - -chrome.webRequest.onBeforeSendHeaders.addListener( - function(details) { - removeHeader(details.requestHeaders, 'cookie'); - return {requestHeaders: details.requestHeaders}; - }, - // filters - {urls: ['https://*/*', 'http://*/*']}, - // extraInfoSpec - ['blocking', 'requestHeaders', 'extraHeaders']); - -chrome.webRequest.onHeadersReceived.addListener( - function(details) { - removeHeader(details.responseHeaders, 'set-cookie'); - return {responseHeaders: details.responseHeaders}; - }, - // filters - {urls: ['https://*/*', 'http://*/*']}, - // extraInfoSpec - ['blocking', 'responseHeaders', 'extraHeaders']);
diff --git a/chrome/common/extensions/docs/examples/extensions/no_cookies/manifest.json b/chrome/common/extensions/docs/examples/extensions/no_cookies/manifest.json deleted file mode 100644 index 1a0681c..0000000 --- a/chrome/common/extensions/docs/examples/extensions/no_cookies/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "No Cookies", - "description": "Removes 'Cookie' and 'Set-Cookie' headers.", - "version": "1.0", - "manifest_version": 2, - "permissions": [ - "webRequest", - "webRequestBlocking", - "https://*/*", - "http://*/*" - ], - "background": { - "scripts": ["background.js"] - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/NOTICE b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/NOTICE deleted file mode 100644 index 8166d26b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/NOTICE +++ /dev/null
@@ -1,49 +0,0 @@ -This extension uses code from the following two JavaScript libraries: - -http://unitedheroes.net/OAuthSimple/js/OAuthSimple.js -===================================================== -/* OAuthSimple - * A simpler version of OAuth - * - * author: jr conlin - * mail: src@anticipatr.com - * copyright: unitedHeroes.net - * version: 1.0 - * url: http://unitedHeroes.net/OAuthSimple - * - * Copyright (c) 2009, unitedHeroes.net - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the unitedHeroes.net nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - http://pajhome.org.uk/crypt/md5/sha1.js - ======================================= - /* - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined - * in FIPS PUB 180-1 - * Version 2.1a Copyright Paul Johnston 2000 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - */
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/README b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/README deleted file mode 100644 index 9c0393b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/README +++ /dev/null
@@ -1,69 +0,0 @@ -Sample extension to demonstrate integration with an OAuth service. - -Overview --------- -This sample demonstrates the use of OAuth to authorize against -Google's Contacts API inside of an extension. It implements a library which -may be reused generically to authorize requests to any 3-legged OAuth API. - -Library -------- -The library files are: - * chrome_ex_oauth.html - * chrome_ex_oauth.js - * chrome_ex_oauthsimple.js - -To use these files, place them in the root of your extension and include both -.js files in your background page in the following order: - - <script type="text/javascript" src="chrome_ex_oauthsimple.js"></script> - <script type="text/javascript" src="chrome_ex_oauth.js"></script> - -To initialize the API, create a ChromeExOAuth object in the background page: - - var oauth = ChromeExOAuth.initBackgroundPage({ - 'request_url' : <OAuth request URL>, - 'authorize_url' : <OAuth authorize URL>, - 'access_url' : <OAuth access token URL>, - 'consumer_key' : <OAuth consumer key>, - 'consumer_secret' : <OAuth consumer secret>, - 'scope' : <scope parameter for this auth>, - 'app_name' : <application name, not used by all OAuth providers> - }); - -Call the authorize() function to redirect the user to the OAuth provider in -order to obtain an access token. The client library abstracts most of this -process, so all you need to do is pass a callback to the authorize() function -and a new tab will open and redirect the user. If the library already has -stored an access token for the current scope, then no tab will be opened. In -either case, the callback will be called with the resulting token and secret. - - oauth.authorize(onAuthorized); - -There is no need to store the token and secret, as this library already stores -these values in localStorage. Once the callback you specified is called, you -can call the sendSignedRequest function to send OAuth-signed requests to the -API. The sendSignedRequest call takes an url to fetch, a callback function, -and an optional parameter object as its arguments. The callback is passed -the response text as well as the XMLHttpRequest object which was used to -make the request as its arguments. - - function callback(text, xhr) { - //... - }; - - function onAuthorized() { - var url = <API url inside of the requested scope>; - var request = { - 'method' : 'GET', - 'parameters' : { - <Any request parameters as key : value pairs> - } - } - oauth.sendSignedRequest(url, callback, request); - }; - oauth.authorize(onAuthorized); - - - -
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/background.js b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/background.js deleted file mode 100644 index 2eef084..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/background.js +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var oauth = ChromeExOAuth.initBackgroundPage({ - 'request_url' : 'https://www.google.com/accounts/OAuthGetRequestToken', - 'authorize_url' : 'https://www.google.com/accounts/OAuthAuthorizeToken', - 'access_url' : 'https://www.google.com/accounts/OAuthGetAccessToken', - 'consumer_key' : 'anonymous', - 'consumer_secret' : 'anonymous', - 'scope' : 'http://www.google.com/m8/feeds/', - 'app_name' : 'Sample - OAuth Contacts' -}); - -var contacts = null; - -function setIcon() { - if (oauth.hasToken()) { - chrome.browserAction.setIcon({ 'path' : 'img/icon-19-on.png'}); - } else { - chrome.browserAction.setIcon({ 'path' : 'img/icon-19-off.png'}); - } -}; - -function onContacts(text, xhr) { - contacts = []; - var data = JSON.parse(text); - for (var i = 0, entry; entry = data.feed.entry[i]; i++) { - var contact = { - 'name' : entry['title']['$t'], - 'id' : entry['id']['$t'], - 'emails' : [] - }; - - if (entry['gd$email']) { - var emails = entry['gd$email']; - for (var j = 0, email; email = emails[j]; j++) { - contact['emails'].push(email['address']); - } - } - - if (!contact['name']) { - contact['name'] = contact['emails'][0] || "<Unknown>"; - } - contacts.push(contact); - } - - chrome.tabs.create({ 'url' : 'contacts.html'}); -}; - -function getContacts() { - oauth.authorize(function() { - console.log("on authorize"); - setIcon(); - var url = "http://www.google.com/m8/feeds/contacts/default/full"; - oauth.sendSignedRequest(url, onContacts, { - 'parameters' : { - 'alt' : 'json', - 'max-results' : 100 - } - }); - }); -}; - -function logout() { - oauth.clearTokens(); - setIcon(); -}; - -setIcon(); -chrome.browserAction.onClicked.addListener(getContacts);
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.html b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.html deleted file mode 100644 index 4b03a3a4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2009 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. ---> -<html> - <head> - <title>OAuth Redirect Page</title> - <style type="text/css"> - body { - font: 16px Arial; - color: #333; - } - </style> - <script type="text/javascript" src="chrome_ex_oauthsimple.js"></script> - <script type="text/javascript" src="chrome_ex_oauth.js"></script> - <script type="text/javascript" src="onload.js"></script> - </head> - <body> - Redirecting... - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.js b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.js deleted file mode 100644 index 036820e8..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.js +++ /dev/null
@@ -1,591 +0,0 @@ -// Copyright (c) 2010 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. - -/** - * Constructor - no need to invoke directly, call initBackgroundPage instead. - * @constructor - * @param {String} url_request_token The OAuth request token URL. - * @param {String} url_auth_token The OAuth authorize token URL. - * @param {String} url_access_token The OAuth access token URL. - * @param {String} consumer_key The OAuth consumer key. - * @param {String} consumer_secret The OAuth consumer secret. - * @param {String} oauth_scope The OAuth scope parameter. - * @param {Object} opt_args Optional arguments. Recognized parameters: - * "app_name" {String} Name of the current application - * "callback_page" {String} If you renamed chrome_ex_oauth.html, the name - * this file was renamed to. - */ -function ChromeExOAuth(url_request_token, url_auth_token, url_access_token, - consumer_key, consumer_secret, oauth_scope, opt_args) { - this.url_request_token = url_request_token; - this.url_auth_token = url_auth_token; - this.url_access_token = url_access_token; - this.consumer_key = consumer_key; - this.consumer_secret = consumer_secret; - this.oauth_scope = oauth_scope; - this.app_name = opt_args && opt_args['app_name'] || - "ChromeExOAuth Library"; - this.key_token = "oauth_token"; - this.key_token_secret = "oauth_token_secret"; - this.callback_page = opt_args && opt_args['callback_page'] || - "chrome_ex_oauth.html"; - this.auth_params = {}; - if (opt_args && opt_args['auth_params']) { - for (key in opt_args['auth_params']) { - if (opt_args['auth_params'].hasOwnProperty(key)) { - this.auth_params[key] = opt_args['auth_params'][key]; - } - } - } -}; - -/******************************************************************************* - * PUBLIC API METHODS - * Call these from your background page. - ******************************************************************************/ - -/** - * Initializes the OAuth helper from the background page. You must call this - * before attempting to make any OAuth calls. - * @param {Object} oauth_config Configuration parameters in a JavaScript object. - * The following parameters are recognized: - * "request_url" {String} OAuth request token URL. - * "authorize_url" {String} OAuth authorize token URL. - * "access_url" {String} OAuth access token URL. - * "consumer_key" {String} OAuth consumer key. - * "consumer_secret" {String} OAuth consumer secret. - * "scope" {String} OAuth access scope. - * "app_name" {String} Application name. - * "auth_params" {Object} Additional parameters to pass to the - * Authorization token URL. For an example, 'hd', 'hl', 'btmpl': - * http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth - * @return {ChromeExOAuth} An initialized ChromeExOAuth object. - */ -ChromeExOAuth.initBackgroundPage = function(oauth_config) { - window.chromeExOAuthConfig = oauth_config; - window.chromeExOAuth = ChromeExOAuth.fromConfig(oauth_config); - window.chromeExOAuthRedirectStarted = false; - window.chromeExOAuthRequestingAccess = false; - - var url_match = chrome.extension.getURL(window.chromeExOAuth.callback_page); - var tabs = {}; - chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { - if (changeInfo.url && - changeInfo.url.substr(0, url_match.length) === url_match && - changeInfo.url != tabs[tabId] && - window.chromeExOAuthRequestingAccess == false) { - chrome.tabs.create({ 'url' : changeInfo.url }, function(tab) { - tabs[tab.id] = tab.url; - chrome.tabs.remove(tabId); - }); - } - }); - - return window.chromeExOAuth; -}; - -/** - * Authorizes the current user with the configued API. You must call this - * before calling sendSignedRequest. - * @param {Function} callback A function to call once an access token has - * been obtained. This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - */ -ChromeExOAuth.prototype.authorize = function(callback) { - if (this.hasToken()) { - callback(this.getToken(), this.getTokenSecret()); - } else { - window.chromeExOAuthOnAuthorize = function(token, secret) { - callback(token, secret); - }; - chrome.tabs.create({ 'url' :chrome.extension.getURL(this.callback_page) }); - } -}; - -/** - * Clears any OAuth tokens stored for this configuration. Effectively a - * "logout" of the configured OAuth API. - */ -ChromeExOAuth.prototype.clearTokens = function() { - delete localStorage[this.key_token + encodeURI(this.oauth_scope)]; - delete localStorage[this.key_token_secret + encodeURI(this.oauth_scope)]; -}; - -/** - * Returns whether a token is currently stored for this configuration. - * Effectively a check to see whether the current user is "logged in" to - * the configured OAuth API. - * @return {Boolean} True if an access token exists. - */ -ChromeExOAuth.prototype.hasToken = function() { - return !!this.getToken(); -}; - -/** - * Makes an OAuth-signed HTTP request with the currently authorized tokens. - * @param {String} url The URL to send the request to. Querystring parameters - * should be omitted. - * @param {Function} callback A function to be called once the request is - * completed. This callback will be passed the following arguments: - * responseText {String} The text response. - * xhr {XMLHttpRequest} The XMLHttpRequest object which was used to - * send the request. Useful if you need to check response status - * code, etc. - * @param {Object} opt_params Additional parameters to configure the request. - * The following parameters are accepted: - * "method" {String} The HTTP method to use. Defaults to "GET". - * "body" {String} A request body to send. Defaults to null. - * "parameters" {Object} Query parameters to include in the request. - * "headers" {Object} Additional headers to include in the request. - */ -ChromeExOAuth.prototype.sendSignedRequest = function(url, callback, - opt_params) { - var method = opt_params && opt_params['method'] || 'GET'; - var body = opt_params && opt_params['body'] || null; - var params = opt_params && opt_params['parameters'] || {}; - var headers = opt_params && opt_params['headers'] || {}; - - var signedUrl = this.signURL(url, method, params); - - ChromeExOAuth.sendRequest(method, signedUrl, headers, body, function (xhr) { - if (xhr.readyState == 4) { - callback(xhr.responseText, xhr); - } - }); -}; - -/** - * Adds the required OAuth parameters to the given url and returns the - * result. Useful if you need a signed url but don't want to make an XHR - * request. - * @param {String} method The http method to use. - * @param {String} url The base url of the resource you are querying. - * @param {Object} opt_params Query parameters to include in the request. - * @return {String} The base url plus any query params plus any OAuth params. - */ -ChromeExOAuth.prototype.signURL = function(url, method, opt_params) { - var token = this.getToken(); - var secret = this.getTokenSecret(); - if (!token || !secret) { - throw new Error("No oauth token or token secret"); - } - - var params = opt_params || {}; - - var result = OAuthSimple().sign({ - action : method, - path : url, - parameters : params, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret, - oauth_secret : secret, - oauth_token: token - } - }); - - return result.signed_url; -}; - -/** - * Generates the Authorization header based on the oauth parameters. - * @param {String} url The base url of the resource you are querying. - * @param {Object} opt_params Query parameters to include in the request. - * @return {String} An Authorization header containing the oauth_* params. - */ -ChromeExOAuth.prototype.getAuthorizationHeader = function(url, method, - opt_params) { - var token = this.getToken(); - var secret = this.getTokenSecret(); - if (!token || !secret) { - throw new Error("No oauth token or token secret"); - } - - var params = opt_params || {}; - - return OAuthSimple().getHeaderString({ - action: method, - path : url, - parameters : params, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret, - oauth_secret : secret, - oauth_token: token - } - }); -}; - -/******************************************************************************* - * PRIVATE API METHODS - * Used by the library. There should be no need to call these methods directly. - ******************************************************************************/ - -/** - * Creates a new ChromeExOAuth object from the supplied configuration object. - * @param {Object} oauth_config Configuration parameters in a JavaScript object. - * The following parameters are recognized: - * "request_url" {String} OAuth request token URL. - * "authorize_url" {String} OAuth authorize token URL. - * "access_url" {String} OAuth access token URL. - * "consumer_key" {String} OAuth consumer key. - * "consumer_secret" {String} OAuth consumer secret. - * "scope" {String} OAuth access scope. - * "app_name" {String} Application name. - * "auth_params" {Object} Additional parameters to pass to the - * Authorization token URL. For an example, 'hd', 'hl', 'btmpl': - * http://code.google.com/apis/accounts/docs/OAuth_ref.html#GetAuth - * @return {ChromeExOAuth} An initialized ChromeExOAuth object. - */ -ChromeExOAuth.fromConfig = function(oauth_config) { - return new ChromeExOAuth( - oauth_config['request_url'], - oauth_config['authorize_url'], - oauth_config['access_url'], - oauth_config['consumer_key'], - oauth_config['consumer_secret'], - oauth_config['scope'], - { - 'app_name' : oauth_config['app_name'], - 'auth_params' : oauth_config['auth_params'] - } - ); -}; - -/** - * Initializes chrome_ex_oauth.html and redirects the page if needed to start - * the OAuth flow. Once an access token is obtained, this function closes - * chrome_ex_oauth.html. - */ -ChromeExOAuth.initCallbackPage = function() { - var background_page = chrome.extension.getBackgroundPage(); - var oauth_config = background_page.chromeExOAuthConfig; - var oauth = ChromeExOAuth.fromConfig(oauth_config); - background_page.chromeExOAuthRedirectStarted = true; - oauth.initOAuthFlow(function (token, secret) { - background_page.chromeExOAuthOnAuthorize(token, secret); - background_page.chromeExOAuthRedirectStarted = false; - chrome.tabs.query({active: true, currentWindow: true}, function (tabs) { - chrome.tabs.remove(tabs[0].id); - }); - }); -}; - -/** - * Sends an HTTP request. Convenience wrapper for XMLHttpRequest calls. - * @param {String} method The HTTP method to use. - * @param {String} url The URL to send the request to. - * @param {Object} headers Optional request headers in key/value format. - * @param {String} body Optional body content. - * @param {Function} callback Function to call when the XMLHttpRequest's - * ready state changes. See documentation for XMLHttpRequest's - * onreadystatechange handler for more information. - */ -ChromeExOAuth.sendRequest = function(method, url, headers, body, callback) { - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function(data) { - callback(xhr, data); - } - xhr.open(method, url, true); - if (headers) { - for (var header in headers) { - if (headers.hasOwnProperty(header)) { - xhr.setRequestHeader(header, headers[header]); - } - } - } - xhr.send(body); -}; - -/** - * Decodes a URL-encoded string into key/value pairs. - * @param {String} encoded An URL-encoded string. - * @return {Object} An object representing the decoded key/value pairs found - * in the encoded string. - */ -ChromeExOAuth.formDecode = function(encoded) { - var params = encoded.split("&"); - var decoded = {}; - for (var i = 0, param; param = params[i]; i++) { - var keyval = param.split("="); - if (keyval.length == 2) { - var key = ChromeExOAuth.fromRfc3986(keyval[0]); - var val = ChromeExOAuth.fromRfc3986(keyval[1]); - decoded[key] = val; - } - } - return decoded; -}; - -/** - * Returns the current window's querystring decoded into key/value pairs. - * @return {Object} A object representing any key/value pairs found in the - * current window's querystring. - */ -ChromeExOAuth.getQueryStringParams = function() { - var urlparts = window.location.href.split("?"); - if (urlparts.length >= 2) { - var querystring = urlparts.slice(1).join("?"); - return ChromeExOAuth.formDecode(querystring); - } - return {}; -}; - -/** - * Binds a function call to a specific object. This function will also take - * a variable number of additional arguments which will be prepended to the - * arguments passed to the bound function when it is called. - * @param {Function} func The function to bind. - * @param {Object} obj The object to bind to the function's "this". - * @return {Function} A closure that will call the bound function. - */ -ChromeExOAuth.bind = function(func, obj) { - var newargs = Array.prototype.slice.call(arguments).slice(2); - return function() { - var combinedargs = newargs.concat(Array.prototype.slice.call(arguments)); - func.apply(obj, combinedargs); - }; -}; - -/** - * Encodes a value according to the RFC3986 specification. - * @param {String} val The string to encode. - */ -ChromeExOAuth.toRfc3986 = function(val){ - return encodeURIComponent(val) - .replace(/\!/g, "%21") - .replace(/\*/g, "%2A") - .replace(/'/g, "%27") - .replace(/\(/g, "%28") - .replace(/\)/g, "%29"); -}; - -/** - * Decodes a string that has been encoded according to RFC3986. - * @param {String} val The string to decode. - */ -ChromeExOAuth.fromRfc3986 = function(val){ - var tmp = val - .replace(/%21/g, "!") - .replace(/%2A/g, "*") - .replace(/%27/g, "'") - .replace(/%28/g, "(") - .replace(/%29/g, ")"); - return decodeURIComponent(tmp); -}; - -/** - * Adds a key/value parameter to the supplied URL. - * @param {String} url An URL which may or may not contain querystring values. - * @param {String} key A key - * @param {String} value A value - * @return {String} The URL with URL-encoded versions of the key and value - * appended, prefixing them with "&" or "?" as needed. - */ -ChromeExOAuth.addURLParam = function(url, key, value) { - var sep = (url.indexOf('?') >= 0) ? "&" : "?"; - return url + sep + - ChromeExOAuth.toRfc3986(key) + "=" + ChromeExOAuth.toRfc3986(value); -}; - -/** - * Stores an OAuth token for the configured scope. - * @param {String} token The token to store. - */ -ChromeExOAuth.prototype.setToken = function(token) { - localStorage[this.key_token + encodeURI(this.oauth_scope)] = token; -}; - -/** - * Retrieves any stored token for the configured scope. - * @return {String} The stored token. - */ -ChromeExOAuth.prototype.getToken = function() { - return localStorage[this.key_token + encodeURI(this.oauth_scope)]; -}; - -/** - * Stores an OAuth token secret for the configured scope. - * @param {String} secret The secret to store. - */ -ChromeExOAuth.prototype.setTokenSecret = function(secret) { - localStorage[this.key_token_secret + encodeURI(this.oauth_scope)] = secret; -}; - -/** - * Retrieves any stored secret for the configured scope. - * @return {String} The stored secret. - */ -ChromeExOAuth.prototype.getTokenSecret = function() { - return localStorage[this.key_token_secret + encodeURI(this.oauth_scope)]; -}; - -/** - * Starts an OAuth authorization flow for the current page. If a token exists, - * no redirect is needed and the supplied callback is called immediately. - * If this method detects that a redirect has finished, it grabs the - * appropriate OAuth parameters from the URL and attempts to retrieve an - * access token. If no token exists and no redirect has happened, then - * an access token is requested and the page is ultimately redirected. - * @param {Function} callback The function to call once the flow has finished. - * This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - */ -ChromeExOAuth.prototype.initOAuthFlow = function(callback) { - if (!this.hasToken()) { - var params = ChromeExOAuth.getQueryStringParams(); - if (params['chromeexoauthcallback'] == 'true') { - var oauth_token = params['oauth_token']; - var oauth_verifier = params['oauth_verifier'] - this.getAccessToken(oauth_token, oauth_verifier, callback); - } else { - var request_params = { - 'url_callback_param' : 'chromeexoauthcallback' - } - this.getRequestToken(function(url) { - window.location.href = url; - }, request_params); - } - } else { - callback(this.getToken(), this.getTokenSecret()); - } -}; - -/** - * Requests an OAuth request token. - * @param {Function} callback Function to call once the authorize URL is - * calculated. This callback will be passed the following arguments: - * url {String} The URL the user must be redirected to in order to - * approve the token. - * @param {Object} opt_args Optional arguments. The following parameters - * are accepted: - * "url_callback" {String} The URL the OAuth provider will redirect to. - * "url_callback_param" {String} A parameter to include in the callback - * URL in order to indicate to this library that a redirect has - * taken place. - */ -ChromeExOAuth.prototype.getRequestToken = function(callback, opt_args) { - if (typeof callback !== "function") { - throw new Error("Specified callback must be a function."); - } - var url = opt_args && opt_args['url_callback'] || - window && window.top && window.top.location && - window.top.location.href; - - var url_param = opt_args && opt_args['url_callback_param'] || - "chromeexoauthcallback"; - var url_callback = ChromeExOAuth.addURLParam(url, url_param, "true"); - - var result = OAuthSimple().sign({ - path : this.url_request_token, - parameters: { - "xoauth_displayname" : this.app_name, - "scope" : this.oauth_scope, - "oauth_callback" : url_callback - }, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret - } - }); - var onToken = ChromeExOAuth.bind(this.onRequestToken, this, callback); - ChromeExOAuth.sendRequest("GET", result.signed_url, null, null, onToken); -}; - -/** - * Called when a request token has been returned. Stores the request token - * secret for later use and sends the authorization url to the supplied - * callback (for redirecting the user). - * @param {Function} callback Function to call once the authorize URL is - * calculated. This callback will be passed the following arguments: - * url {String} The URL the user must be redirected to in order to - * approve the token. - * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the - * request token. - */ -ChromeExOAuth.prototype.onRequestToken = function(callback, xhr) { - if (xhr.readyState == 4) { - if (xhr.status == 200) { - var params = ChromeExOAuth.formDecode(xhr.responseText); - var token = params['oauth_token']; - this.setTokenSecret(params['oauth_token_secret']); - var url = ChromeExOAuth.addURLParam(this.url_auth_token, - "oauth_token", token); - for (var key in this.auth_params) { - if (this.auth_params.hasOwnProperty(key)) { - url = ChromeExOAuth.addURLParam(url, key, this.auth_params[key]); - } - } - callback(url); - } else { - throw new Error("Fetching request token failed. Status " + xhr.status); - } - } -}; - -/** - * Requests an OAuth access token. - * @param {String} oauth_token The OAuth request token. - * @param {String} oauth_verifier The OAuth token verifier. - * @param {Function} callback The function to call once the token is obtained. - * This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - */ -ChromeExOAuth.prototype.getAccessToken = function(oauth_token, oauth_verifier, - callback) { - if (typeof callback !== "function") { - throw new Error("Specified callback must be a function."); - } - var bg = chrome.extension.getBackgroundPage(); - if (bg.chromeExOAuthRequestingAccess == false) { - bg.chromeExOAuthRequestingAccess = true; - - var result = OAuthSimple().sign({ - path : this.url_access_token, - parameters: { - "oauth_token" : oauth_token, - "oauth_verifier" : oauth_verifier - }, - signatures: { - consumer_key : this.consumer_key, - shared_secret : this.consumer_secret, - oauth_secret : this.getTokenSecret(this.oauth_scope) - } - }); - - var onToken = ChromeExOAuth.bind(this.onAccessToken, this, callback); - ChromeExOAuth.sendRequest("GET", result.signed_url, null, null, onToken); - } -}; - -/** - * Called when an access token has been returned. Stores the access token and - * access token secret for later use and sends them to the supplied callback. - * @param {Function} callback The function to call once the token is obtained. - * This callback will be passed the following arguments: - * token {String} The OAuth access token. - * secret {String} The OAuth access token secret. - * @param {XMLHttpRequest} xhr The XMLHttpRequest object used to fetch the - * access token. - */ -ChromeExOAuth.prototype.onAccessToken = function(callback, xhr) { - if (xhr.readyState == 4) { - var bg = chrome.extension.getBackgroundPage(); - if (xhr.status == 200) { - var params = ChromeExOAuth.formDecode(xhr.responseText); - var token = params["oauth_token"]; - var secret = params["oauth_token_secret"]; - this.setToken(token); - this.setTokenSecret(secret); - bg.chromeExOAuthRequestingAccess = false; - callback(token, secret); - } else { - bg.chromeExOAuthRequestingAccess = false; - throw new Error("Fetching access token failed with status " + xhr.status); - } - } -}; \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauthsimple.js b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauthsimple.js deleted file mode 100644 index af0fe8a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauthsimple.js +++ /dev/null
@@ -1,458 +0,0 @@ -/* OAuthSimple - * A simpler version of OAuth - * - * author: jr conlin - * mail: src@anticipatr.com - * copyright: unitedHeroes.net - * version: 1.0 - * url: http://unitedHeroes.net/OAuthSimple - * - * Copyright (c) 2009, unitedHeroes.net - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the unitedHeroes.net nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY UNITEDHEROES.NET ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL UNITEDHEROES.NET BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -var OAuthSimple; - -if (OAuthSimple === undefined) -{ - /* Simple OAuth - * - * This class only builds the OAuth elements, it does not do the actual - * transmission or reception of the tokens. It does not validate elements - * of the token. It is for client use only. - * - * api_key is the API key, also known as the OAuth consumer key - * shared_secret is the shared secret (duh). - * - * Both the api_key and shared_secret are generally provided by the site - * offering OAuth services. You need to specify them at object creation - * because nobody <explative>ing uses OAuth without that minimal set of - * signatures. - * - * If you want to use the higher order security that comes from the - * OAuth token (sorry, I don't provide the functions to fetch that because - * sites aren't horribly consistent about how they offer that), you need to - * pass those in either with .setTokensAndSecrets() or as an argument to the - * .sign() or .getHeaderString() functions. - * - * Example: - <code> - var oauthObject = OAuthSimple().sign({path:'http://example.com/rest/', - parameters: 'foo=bar&gorp=banana', - signatures:{ - api_key:'12345abcd', - shared_secret:'xyz-5309' - }}); - document.getElementById('someLink').href=oauthObject.signed_url; - </code> - * - * that will sign as a "GET" using "SHA1-MAC" the url. If you need more than - * that, read on, McDuff. - */ - - /** OAuthSimple creator - * - * Create an instance of OAuthSimple - * - * @param api_key {string} The API Key (sometimes referred to as the consumer key) This value is usually supplied by the site you wish to use. - * @param shared_secret (string) The shared secret. This value is also usually provided by the site you wish to use. - */ - OAuthSimple = function (consumer_key,shared_secret) - { -/* if (api_key == undefined) - throw("Missing argument: api_key (oauth_consumer_key) for OAuthSimple. This is usually provided by the hosting site."); - if (shared_secret == undefined) - throw("Missing argument: shared_secret (shared secret) for OAuthSimple. This is usually provided by the hosting site."); -*/ this._secrets={}; - this._parameters={}; - - // General configuration options. - if (consumer_key !== undefined) { - this._secrets['consumer_key'] = consumer_key; - } - if (shared_secret !== undefined) { - this._secrets['shared_secret'] = shared_secret; - } - this._default_signature_method= "HMAC-SHA1"; - this._action = "GET"; - this._nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - - this.reset = function() { - this._parameters={}; - this._path=undefined; - return this; - }; - - /** set the parameters either from a hash or a string - * - * @param {string,object} List of parameters for the call, this can either be a URI string (e.g. "foo=bar&gorp=banana" or an object/hash) - */ - this.setParameters = function (parameters) { - if (parameters === undefined) { - parameters = {}; - } - if (typeof(parameters) == 'string') { - parameters=this._parseParameterString(parameters); - } - this._parameters = parameters; - if (this._parameters['oauth_nonce'] === undefined) { - this._getNonce(); - } - if (this._parameters['oauth_timestamp'] === undefined) { - this._getTimestamp(); - } - if (this._parameters['oauth_method'] === undefined) { - this.setSignatureMethod(); - } - if (this._parameters['oauth_consumer_key'] === undefined) { - this._getApiKey(); - } - if(this._parameters['oauth_token'] === undefined) { - this._getAccessToken(); - } - - return this; - }; - - /** convienence method for setParameters - * - * @param parameters {string,object} See .setParameters - */ - this.setQueryString = function (parameters) { - return this.setParameters(parameters); - }; - - /** Set the target URL (does not include the parameters) - * - * @param path {string} the fully qualified URI (excluding query arguments) (e.g "http://example.org/foo") - */ - this.setURL = function (path) { - if (path == '') { - throw ('No path specified for OAuthSimple.setURL'); - } - this._path = path; - return this; - }; - - /** convienence method for setURL - * - * @param path {string} see .setURL - */ - this.setPath = function(path){ - return this.setURL(path); - }; - - /** set the "action" for the url, (e.g. GET,POST, DELETE, etc.) - * - * @param action {string} HTTP Action word. - */ - this.setAction = function(action) { - if (action === undefined) { - action="GET"; - } - action = action.toUpperCase(); - if (action.match('[^A-Z]')) { - throw ('Invalid action specified for OAuthSimple.setAction'); - } - this._action = action; - return this; - }; - - /** set the signatures (as well as validate the ones you have) - * - * @param signatures {object} object/hash of the token/signature pairs {api_key:, shared_secret:, oauth_token: oauth_secret:} - */ - this.setTokensAndSecrets = function(signatures) { - if (signatures) - { - for (var i in signatures) { - this._secrets[i] = signatures[i]; - } - } - // Aliases - if (this._secrets['api_key']) { - this._secrets.consumer_key = this._secrets.api_key; - } - if (this._secrets['access_token']) { - this._secrets.oauth_token = this._secrets.access_token; - } - if (this._secrets['access_secret']) { - this._secrets.oauth_secret = this._secrets.access_secret; - } - // Gauntlet - if (this._secrets.consumer_key === undefined) { - throw('Missing required consumer_key in OAuthSimple.setTokensAndSecrets'); - } - if (this._secrets.shared_secret === undefined) { - throw('Missing required shared_secret in OAuthSimple.setTokensAndSecrets'); - } - if ((this._secrets.oauth_token !== undefined) && (this._secrets.oauth_secret === undefined)) { - throw('Missing oauth_secret for supplied oauth_token in OAuthSimple.setTokensAndSecrets'); - } - return this; - }; - - /** set the signature method (currently only Plaintext or SHA-MAC1) - * - * @param method {string} Method of signing the transaction (only PLAINTEXT and SHA-MAC1 allowed for now) - */ - this.setSignatureMethod = function(method) { - if (method === undefined) { - method = this._default_signature_method; - } - //TODO: accept things other than PlainText or SHA-MAC1 - if (method.toUpperCase().match(/(PLAINTEXT|HMAC-SHA1)/) === undefined) { - throw ('Unknown signing method specified for OAuthSimple.setSignatureMethod'); - } - this._parameters['oauth_signature_method']= method.toUpperCase(); - return this; - }; - - /** sign the request - * - * note: all arguments are optional, provided you've set them using the - * other helper functions. - * - * @param args {object} hash of arguments for the call - * {action:, path:, parameters:, method:, signatures:} - * all arguments are optional. - */ - this.sign = function (args) { - if (args === undefined) { - args = {}; - } - // Set any given parameters - if(args['action'] !== undefined) { - this.setAction(args['action']); - } - if (args['path'] !== undefined) { - this.setPath(args['path']); - } - if (args['method'] !== undefined) { - this.setSignatureMethod(args['method']); - } - this.setTokensAndSecrets(args['signatures']); - if (args['parameters'] !== undefined){ - this.setParameters(args['parameters']); - } - // check the parameters - var normParams = this._normalizedParameters(); - this._parameters['oauth_signature']=this._generateSignature(normParams); - return { - parameters: this._parameters, - signature: this._oauthEscape(this._parameters['oauth_signature']), - signed_url: this._path + '?' + this._normalizedParameters(), - header: this.getHeaderString() - }; - }; - - /** Return a formatted "header" string - * - * NOTE: This doesn't set the "Authorization: " prefix, which is required. - * I don't set it because various set header functions prefer different - * ways to do that. - * - * @param args {object} see .sign - */ - this.getHeaderString = function(args) { - if (this._parameters['oauth_signature'] === undefined) { - this.sign(args); - } - - var result = 'OAuth '; - for (var pName in this._parameters) - { - if (!pName.match(/^oauth/)) { - continue; - } - if ((this._parameters[pName]) instanceof Array) - { - var pLength = this._parameters[pName].length; - for (var j=0;j<pLength;j++) - { - result += pName +'="'+this._oauthEscape(this._parameters[pName][j])+'" '; - } - } - else - { - result += pName + '="'+this._oauthEscape(this._parameters[pName])+'" '; - } - } - return result; - }; - - // Start Private Methods. - - /** convert the parameter string into a hash of objects. - * - */ - this._parseParameterString = function(paramString){ - var elements = paramString.split('&'); - var result={}; - for(var element=elements.shift();element;element=elements.shift()) - { - var keyToken=element.split('='); - var value=''; - if (keyToken[1]) { - value=decodeURIComponent(keyToken[1]); - } - if(result[keyToken[0]]){ - if (!(result[keyToken[0]] instanceof Array)) - { - result[keyToken[0]] = Array(result[keyToken[0]],value); - } - else - { - result[keyToken[0]].push(value); - } - } - else - { - result[keyToken[0]]=value; - } - } - return result; - }; - - this._oauthEscape = function(string) { - if (string === undefined) { - return ""; - } - if (string instanceof Array) - { - throw('Array passed to _oauthEscape'); - } - return encodeURIComponent(string).replace(/\!/g, "%21"). - replace(/\*/g, "%2A"). - replace(/'/g, "%27"). - replace(/\(/g, "%28"). - replace(/\)/g, "%29"); - }; - - this._getNonce = function (length) { - if (length === undefined) { - length=5; - } - var result = ""; - var cLength = this._nonce_chars.length; - for (var i = 0; i < length;i++) { - var rnum = Math.floor(Math.random() *cLength); - result += this._nonce_chars.substring(rnum,rnum+1); - } - this._parameters['oauth_nonce']=result; - return result; - }; - - this._getApiKey = function() { - if (this._secrets.consumer_key === undefined) { - throw('No consumer_key set for OAuthSimple.'); - } - this._parameters['oauth_consumer_key']=this._secrets.consumer_key; - return this._parameters.oauth_consumer_key; - }; - - this._getAccessToken = function() { - if (this._secrets['oauth_secret'] === undefined) { - return ''; - } - if (this._secrets['oauth_token'] === undefined) { - throw('No oauth_token (access_token) set for OAuthSimple.'); - } - this._parameters['oauth_token'] = this._secrets.oauth_token; - return this._parameters.oauth_token; - }; - - this._getTimestamp = function() { - var d = new Date(); - var ts = Math.floor(d.getTime()/1000); - this._parameters['oauth_timestamp'] = ts; - return ts; - }; - - this.b64_hmac_sha1 = function(k,d,_p,_z){ - // heavily optimized and compressed version of http://pajhome.org.uk/crypt/md5/sha1.js - // _p = b64pad, _z = character size; not used here but I left them available just in case - if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d); - } - - - this._normalizedParameters = function() { - var elements = new Array(); - var paramNames = []; - var ra =0; - for (var paramName in this._parameters) - { - if (ra++ > 1000) { - throw('runaway 1'); - } - paramNames.unshift(paramName); - } - paramNames = paramNames.sort(); - pLen = paramNames.length; - for (var i=0;i<pLen; i++) - { - paramName=paramNames[i]; - //skip secrets. - if (paramName.match(/\w+_secret/)) { - continue; - } - if (this._parameters[paramName] instanceof Array) - { - var sorted = this._parameters[paramName].sort(); - var spLen = sorted.length; - for (var j = 0;j<spLen;j++){ - if (ra++ > 1000) { - throw('runaway 1'); - } - elements.push(this._oauthEscape(paramName) + '=' + - this._oauthEscape(sorted[j])); - } - continue; - } - elements.push(this._oauthEscape(paramName) + '=' + - this._oauthEscape(this._parameters[paramName])); - } - return elements.join('&'); - }; - - this._generateSignature = function() { - - var secretKey = this._oauthEscape(this._secrets.shared_secret)+'&'+ - this._oauthEscape(this._secrets.oauth_secret); - if (this._parameters['oauth_signature_method'] == 'PLAINTEXT') - { - return secretKey; - } - if (this._parameters['oauth_signature_method'] == 'HMAC-SHA1') - { - var sigString = this._oauthEscape(this._action)+'&'+this._oauthEscape(this._path)+'&'+this._oauthEscape(this._normalizedParameters()); - return this.b64_hmac_sha1(secretKey,sigString); - } - return null; - }; - - return this; - }; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/contacts.html b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/contacts.html deleted file mode 100644 index 10f29e8..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/contacts.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2009 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. ---> -<html> - <head> - <title>Your Google Contacts List</title> - <style type="text/css"> - body { - font: 14px Arial; - } - p { - font-weight: bold; - } - </style> - </head> - <body> - <h1>Your Google Contacts List</h1> - <h2>Listing the first 100 results of a standard query to - <a href="http://code.google.com/apis/contacts/">Google's - Contacts API</a></h2> - <button id="clear">Click here to clear your OAuth token</button> - <div id="output"> - </div> - <script src="contacts.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/contacts.js b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/contacts.js deleted file mode 100644 index 225cd9b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/contacts.js +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var contacts = chrome.extension.getBackgroundPage().contacts; -var output = document.getElementById('output'); -for (var i = 0, contact; contact = contacts[i]; i++) { - var div = document.createElement('div'); - var pName = document.createElement('p'); - var ulEmails = document.createElement('ul'); - - pName.innerText = contact['name']; - div.appendChild(pName); - - for (var j = 0, email; email = contact['emails'][j]; j++) { - var liEmail = document.createElement('li'); - liEmail.innerText = email; - ulEmails.appendChild(liEmail); - } - - div.appendChild(ulEmails); - output.appendChild(div); -} - -function logout() { - chrome.extension.getBackgroundPage().logout(); - window.close(); -} - -document.addEventListener('DOMContentLoaded', function () { - document.querySelector('#clear').addEventListener('click', logout); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-128.png b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-128.png deleted file mode 100644 index 8d0bc2f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-19-off.png b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-19-off.png deleted file mode 100644 index 06aae8a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-19-off.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-19-on.png b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-19-on.png deleted file mode 100644 index c1ba8a39..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-19-on.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-48.png b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-48.png deleted file mode 100644 index bf2f4d4..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/img/icon-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/manifest.json b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/manifest.json deleted file mode 100644 index 5771b423..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/manifest.json +++ /dev/null
@@ -1,26 +0,0 @@ -{ - "name": "Sample - OAuth Contacts", - "version": "1.0.6", - "icons": { "48": "img/icon-48.png", - "128": "img/icon-128.png" }, - "description": "Uses OAuth to connect to Google's contacts service and display a list of your contacts.", - "background": { - "scripts": [ - "chrome_ex_oauthsimple.js", - "chrome_ex_oauth.js", - "background.js" - ] - }, - "browser_action": { - "default_title": "", - "default_icon": "img/icon-19-off.png" - }, - "permissions": [ - "tabs", - "http://www.google.com/m8/feeds/*", - "https://www.google.com/accounts/OAuthGetRequestToken", - "https://www.google.com/accounts/OAuthAuthorizeToken", - "https://www.google.com/accounts/OAuthGetAccessToken" - ], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/onload.js b/chrome/common/extensions/docs/examples/extensions/oauth_contacts/onload.js deleted file mode 100644 index 83ba522..0000000 --- a/chrome/common/extensions/docs/examples/extensions/oauth_contacts/onload.js +++ /dev/null
@@ -1,7 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -window.onload = function() { - ChromeExOAuth.initCallbackPage(); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions128.png b/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions128.png deleted file mode 100644 index 8cf09db..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions16.png b/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions16.png deleted file mode 100644 index 5b9f847..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions32.png b/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions32.png deleted file mode 100644 index 99801964..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions48.png b/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions48.png deleted file mode 100644 index fa61a0e1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/images/optional_permissions48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/logic.js b/chrome/common/extensions/docs/examples/extensions/optional_permissions/logic.js deleted file mode 100644 index 9c2b994..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/logic.js +++ /dev/null
@@ -1,77 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -const kPermissionObj = { - permissions: ['topSites'] -}; - -const sites_div = document.getElementById('display_top'); - -const todo = document.getElementById('display_todo'); - -const form = document.querySelector('form'); - -const footer = document.querySelector('footer'); - -function createTop(){chrome.topSites.get(function(topSites) { - topSites.forEach(function(site) { - let div = document.createElement('div'); - div.className = 'colorFun'; - let tooltip = document.createElement('span'); - tooltip.innerText = site.title; - tooltip.className = 'tooltip'; - let url = document.createElement('a'); - url.href = site.url; - let hostname = (new URL(site.url)).hostname; - let image = document.createElement('img'); - image.title = site.title; - image.src = 'https://logo.clearbit.com/' + hostname; - url.appendChild(image); - div.appendChild(url); - div.appendChild(tooltip); - sites_div.appendChild(div); - }) -})}; - -chrome.permissions.contains({permissions: ['topSites']}, function(result) { - if (result) { - // The extension has the permissions. - createTop(); - } else { - // The extension doesn't have the permissions. - let button = document.createElement('button'); - button.innerText = 'Allow Extension to Access Top Sites'; - button.addEventListener('click', function() { - chrome.permissions.request(kPermissionObj, function(granted) { - if (granted) { - console.log('granted'); - sites_div.innerText = ''; - createTop(); - } else { - console.log('not granted'); - } - }); - }); - footer.appendChild(button); - } -}); - -form.addEventListener('submit', function() { - let todo_value = document.getElementById('todo_value'); - chrome.storage.sync.set({todo: todo_value.value}); -}); - -function setToDo() { - chrome.storage.sync.get(['todo'], function(value) { - if (!value.todo) { - todo.innerText = ''; - } else { - todo.innerText = value.todo; - } - }); -}; - -setToDo();
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/manifest.json b/chrome/common/extensions/docs/examples/extensions/optional_permissions/manifest.json deleted file mode 100644 index ac62ef2d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "name": "Optional Permissions New Tab", - "version": "1.2.5.0", - "description": "Demonstrates optional permissions in extensions", - "permissions": ["storage"], - "optional_permissions": [ - "topSites" - ], - "icons": { - "16": "images/optional_permissions16.png", - "32": "images/optional_permissions32.png", - "48": "images/optional_permissions48.png", - "128": "images/optional_permissions128.png" - }, - "chrome_url_overrides": { - "newtab": "newtab.html" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/newtab.html b/chrome/common/extensions/docs/examples/extensions/optional_permissions/newtab.html deleted file mode 100644 index 483d1c9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/newtab.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="UTF-8"> - <title>New Tab - Optional Permissions</title> - <link rel="stylesheet" type="text/css" href="style.css"> - </head> - <body> - <div id="todo_div" class="center colorFun"> - <h1 id="display_todo"></h1> - </div> - <div id="display_top"></div> - <form class="center"> - <input id="todo_value" placeholder="My focus today is..." /> - <input type="submit" value="Submit"> - </form> - <footer></footer> - <script src="logic.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/optional_permissions/style.css b/chrome/common/extensions/docs/examples/extensions/optional_permissions/style.css deleted file mode 100644 index 2c94874..0000000 --- a/chrome/common/extensions/docs/examples/extensions/optional_permissions/style.css +++ /dev/null
@@ -1,80 +0,0 @@ -/* Copyright 2018 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.*/ - -h1 { - font-family: "Courier New", Courier, monospaces; -} - -#display_top { - margin: auto; - width: 600px; -} - -#todo_div { - margin-top: 0px; - height: 100px; - width: 100%; - display: flex; - align-items: center; - justify-content: center; -} - -.center { - display: flex; - align-items: center; - justify-content: center; -} - -@keyframes color-extravaganza { - 0% {background-color: #4285F4;} - 10% {background-color: #4285F4;} - 25% {background-color: #EA4335;} - 50% {background-color: #FBBC04;} - 100% {background-color: #34A853;} -} - -.colorFun { - position: relative; - height: 100px; - width: 100px; - padding: 10px; - display: inline-block; - margin-top: 60px; -} - -.colorFun .tooltip { - visibility: hidden; - width: 120px; - color: #fff; - text-align: center; - padding: 5px 0; - border-radius: 6px; - position: absolute; - z-index: 1; - bottom: 0%; - left: 50%; - margin-left: -60px; - opacity: 0; - transition: opacity 0.3s; -} - - -#todo_div, .colorFun:hover .tooltip { - visibility: visible; - opacity: 1; - animation-name: color-extravaganza; - animation-duration: 6s; - animation-iteration-count: infinite; - animation-direction: alternate; -} - -img { - width: 100px; -} - -footer { - position: absolute; - bottom: 20px; - left: 20px; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/plugin_settings/_locales/en/messages.json deleted file mode 100644 index f2bd7f5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/_locales/en/messages.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "extName": { - "message": "Per-plugin content settings" - }, - "extDescription": { - "message": "Customize your content setting for different plugins." - }, - "patternColumnHeader": { - "message": "Hostname Pattern" - }, - "settingColumnHeader": { - "message": "Behavior" - }, - "allowRule": { - "message": "Allow" - }, - "blockRule": { - "message": "Block" - }, - "addNewPattern": { - "message": "Add a new hostname pattern" - } -} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/bunny128.png b/chrome/common/extensions/docs/examples/extensions/plugin_settings/bunny128.png deleted file mode 100644 index 06e4668..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/bunny128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/bunny48.png b/chrome/common/extensions/docs/examples/extensions/plugin_settings/bunny48.png deleted file mode 100644 index 09ce0e4c9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/bunny48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/css/plugin_list.css b/chrome/common/extensions/docs/examples/extensions/plugin_settings/css/plugin_list.css deleted file mode 100644 index acb72a76..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/css/plugin_list.css +++ /dev/null
@@ -1,83 +0,0 @@ -/* Copyright (c) 2011 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. */ - -body { - font-family: Helvetica, sans-serif; - background-color: white; - color: black; - margin: 10px; -} - -.plugin-list { - border: 1px solid #d9d9d9; - border-radius: 2px; - width: 517px; -} - -.plugin-list > li { - padding: 3px; -} - -.plugin-name { - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - font-weight: bold; -} - -.num-rules:before { - content: ' '; -} - -.plugin-show-details .num-rules { - display: none; -} - -.plugin-description { - display: inline-block; - padding-inline-start: 7px; - width: auto; - overflow: hidden; - text-overflow: ellipsis; - font-size: 95%; -} - -.plugin-details { - background: #f5f8f8; - border: 1px solid #b2b2b2; - border-radius: 5px; - padding: 5px; - height: 0; - width: 500px; - opacity: 0; - transition: height .5s ease-in-out; -} - -.plugin-measure-details .plugin-details { - height: auto; - transition: none; - visibility: hidden; -} - -li.plugin-show-details { - height: auto; -} - -.plugin-show-details .plugin-description { - height: auto; -} - -.plugin-show-details .plugin-details { - opacity: 1; - height: auto; -} - -.column-headers { - display: -webkit-box; - margin-inline-start: 17px; -} - -.column-headers > div { - font-weight: bold; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/css/rule_list.css b/chrome/common/extensions/docs/examples/extensions/plugin_settings/css/rule_list.css deleted file mode 100644 index 2d6c9c1e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/css/rule_list.css +++ /dev/null
@@ -1,31 +0,0 @@ -/* Copyright (c) 2011 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. */ - -.rule-pattern { - -webkit-box-flex: 1; - margin-inline-end: 10px; - margin-inline-start: 14px; -} - -.rule-behavior { - display: inline-block; - width: 120px; -} - -select.rule-behavior { - vertical-align: middle; -} - -.rule-list { - border: 1px solid #d9d9d9; - border-radius: 2px; -} - -.pattern-column-header { - -webkit-box-flex: 1; -} - -.setting-column-header { - width: 145px; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/button.css b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/button.css deleted file mode 100644 index 5564f426..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/button.css +++ /dev/null
@@ -1,43 +0,0 @@ -button, -input[type='button'], -input[type='submit'] { - -webkit-border-radius: 2px; - -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); - -webkit-user-select: none; - background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5); - border: 1px solid #aaa; - color: #444; - font-size: inherit; - margin-bottom: 0px; - min-width: 4em; - padding: 3px 12px 3px 12px; -} - -button:hover, -input[type='button']:hover, -input[type='submit']:hover { - -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.2); - background: #ebebeb -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9); - border-color: #999; - color: #222; -} - -button:active, -input[type='button']:active, -input[type='submit']:active { - -webkit-box-shadow: inset 0px 1px 3px rgba(0, 0, 0, 0.2); - background: #ebebeb -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc); - color: #333; -} - -button[disabled], -input[type='button'][disabled], -input[type='submit'][disabled], -button[disabled]:hover, -input[type='button'][disabled]:hover, -input[type='submit'][disabled]:hover { - -webkit-box-shadow: none; - background: -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5); - border-color: #aaa; - color: #888; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/chrome_shared.css b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/chrome_shared.css deleted file mode 100644 index dac22eb..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/chrome_shared.css +++ /dev/null
@@ -1,261 +0,0 @@ -/* Copyright (c) 2011 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. */ - -/* Styles common to WebUI pages that share the options pages style */ -body { - cursor: default; - font-size: 13px; -} - -a:link { - color: rgb(63, 110, 194); -} - -a:active { - color: rgb(37, 64, 113); -} - -#navbar-content-title { - -webkit-user-select: none; - color: #53637d; - cursor: pointer; - font-size: 200%; - font-weight: normal; - margin: 0; - padding-bottom: 14px; - padding-inline-end: 24px; - padding-top: 13px; - text-align: end; - text-shadow: white 0 1px 2px; -} - -#main-content { - display: -webkit-box; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; -} - -#navbar { - margin: 0; -} - -#navbar-container { - background: -webkit-linear-gradient(rgba(234, 238, 243, 0.2), #eaeef3), - -webkit-linear-gradient(left, #eaeef3, #eaeef3 97%, #d3d7db); - border-inline-end: 1px solid #c6c9ce; - position: fixed; - bottom: 0; - /* We set both left and right for the sake of RTL. */ - left: 0; - right: 0; - top: 0; - width: 216px; - z-index: 2; -} - -html[dir='rtl'] #navbar-container { - background: -webkit-linear-gradient(rgba(234, 238, 243, 0), #EAEEF3), - -webkit-linear-gradient(right, #EAEEF3, #EAEEF3 97%, #D3D7DB); -} - -html.hide-menu #navbar-container { - display: none; -} - -#navbar-container > ul { - -webkit-user-select: none; - list-style-type: none; - margin: 0; - padding: 0; -} - -.navbar-item { - border-bottom: 1px solid transparent; - border-top: 1px solid transparent; - color: #426dc9; - cursor: pointer; - display: block; - font-size: 105%; - outline: none; - padding: 7px 0; - padding-inline-end: 24px; - text-align: end; - text-shadow: white 0 1px 1px; -} - -.navbar-item:focus { - border-bottom: 1px solid #8faad9; - border-top: 1px solid #8faad9; -} - -.navbar-item-selected { - -webkit-box-shadow: 0px 1px 0px #f7f7f7; - background: -webkit-linear-gradient(left, #bbcee9, #bbcee9 97%, #aabedc); - border-bottom: 1px solid #8faad9; - border-top: 1px solid #8faad9; - color: black; - text-shadow: #bbcee9 0 1px 1px; -} - -#mainview { - -webkit-box-align: stretch; - margin: 0; - position: absolute; - left: 0; - padding-inline-start: 216px; - right: 0; - top: 0; - bottom: 0; - z-index: 1; -} - -html.hide-menu #mainview { - padding-inline-start: 0; -} - -#mainview-content { - min-height: 100%; - position: relative; -} - -#page-container { - box-sizing: border-box; - max-width: 888px; - min-width: 600px; - padding: 0 24px; -} - -div.checkbox, -div.radio { - margin: 5px 0; - color: #444; -} - -div.disabled { - color: #888; -} - -/* TEXT */ -input[type='password'], -input[type='text'], -input[type='url'], -input:not([type]) { - -webkit-border-radius: 2px; - border: 1px solid #aaa; - font-size: inherit; - padding: 3px; -} - -/* CHECKBOX, RADIO */ -input[type=checkbox], -input[type=radio] { - margin-left: 0; - margin-right: 0; - position: relative; - top: 1px; -} - -/* Checkbox and radio buttons have different sizes on different platforms. The - * following rules have platform specific tweaks. - * TODO(arv): Test the vertical position on Linux and CrOS as well. - */ - -label > input[type=checkbox], -label > input[type=radio] { - opacity: 0.7; - margin-top: 1px; -} - -html[os=mac] label > input[type=checkbox], -html[os=mac] label > input[type=radio] { - margin-top: 2px; -} - -html[os=chromeos] label > input[type=checkbox], -html[os=chromeos] label > input[type=radio] { - top: 2px; -} - -/* Checkbox and radio hover visuals. - * Their appearance when checked is set to be the same. - */ -label:hover > input[type=checkbox]:not([disabled]), -label:hover > input[type=radio]:not([disabled]), -label > input:not([disabled]):checked { - opacity: 1; -} - -label:hover > input[type=checkbox]:not([disabled]) ~ span, -label:hover > input[type=radio]:not([disabled]) ~ span, -label > input:not([disabled]):checked ~ span { - color: #222; -} - -/* This will 'disable' the label associated with any input whose next sibling is - * the span containing the label (usually a checkbox or radio). - */ -label > input[disabled] ~ span { - color: #888; -} - -/* Elements that need to be LTR even in an RTL context, but should align - * right. (Namely, URLs, search engine names, etc.) - */ -html[dir='rtl'] .weakrtl { - direction: ltr; - text-align: right; -} - -/* Input fields in search engine table need to be weak-rtl. Since those input - * fields are generated for all cr.ListItem elements (and we only want weakrtl - * on some), the class needs to be on the enclosing div. - */ -html[dir='rtl'] div.weakrtl input { - direction: ltr; - text-align: right; -} - -html[dir='rtl'] .favicon-cell.weakrtl { - padding-inline-end: 22px; - padding-inline-start: 0; -} - -/* weakrtl for selection drop downs needs to account for the fact that - * Webkit does not honor the text-align attribute for the select element. - * (See Webkit bug #40216) - */ -html[dir='rtl'] select.weakrtl { - direction: rtl; -} - -html[dir='rtl'] select.weakrtl option { - direction: ltr; -} - -/* WebKit does not honor alignment for text specified via placeholder attrib. - * This CSS is a workaround. Please remove once WebKit bug is fixed. - * https://bugs.webkit.org/show_bug.cgi?id=63367 - */ -html[dir='rtl'] input.weakrtl::-webkit-input-placeholder, -html[dir='rtl'] .weakrtl input::-webkit-input-placeholder { - direction: rtl; -} - -.page h1 { - -webkit-user-select: none; - border-bottom: 1px solid #eeeeee; - color: #53637d; - font-size: 200%; - font-weight: normal; - margin: 0; - padding-bottom: 4px; - padding-inline-end: 24px; - padding-top: 13px; - text-shadow: white 0 1px 2px; -} - -
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/list.css b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/list.css deleted file mode 100644 index 75d2a92..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/list.css +++ /dev/null
@@ -1,89 +0,0 @@ - -list, -grid { - display: block; - outline: none; - overflow: auto; - position: relative; /* Make sure that item offsets are relative to the - list. */ -} - -list > *, -grid > * { - -webkit-user-select: none; - background-color: rgba(255,255,255,0); - border: 1px solid rgba(255,255,255,0); /* transparent white */ - border-radius: 2px; - cursor: default; - line-height: 20px; - margin: -1px 0; - overflow: hidden; - padding: 0px 3px; - position: relative; /* to allow overlap */ - text-overflow: ellipsis; - white-space: pre; -} - -list > * { - display: block; -} - -grid > * { - display: inline-block; -} - -list > [lead], -grid > [lead] { - border-color: transparent; -} - -list:focus > [lead], -grid:focus > [lead] { - border-color: hsl(214, 91%, 65%); - z-index: 2; -} - -list > [anchor], -grid > [anchor] { - -} - -list:not([disabled]) > :hover, -grid:not([disabled]) > :hover { - border-color: hsl(214, 91%, 85%); - z-index: 1; - background-color: hsl(214, 91%, 97%); -} - -list > [selected], -grid > [selected] { - border-color: hsl(0, 0%, 85%); - background-color: hsl(0,0%,90%); - z-index: 2; - background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.8), - rgba(255, 255, 255, 0)); -} - -list:focus > [selected], -grid:focus > [selected] { - background-color: hsl(214,91%,89%); - border-color: hsl(214, 91%, 65%); -} - -list:focus > [lead][selected], -list > [selected]:hover, -grid:focus > [lead][selected], -grid > [selected]:hover { - background-color: hsl(214, 91%, 87%); - border-color: hsl(214, 91%, 65%); -} - -list > .spacer, -grid > .spacer { - border: 0; - box-sizing: border-box; - display: block; - overflow: hidden; - visibility: hidden; - margin: 0; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/select.css b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/select.css deleted file mode 100644 index 24de2aaf..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/css/select.css +++ /dev/null
@@ -1,51 +0,0 @@ -/* Copyright (c) 2011 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. - * - * This is the generic select css used on various WebUI implementations. - */ - -select { - -webkit-appearance: button; - -webkit-border-radius: 2px; - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); - -webkit-user-select: none; - background-image: url("../images/select.png"), - -webkit-linear-gradient(#fafafa, #f4f4f4 40%, #e5e5e5); - background-position: center right; - background-repeat: no-repeat; - border: 1px solid #aaa; - color: #555; - font-size: inherit; - margin: 0; - overflow: hidden; - padding-top: 2px; - padding-inline-end: 20px; - padding-inline-start: 2px; - padding-bottom: 2px; - text-overflow: ellipsis; - white-space: nowrap; -} - -html[dir='rtl'] select { - background-position: center left; -} - - -select:disabled { - color: graytext; -} - -select:enabled:hover { - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); - background-image: url("../images/select.png"), - -webkit-linear-gradient(#fefefe, #f8f8f8 40%, #e9e9e9); - color: #333; -} - -select:enabled:active { - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); - background-image: url("../images/select.png"), - -webkit-linear-gradient(#f4f4f4, #efefef 40%, #dcdcdc); - color: #444; -} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/images/select.png b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/images/select.png deleted file mode 100644 index d5dcea3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/images/select.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr.js deleted file mode 100644 index a1d84ab..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr.js +++ /dev/null
@@ -1,334 +0,0 @@ -// Copyright (c) 2011 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. - -const cr = (function() { - - /** - * Whether we are using a Mac or not. - * @type {boolean} - */ - const isMac = /Mac/.test(navigator.platform); - - /** - * Whether this is on the Windows platform or not. - * @type {boolean} - */ - const isWindows = /Win/.test(navigator.platform); - - /** - * Whether this is on chromeOS or not. - * @type {boolean} - */ - const isChromeOS = /CrOS/.test(navigator.userAgent); - - /** - * Whether this is on vanilla Linux (not chromeOS). - * @type {boolean} - */ - const isLinux = /Linux/.test(navigator.userAgent); - - /** - * Sets the os and toolkit attributes in the <html> element so that platform - * specific css rules can be applied. - */ - function enablePlatformSpecificCSSRules() { - if (isMac) - doc.documentElement.setAttribute('os', 'mac'); - if (isWindows) - doc.documentElement.setAttribute('os', 'windows'); - if (isChromeOS) - doc.documentElement.setAttribute('os', 'chromeos'); - if (isLinux) - doc.documentElement.setAttribute('os', 'linux'); - } - - /** - * Builds an object structure for the provided namespace path, - * ensuring that names that already exist are not overwritten. For - * example: - * "a.b.c" -> a = {};a.b={};a.b.c={}; - * @param {string} name Name of the object that this file defines. - * @param {*=} opt_object The object to expose at the end of the path. - * @param {Object=} opt_objectToExportTo The object to add the path to; - * default is {@code window}. - * @private - */ - function exportPath(name, opt_object, opt_objectToExportTo) { - var parts = name.split('.'); - var cur = opt_objectToExportTo || window /* global */; - - for (var part; parts.length && (part = parts.shift());) { - if (!parts.length && opt_object !== undefined) { - // last part and we have an object; use it - cur[part] = opt_object; - } else if (part in cur) { - cur = cur[part]; - } else { - cur = cur[part] = {}; - } - } - return cur; - }; - - /** - * Fires a property change event on the target. - * @param {EventTarget} target The target to dispatch the event on. - * @param {string} propertyName The name of the property that changed. - * @param {*} newValue The new value for the property. - * @param {*} oldValue The old value for the property. - */ - function dispatchPropertyChange(target, propertyName, newValue, oldValue) { - var e = new CrEvent(propertyName + 'Change'); - e.propertyName = propertyName; - e.newValue = newValue; - e.oldValue = oldValue; - target.dispatchEvent(e); - } - - /** - * The kind of property to define in {@code defineProperty}. - * @enum {number} - */ - const PropertyKind = { - /** - * Plain old JS property where the backing data is stored as a "private" - * field on the object. - */ - JS: 'js', - - /** - * The property backing data is stored as an attribute on an element. - */ - ATTR: 'attr', - - /** - * The property backing data is stored as an attribute on an element. If the - * element has the attribute then the value is true. - */ - BOOL_ATTR: 'boolAttr' - }; - - /** - * Helper function for defineProperty that returns the getter to use for the - * property. - * @param {string} name - * @param {cr.PropertyKind} kind - * @return {function():*} The getter for the property. - */ - function getGetter(name, kind) { - switch (kind) { - case PropertyKind.JS: - var privateName = name + '_'; - return function() { - return this[privateName]; - }; - case PropertyKind.ATTR: - return function() { - return this.getAttribute(name); - }; - case PropertyKind.BOOL_ATTR: - return function() { - return this.hasAttribute(name); - }; - } - } - - /** - * Helper function for defineProperty that returns the setter of the right - * kind. - * @param {string} name The name of the property we are defining the setter - * for. - * @param {cr.PropertyKind} kind The kind of property we are getting the - * setter for. - * @param {function(*):void} opt_setHook A function to run after the property - * is set, but before the propertyChange event is fired. - * @return {function(*):void} The function to use as a setter. - */ - function getSetter(name, kind, opt_setHook) { - switch (kind) { - case PropertyKind.JS: - var privateName = name + '_'; - return function(value) { - var oldValue = this[privateName]; - if (value !== oldValue) { - this[privateName] = value; - if (opt_setHook) - opt_setHook.call(this, value, oldValue); - dispatchPropertyChange(this, name, value, oldValue); - } - }; - - case PropertyKind.ATTR: - return function(value) { - var oldValue = this[name]; - if (value !== oldValue) { - if (value == undefined) - this.removeAttribute(name); - else - this.setAttribute(name, value); - if (opt_setHook) - opt_setHook.call(this, value, oldValue); - dispatchPropertyChange(this, name, value, oldValue); - } - }; - - case PropertyKind.BOOL_ATTR: - return function(value) { - var oldValue = this[name]; - if (value !== oldValue) { - if (value) - this.setAttribute(name, name); - else - this.removeAttribute(name); - if (opt_setHook) - opt_setHook.call(this, value, oldValue); - dispatchPropertyChange(this, name, value, oldValue); - } - }; - } - } - - /** - * Defines a property on an object. When the setter changes the value a - * property change event with the type {@code name + 'Change'} is fired. - * @param {!Object} obj The object to define the property for. - * @param {string} name The name of the property. - * @param {cr.PropertyKind=} opt_kind What kind of underlying storage to use. - * @param {function(*):void} opt_setHook A function to run after the - * property is set, but before the propertyChange event is fired. - */ - function defineProperty(obj, name, opt_kind, opt_setHook) { - if (typeof obj == 'function') - obj = obj.prototype; - - var kind = opt_kind || PropertyKind.JS; - - if (!obj.__lookupGetter__(name)) { - obj.__defineGetter__(name, getGetter(name, kind)); - } - - if (!obj.__lookupSetter__(name)) { - obj.__defineSetter__(name, getSetter(name, kind, opt_setHook)); - } - } - - /** - * Counter for use with createUid - */ - var uidCounter = 1; - - /** - * @return {number} A new unique ID. - */ - function createUid() { - return uidCounter++; - } - - /** - * Returns a unique ID for the item. This mutates the item so it needs to be - * an object - * @param {!Object} item The item to get the unique ID for. - * @return {number} The unique ID for the item. - */ - function getUid(item) { - if (item.hasOwnProperty('uid')) - return item.uid; - return item.uid = createUid(); - } - - /** - * Dispatches a simple event on an event target. - * @param {!EventTarget} target The event target to dispatch the event on. - * @param {string} type The type of the event. - * @param {boolean=} opt_bubbles Whether the event bubbles or not. - * @param {boolean=} opt_cancelable Whether the default action of the event - * can be prevented. Default is true. - * @return {boolean} If any of the listeners called {@code preventDefault} - * during the dispatch this will return false. - */ - function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) { - var e = new Event(type, { - bubbles: opt_bubbles, - cancelable: opt_cancelable === undefined || opt_cancelable - }); - return target.dispatchEvent(e); - } - - /** - * @param {string} name - * @param {!Function} fun - */ - function define(name, fun) { - var obj = exportPath(name); - var exports = fun(); - for (var propertyName in exports) { - // Maybe we should check the prototype chain here? The current usage - // pattern is always using an object literal so we only care about own - // properties. - var propertyDescriptor = Object.getOwnPropertyDescriptor(exports, - propertyName); - if (propertyDescriptor) - Object.defineProperty(obj, propertyName, propertyDescriptor); - } - } - - /** - * Document used for various document related operations. - * @type {!Document} - */ - var doc = document; - - - /** - * Allows you to run func in the context of a different document. - * @param {!Document} document The document to use. - * @param {function():*} func The function to call. - */ - function withDoc(document, func) { - var oldDoc = doc; - doc = document; - try { - func(); - } finally { - doc = oldDoc; - } - } - - /** - * Adds a {@code getInstance} static method that always return the same - * instance object. - * @param {!Function} ctor The constructor for the class to add the static - * method to. - */ - function addSingletonGetter(ctor) { - ctor.getInstance = function() { - return ctor.instance_ || (ctor.instance_ = new ctor()); - }; - } - - return { - addSingletonGetter: addSingletonGetter, - isChromeOS: isChromeOS, - isMac: isMac, - isWindows: isWindows, - isLinux: isLinux, - enablePlatformSpecificCSSRules: enablePlatformSpecificCSSRules, - define: define, - defineProperty: defineProperty, - PropertyKind: PropertyKind, - createUid: createUid, - getUid: getUid, - dispatchSimpleEvent: dispatchSimpleEvent, - dispatchPropertyChange: dispatchPropertyChange, - - /** - * The document that we are currently using. - * @type {!Document} - */ - get doc() { - return doc; - }, - withDoc: withDoc - }; -})();
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/event_target.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/event_target.js deleted file mode 100644 index 5bcb41d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/event_target.js +++ /dev/null
@@ -1,104 +0,0 @@ -// Copyright (c) 2010 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. - -/** - * @fileoverview This contains an implementation of the EventTarget interface - * as defined by DOM Level 2 Events. - */ - -cr.define('cr', function() { - - /** - * Creates a new EventTarget. This class implements the DOM level 2 - * EventTarget interface and can be used wherever those are used. - * @constructor - */ - function EventTarget() { - } - - EventTarget.prototype = { - - /** - * Adds an event listener to the target. - * @param {string} type The name of the event. - * @param {!Function|{handleEvent:Function}} handler The handler for the - * event. This is called when the event is dispatched. - */ - addEventListener: function(type, handler) { - if (!this.listeners_) - this.listeners_ = Object.create(null); - if (!(type in this.listeners_)) { - this.listeners_[type] = [handler]; - } else { - var handlers = this.listeners_[type]; - if (handlers.indexOf(handler) < 0) - handlers.push(handler); - } - }, - - /** - * Removes an event listener from the target. - * @param {string} type The name of the event. - * @param {!Function|{handleEvent:Function}} handler The handler for the - * event. - */ - removeEventListener: function(type, handler) { - if (!this.listeners_) - return; - if (type in this.listeners_) { - var handlers = this.listeners_[type]; - var index = handlers.indexOf(handler); - if (index >= 0) { - // Clean up if this was the last listener. - if (handlers.length == 1) - delete this.listeners_[type]; - else - handlers.splice(index, 1); - } - } - }, - - /** - * Dispatches an event and calls all the listeners that are listening to - * the type of the event. - * @param {!cr.event.Event} event The event to dispatch. - * @return {boolean} Whether the default action was prevented. If someone - * calls preventDefault on the event object then this returns false. - */ - dispatchEvent: function(event) { - if (!this.listeners_) - return true; - - // Since we are using DOM Event objects we need to override some of the - // properties and methods so that we can emulate this correctly. - var self = this; - event.__defineGetter__('target', function() { - return self; - }); - event.preventDefault = function() { - this.returnValue = false; - }; - - var type = event.type; - var prevented = 0; - if (type in this.listeners_) { - // Clone to prevent removal during dispatch - var handlers = this.listeners_[type].concat(); - for (var i = 0, handler; handler = handlers[i]; i++) { - if (handler.handleEvent) - prevented |= handler.handleEvent.call(handler, event) === false; - else - prevented |= handler.call(this, event) === false; - } - } - - return !prevented && event.returnValue; - } - }; - - // Export - return { - EventTarget: EventTarget - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui.js deleted file mode 100644 index ea286b2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui.js +++ /dev/null
@@ -1,161 +0,0 @@ -// Copyright (c) 2010 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. - -cr.define('cr.ui', function() { - - /** - * Decorates elements as an instance of a class. - * @param {string|!Element} source The way to find the element(s) to decorate. - * If this is a string then {@code querySeletorAll} is used to find the - * elements to decorate. - * @param {!Function} constr The constructor to decorate with. The constr - * needs to have a {@code decorate} function. - */ - function decorate(source, constr) { - var elements; - if (typeof source == 'string') - elements = cr.doc.querySelectorAll(source); - else - elements = [source]; - - for (var i = 0, el; el = elements[i]; i++) { - if (!(el instanceof constr)) - constr.decorate(el); - } - } - - /** - * Helper function for creating new element for define. - */ - function createElementHelper(tagName, opt_bag) { - // Allow passing in ownerDocument to create in a different document. - var doc; - if (opt_bag && opt_bag.ownerDocument) - doc = opt_bag.ownerDocument; - else - doc = cr.doc; - return doc.createElement(tagName); - } - - /** - * Creates the constructor for a UI element class. - * - * Usage: - * <pre> - * var List = cr.ui.define('list'); - * List.prototype = { - * __proto__: HTMLUListElement.prototype, - * decorate: function() { - * ... - * }, - * ... - * }; - * </pre> - * - * @param {string|Function} tagNameOrFunction The tagName or - * function to use for newly created elements. If this is a function it - * needs to return a new element when called. - * @return {function(Object=):Element} The constructor function which takes - * an optional property bag. The function also has a static - * {@code decorate} method added to it. - */ - function define(tagNameOrFunction) { - var createFunction, tagName; - if (typeof tagNameOrFunction == 'function') { - createFunction = tagNameOrFunction; - tagName = ''; - } else { - createFunction = createElementHelper; - tagName = tagNameOrFunction; - } - - /** - * Creates a new UI element constructor. - * @param {Object=} opt_propertyBag Optional bag of properties to set on the - * object after created. The property {@code ownerDocument} is special - * cased and it allows you to create the element in a different - * document than the default. - * @constructor - */ - function f(opt_propertyBag) { - var el = createFunction(tagName, opt_propertyBag); - f.decorate(el); - for (var propertyName in opt_propertyBag) { - el[propertyName] = opt_propertyBag[propertyName]; - } - return el; - } - - /** - * Decorates an element as a UI element class. - * @param {!Element} el The element to decorate. - */ - f.decorate = function(el) { - el.__proto__ = f.prototype; - el.decorate(); - }; - - return f; - } - - /** - * Input elements do not grow and shrink with their content. This is a simple - * (and not very efficient) way of handling shrinking to content with support - * for min width and limited by the width of the parent element. - * @param {HTMLElement} el The element to limit the width for. - * @param {number} parentEl The parent element that should limit the size. - * @param {number} min The minimum width. - */ - function limitInputWidth(el, parentEl, min) { - // Needs a size larger than borders - el.style.width = '10px'; - var doc = el.ownerDocument; - var win = doc.defaultView; - var computedStyle = win.getComputedStyle(el); - var parentComputedStyle = win.getComputedStyle(parentEl); - var rtl = computedStyle.direction == 'rtl'; - - // To get the max width we get the width of the treeItem minus the position - // of the input. - var inputRect = el.getBoundingClientRect(); // box-sizing - var parentRect = parentEl.getBoundingClientRect(); - var startPos = rtl ? parentRect.right - inputRect.right : - inputRect.left - parentRect.left; - - // Add up border and padding of the input. - var inner = parseInt(computedStyle.borderLeftWidth, 10) + - parseInt(computedStyle.paddingLeft, 10) + - parseInt(computedStyle.paddingRight, 10) + - parseInt(computedStyle.borderRightWidth, 10); - - // We also need to subtract the padding of parent to prevent it to overflow. - var parentPadding = rtl ? parseInt(parentComputedStyle.paddingLeft, 10) : - parseInt(parentComputedStyle.paddingRight, 10); - - var max = parentEl.clientWidth - startPos - inner - parentPadding; - - function limit() { - if (el.scrollWidth > max) { - el.style.width = max + 'px'; - } else { - el.style.width = 0; - var sw = el.scrollWidth; - if (sw < min) { - el.style.width = min + 'px'; - } else { - el.style.width = sw + 'px'; - } - } - } - - el.addEventListener('input', limit); - limit(); - } - - return { - decorate: decorate, - define: define, - limitInputWidth: limitInputWidth - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js deleted file mode 100644 index fa695f8e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/array_data_model.js +++ /dev/null
@@ -1,362 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * @fileoverview This is a data model representin - */ - -cr.define('cr.ui', function() { - /** @const */ var EventTarget = cr.EventTarget; - - /** - * A data model that wraps a simple array and supports sorting by storing - * initial indexes of elements for each position in sorted array. - * @param {!Array} array The underlying array. - * @constructor - * @extends {EventTarget} - */ - function ArrayDataModel(array) { - this.array_ = array; - this.indexes_ = []; - this.compareFunctions_ = {}; - - for (var i = 0; i < array.length; i++) { - this.indexes_.push(i); - } - } - - ArrayDataModel.prototype = { - __proto__: EventTarget.prototype, - - /** - * The length of the data model. - * @type {number} - */ - get length() { - return this.array_.length; - }, - - /** - * Returns the item at the given index. - * This implementation returns the item at the given index in the sorted - * array. - * @param {number} index The index of the element to get. - * @return {*} The element at the given index. - */ - item: function(index) { - if (index >= 0 && index < this.length) - return this.array_[this.indexes_[index]]; - return undefined; - }, - - /** - * Returns compare function set for given field. - * @param {string} field The field to get compare function for. - * @return {function(*, *): number} Compare function set for given field. - */ - compareFunction: function(field) { - return this.compareFunctions_[field]; - }, - - /** - * Sets compare function for given field. - * @param {string} field The field to set compare function. - * @param {function(*, *): number} Compare function to set for given field. - */ - setCompareFunction: function(field, compareFunction) { - if (!this.compareFunctions_) { - this.compareFunctions_ = {}; - } - this.compareFunctions_[field] = compareFunction; - }, - - /** - * Returns current sort status. - * @return {!Object} Current sort status. - */ - get sortStatus() { - if (this.sortStatus_) { - return this.createSortStatus( - this.sortStatus_.field, this.sortStatus_.direction); - } else { - return this.createSortStatus(null, null); - } - }, - - /** - * Returns the first matching item. - * @param {*} item The item to find. - * @param {number=} opt_fromIndex If provided, then the searching start at - * the {@code opt_fromIndex}. - * @return {number} The index of the first found element or -1 if not found. - */ - indexOf: function(item, opt_fromIndex) { - return this.array_.indexOf(item, opt_fromIndex); - }, - - /** - * Returns an array of elements in a selected range. - * @param {number=} opt_from The starting index of the selected range. - * @param {number=} opt_to The ending index of selected range. - * @return {Array} An array of elements in the selected range. - */ - slice: function(opt_from, opt_to) { - return this.array_.slice.apply(this.array_, arguments); - }, - - /** - * This removes and adds items to the model. - * This dispatches a splice event. - * This implementation runs sort after splice and creates permutation for - * the whole change. - * @param {number} index The index of the item to update. - * @param {number} deleteCount The number of items to remove. - * @param {...*} The items to add. - * @return {!Array} An array with the removed items. - */ - splice: function(index, deleteCount, var_args) { - var addCount = arguments.length - 2; - var newIndexes = []; - var deletePermutation = []; - var deleted = 0; - for (var i = 0; i < this.indexes_.length; i++) { - var oldIndex = this.indexes_[i]; - if (oldIndex < index) { - newIndexes.push(oldIndex); - deletePermutation.push(i - deleted); - } else if (oldIndex >= index + deleteCount) { - newIndexes.push(oldIndex - deleteCount + addCount); - deletePermutation.push(i - deleted); - } else { - deletePermutation.push(-1); - deleted++; - } - } - for (var i = 0; i < addCount; i++) { - newIndexes.push(index + i); - } - this.indexes_ = newIndexes; - - var arr = this.array_; - - // TODO(arv): Maybe unify splice and change events? - var spliceEvent = new Event('splice'); - spliceEvent.index = index; - spliceEvent.removed = arr.slice(index, index + deleteCount); - spliceEvent.added = Array.prototype.slice.call(arguments, 2); - - var rv = arr.splice.apply(arr, arguments); - - var status = this.sortStatus; - // if sortStatus.field is null, this restores original order. - var sortPermutation = this.doSort_(this.sortStatus.field, - this.sortStatus.direction); - if (sortPermutation) { - var splicePermutation = deletePermutation.map(function(element) { - return element != -1 ? sortPermutation[element] : -1; - }); - this.dispatchPermutedEvent_(splicePermutation); - } else { - this.dispatchPermutedEvent_(deletePermutation); - } - - this.dispatchEvent(spliceEvent); - - // If real sorting is needed, we should first call prepareSort (data may - // change), and then sort again. - // Still need to finish the sorting above (including events), so - // list will not go to inconsistent state. - if (status.field) { - setTimeout(this.sort.bind(this, status.field, status.direction), 0); - } - return rv; - }, - - /** - * Appends items to the end of the model. - * - * This dispatches a splice event. - * - * @param {...*} The items to append. - * @return {number} The new length of the model. - */ - push: function(var_args) { - var args = Array.prototype.slice.call(arguments); - args.unshift(this.length, 0); - this.splice.apply(this, args); - return this.length; - }, - - /** - * Use this to update a given item in the array. This does not remove and - * reinsert a new item. - * This dispatches a change event. - * This runs sort after updating. - * @param {number} index The index of the item to update. - */ - updateIndex: function(index) { - if (index < 0 || index >= this.length) - throw Error('Invalid index, ' + index); - - // TODO(arv): Maybe unify splice and change events? - var e = new Event('change'); - e.index = index; - this.dispatchEvent(e); - - if (this.sortStatus.field) { - var status = this.sortStatus; - var sortPermutation = this.doSort_(this.sortStatus.field, - this.sortStatus.direction); - if (sortPermutation) - this.dispatchPermutedEvent_(sortPermutation); - // We should first call prepareSort (data may change), and then sort. - // Still need to finish the sorting above (including events), so - // list will not go to inconsistent state. - setTimeout(this.sort.bind(this, status.field, status.direction), 0); - } - }, - - /** - * Creates sort status with given field and direction. - * @param {string} field Sort field. - * @param {string} direction Sort direction. - * @return {!Object} Created sort status. - */ - createSortStatus: function(field, direction) { - return { - field: field, - direction: direction - }; - }, - - /** - * Called before a sort happens so that you may fetch additional data - * required for the sort. - * - * @param {string} field Sort field. - * @param {function()} callback The function to invoke when preparation - * is complete. - */ - prepareSort: function(field, callback) { - callback(); - }, - - /** - * Sorts data model according to given field and direction and dispathes - * sorted event. - * @param {string} field Sort field. - * @param {string} direction Sort direction. - */ - sort: function(field, direction) { - var self = this; - - this.prepareSort(field, function() { - var sortPermutation = self.doSort_(field, direction); - if (sortPermutation) - self.dispatchPermutedEvent_(sortPermutation); - self.dispatchSortEvent_(); - }); - }, - - /** - * Sorts data model according to given field and direction. - * @param {string} field Sort field. - * @param {string} direction Sort direction. - */ - doSort_: function(field, direction) { - var compareFunction = this.sortFunction_(field, direction); - var positions = []; - for (var i = 0; i < this.length; i++) { - positions[this.indexes_[i]] = i; - } - this.indexes_.sort(compareFunction); - this.sortStatus_ = this.createSortStatus(field, direction); - var sortPermutation = []; - var changed = false; - for (var i = 0; i < this.length; i++) { - if (positions[this.indexes_[i]] != i) - changed = true; - sortPermutation[positions[this.indexes_[i]]] = i; - } - if (changed) - return sortPermutation; - return null; - }, - - dispatchSortEvent_: function() { - var e = new Event('sorted'); - this.dispatchEvent(e); - }, - - dispatchPermutedEvent_: function(permutation) { - var e = new Event('permuted'); - e.permutation = permutation; - e.newLength = this.length; - this.dispatchEvent(e); - }, - - /** - * Creates compare function for the field. - * Returns the function set as sortFunction for given field - * or default compare function - * @param {string} field Sort field. - * @param {function(*, *): number} Compare function. - */ - createCompareFunction_: function(field) { - var compareFunction = - this.compareFunctions_ ? this.compareFunctions_[field] : null; - var defaultValuesCompareFunction = this.defaultValuesCompareFunction; - if (compareFunction) { - return compareFunction; - } else { - return function(a, b) { - return defaultValuesCompareFunction.call(null, a[field], b[field]); - } - } - return compareFunction; - }, - - /** - * Creates compare function for given field and direction. - * @param {string} field Sort field. - * @param {string} direction Sort direction. - * @param {function(*, *): number} Compare function. - */ - sortFunction_: function(field, direction) { - var compareFunction = null; - if (field !== null) - compareFunction = this.createCompareFunction_(field); - var dirMultiplier = direction == 'desc' ? -1 : 1; - - return function(index1, index2) { - var item1 = this.array_[index1]; - var item2 = this.array_[index2]; - - var compareResult = 0; - if (typeof(compareFunction) === 'function') - compareResult = compareFunction.call(null, item1, item2); - if (compareResult != 0) - return dirMultiplier * compareResult; - return dirMultiplier * this.defaultValuesCompareFunction(index1, - index2); - }.bind(this); - }, - - /** - * Default compare function. - */ - defaultValuesCompareFunction: function(a, b) { - // We could insert i18n comparisons here. - if (a < b) - return -1; - if (a > b) - return 1; - return 0; - } - }; - - return { - ArrayDataModel: ArrayDataModel - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list.js deleted file mode 100644 index bc71eb68..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list.js +++ /dev/null
@@ -1,971 +0,0 @@ -// Copyright (c) 2011 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. - -// require: array_data_model.js -// require: list_selection_model.js -// require: list_selection_controller.js -// require: list_item.js - -/** - * @fileoverview This implements a list control. - */ - -cr.define('cr.ui', function() { - const ListSelectionModel = cr.ui.ListSelectionModel; - const ListSelectionController = cr.ui.ListSelectionController; - const ArrayDataModel = cr.ui.ArrayDataModel; - - /** - * Whether a mouse event is inside the element viewport. This will return - * false if the mouseevent was generated over a border or a scrollbar. - * @param {!HTMLElement} el The element to test the event with. - * @param {!Event} e The mouse event. - * @param {boolean} Whether the mouse event was inside the viewport. - */ - function inViewport(el, e) { - var rect = el.getBoundingClientRect(); - var x = e.clientX; - var y = e.clientY; - return x >= rect.left + el.clientLeft && - x < rect.left + el.clientLeft + el.clientWidth && - y >= rect.top + el.clientTop && - y < rect.top + el.clientTop + el.clientHeight; - } - - /** - * Creates an item (dataModel.item(0)) and measures its height. - * @param {!List} list The list to create the item for. - * @param {ListItem=} opt_item The list item to use to do the measuring. If - * this is not provided an item will be created based on the first value - * in the model. - * @return {{height: number, marginVertical: number, width: number, - * marginHorizontal: number}} The height and width of the item, taking - * margins into account, and the height and width of the margins - * themselves. - */ - function measureItem(list, opt_item) { - var dataModel = list.dataModel; - if (!dataModel || !dataModel.length) - return 0; - var item = opt_item || list.createItem(dataModel.item(0)); - if (!opt_item) - list.appendChild(item); - - var rect = item.getBoundingClientRect(); - var cs = getComputedStyle(item); - var mt = parseFloat(cs.marginTop); - var mb = parseFloat(cs.marginBottom); - var ml = parseFloat(cs.marginLeft); - var mr = parseFloat(cs.marginRight); - var h = rect.height; - var w = rect.width; - var mh = 0; - var mv = 0; - - // Handle margin collapsing. - if (mt < 0 && mb < 0) { - mv = Math.min(mt, mb); - } else if (mt >= 0 && mb >= 0) { - mv = Math.max(mt, mb); - } else { - mv = mt + mb; - } - h += mv; - - if (ml < 0 && mr < 0) { - mh = Math.min(ml, mr); - } else if (ml >= 0 && mr >= 0) { - mh = Math.max(ml, mr); - } else { - mh = ml + mr; - } - w += mh; - - if (!opt_item) - list.removeChild(item); - return { - height: Math.max(0, h), marginVertical: mv, - width: Math.max(0, w), marginHorizontal: mh}; - } - - function getComputedStyle(el) { - return el.ownerDocument.defaultView.getComputedStyle(el); - } - - /** - * Creates a new list element. - * @param {Object=} opt_propertyBag Optional properties. - * @constructor - * @extends {HTMLUListElement} - */ - var List = cr.ui.define('list'); - - List.prototype = { - __proto__: HTMLUListElement.prototype, - - /** - * Measured size of list items. This is lazily calculated the first time it - * is needed. Note that lead item is allowed to have a different height, to - * accommodate lists where a single item at a time can be expanded to show - * more detail. - * @type {{height: number, marginVertical: number, width: number, - * marginHorizontal: number}} - * @private - */ - measured_: undefined, - - /** - * The height of the lead item, which is allowed to have a different height - * than other list items to accommodate lists where a single item at a time - * can be expanded to show more detail. It is explicitly set by client code - * when the height of the lead item is changed with {@code set - * leadItemHeight}, and presumed equal to {@code itemHeight_} otherwise. - * @type {number} - * @private - */ - leadItemHeight_: 0, - - /** - * Whether or not the list is autoexpanding. If true, the list resizes - * its height to accomadate all children. - * @type {boolean} - * @private - */ - autoExpands_: false, - - /** - * Function used to create grid items. - * @type {function(): !ListItem} - * @private - */ - itemConstructor_: cr.ui.ListItem, - - /** - * Function used to create grid items. - * @type {function(): !ListItem} - */ - get itemConstructor() { - return this.itemConstructor_; - }, - set itemConstructor(func) { - if (func != this.itemConstructor_) { - this.itemConstructor_ = func; - this.cachedItems_ = {}; - this.redraw(); - } - }, - - dataModel_: null, - - /** - * The data model driving the list. - * @type {ArrayDataModel} - */ - set dataModel(dataModel) { - if (this.dataModel_ != dataModel) { - if (!this.boundHandleDataModelPermuted_) { - this.boundHandleDataModelPermuted_ = - this.handleDataModelPermuted_.bind(this); - this.boundHandleDataModelChange_ = - this.handleDataModelChange_.bind(this); - } - - if (this.dataModel_) { - this.dataModel_.removeEventListener( - 'permuted', - this.boundHandleDataModelPermuted_); - this.dataModel_.removeEventListener('change', - this.boundHandleDataModelChange_); - } - - this.dataModel_ = dataModel; - - this.cachedItems_ = {}; - this.selectionModel.clear(); - if (dataModel) - this.selectionModel.adjustLength(dataModel.length); - - if (this.dataModel_) { - this.dataModel_.addEventListener( - 'permuted', - this.boundHandleDataModelPermuted_); - this.dataModel_.addEventListener('change', - this.boundHandleDataModelChange_); - } - - this.redraw(); - } - }, - - get dataModel() { - return this.dataModel_; - }, - - /** - * The selection model to use. - * @type {cr.ui.ListSelectionModel} - */ - get selectionModel() { - return this.selectionModel_; - }, - set selectionModel(sm) { - var oldSm = this.selectionModel_; - if (oldSm == sm) - return; - - if (!this.boundHandleOnChange_) { - this.boundHandleOnChange_ = this.handleOnChange_.bind(this); - this.boundHandleLeadChange_ = this.handleLeadChange_.bind(this); - } - - if (oldSm) { - oldSm.removeEventListener('change', this.boundHandleOnChange_); - oldSm.removeEventListener('leadIndexChange', - this.boundHandleLeadChange_); - } - - this.selectionModel_ = sm; - this.selectionController_ = this.createSelectionController(sm); - - if (sm) { - sm.addEventListener('change', this.boundHandleOnChange_); - sm.addEventListener('leadIndexChange', this.boundHandleLeadChange_); - } - }, - - /** - * Whether or not the list auto-expands. - * @type {boolean} - */ - get autoExpands() { - return this.autoExpands_; - }, - set autoExpands(autoExpands) { - if (this.autoExpands_ == autoExpands) - return; - this.autoExpands_ = autoExpands; - this.redraw(); - }, - - /** - * Convenience alias for selectionModel.selectedItem - * @type {cr.ui.ListItem} - */ - get selectedItem() { - var dataModel = this.dataModel; - if (dataModel) { - var index = this.selectionModel.selectedIndex; - if (index != -1) - return dataModel.item(index); - } - return null; - }, - set selectedItem(selectedItem) { - var dataModel = this.dataModel; - if (dataModel) { - var index = this.dataModel.indexOf(selectedItem); - this.selectionModel.selectedIndex = index; - } - }, - - /** - * The height of the lead item. - * If set to 0, resets to the same height as other items. - * @type {number} - */ - get leadItemHeight() { - return this.leadItemHeight_ || this.getItemHeight_(); - }, - set leadItemHeight(height) { - if (height) { - var size = this.getItemSize_(); - this.leadItemHeight_ = Math.max(0, height + size.marginVertical); - } else { - this.leadItemHeight_ = 0; - } - }, - - /** - * Convenience alias for selectionModel.selectedItems - * @type {!Array<cr.ui.ListItem>} - */ - get selectedItems() { - var indexes = this.selectionModel.selectedIndexes; - var dataModel = this.dataModel; - if (dataModel) { - return indexes.map(function(i) { - return dataModel.item(i); - }); - } - return []; - }, - - /** - * The HTML elements representing the items. This is just all the list item - * children but subclasses may override this to filter out certain elements. - * @type {HTMLCollection} - */ - get items() { - return Array.prototype.filter.call(this.children, function(child) { - return !child.classList.contains('spacer'); - }); - }, - - batchCount_: 0, - - /** - * When making a lot of updates to the list, the code could be wrapped in - * the startBatchUpdates and finishBatchUpdates to increase performance. Be - * sure that the code will not return without calling endBatchUpdates or the - * list will not be correctly updated. - */ - startBatchUpdates: function() { - this.batchCount_++; - }, - - /** - * See startBatchUpdates. - */ - endBatchUpdates: function() { - this.batchCount_--; - if (this.batchCount_ == 0) - this.redraw(); - }, - - /** - * Initializes the element. - */ - decorate: function() { - // Add fillers. - this.beforeFiller_ = this.ownerDocument.createElement('div'); - this.afterFiller_ = this.ownerDocument.createElement('div'); - this.beforeFiller_.className = 'spacer'; - this.afterFiller_.className = 'spacer'; - this.appendChild(this.beforeFiller_); - this.appendChild(this.afterFiller_); - - var length = this.dataModel ? this.dataModel.length : 0; - this.selectionModel = new ListSelectionModel(length); - - this.addEventListener('dblclick', this.handleDoubleClick_); - this.addEventListener('mousedown', this.handleMouseDownUp_); - this.addEventListener('mouseup', this.handleMouseDownUp_); - this.addEventListener('keydown', this.handleKeyDown); - this.addEventListener('focus', this.handleElementFocus_, true); - this.addEventListener('blur', this.handleElementBlur_, true); - this.addEventListener('scroll', this.redraw.bind(this)); - this.setAttribute('role', 'listbox'); - - // Make list focusable - if (!this.hasAttribute('tabindex')) - this.tabIndex = 0; - }, - - /** - * @return {number} The height of an item, measuring it if necessary. - * @private - */ - getItemHeight_: function() { - return this.getItemSize_().height; - }, - - /** - * @return {number} The width of an item, measuring it if necessary. - * @private - */ - getItemWidth_: function() { - return this.getItemSize_().width; - }, - - /** - * @return {{height: number, width: number}} The height and width - * of an item, measuring it if necessary. - * @private - */ - getItemSize_: function() { - if (!this.measured_ || !this.measured_.height) { - this.measured_ = measureItem(this); - } - return this.measured_; - }, - - /** - * Callback for the double click event. - * @param {Event} e The mouse event object. - * @private - */ - handleDoubleClick_: function(e) { - if (this.disabled) - return; - - var target = this.getListItemAncestor(e.target); - if (target) - this.activateItemAtIndex(this.getIndexOfListItem(target)); - }, - - /** - * Callback for mousedown and mouseup events. - * @param {Event} e The mouse event object. - * @private - */ - handleMouseDownUp_: function(e) { - if (this.disabled) - return; - - var target = e.target; - - // If the target was this element we need to make sure that the user did - // not click on a border or a scrollbar. - if (target == this && !inViewport(target, e)) - return; - - target = this.getListItemAncestor(target); - - var index = target ? this.getIndexOfListItem(target) : -1; - this.selectionController_.handleMouseDownUp(e, index); - }, - - /** - * Called when an element in the list is focused. Marks the list as having - * a focused element, and dispatches an event if it didn't have focus. - * @param {Event} e The focus event. - * @private - */ - handleElementFocus_: function(e) { - if (!this.hasElementFocus) { - this.hasElementFocus = true; - // Force styles based on hasElementFocus to take effect. - this.forceRepaint_(); - } - }, - - /** - * Called when an element in the list is blurred. If focus moves outside - * the list, marks the list as no longer having focus and dispatches an - * event. - * @param {Event} e The blur event. - * @private - */ - handleElementBlur_: function(e) { - // When the blur event happens we do not know who is getting focus so we - // delay this a bit until we know if the new focus node is outside the - // list. - var list = this; - var doc = e.target.ownerDocument; - window.setTimeout(function() { - var activeElement = doc.activeElement; - if (!list.contains(activeElement)) { - list.hasElementFocus = false; - // Force styles based on hasElementFocus to take effect. - list.forceRepaint_(); - } - }); - }, - - /** - * Forces a repaint of the list. Changing custom attributes, even if there - * are style rules depending on them, doesn't cause a repaint - * (<https://bugs.webkit.org/show_bug.cgi?id=12519>), so this can be called - * to force the list to repaint. - * @private - */ - forceRepaint_: function(e) { - var dummyElement = document.createElement('div'); - this.appendChild(dummyElement); - this.removeChild(dummyElement); - }, - - /** - * Returns the list item element containing the given element, or null if - * it doesn't belong to any list item element. - * @param {HTMLElement} element The element. - * @return {ListItem} The list item containing |element|, or null. - */ - getListItemAncestor: function(element) { - var container = element; - while (container && container.parentNode != this) { - container = container.parentNode; - } - return container; - }, - - /** - * Handle a keydown event. - * @param {Event} e The keydown event. - * @return {boolean} Whether the key event was handled. - */ - handleKeyDown: function(e) { - if (this.disabled) - return; - - return this.selectionController_.handleKeyDown(e); - }, - - /** - * Callback from the selection model. We dispatch {@code change} events - * when the selection changes. - * @param {!Event} e Event with change info. - * @private - */ - handleOnChange_: function(ce) { - ce.changes.forEach(function(change) { - var listItem = this.getListItemByIndex(change.index); - if (listItem) - listItem.selected = change.selected; - }, this); - - cr.dispatchSimpleEvent(this, 'change'); - }, - - /** - * Handles a change of the lead item from the selection model. - * @property {Event} pe The property change event. - * @private - */ - handleLeadChange_: function(pe) { - var element; - if (pe.oldValue != -1) { - if ((element = this.getListItemByIndex(pe.oldValue))) - element.lead = false; - } - - if (pe.newValue != -1) { - if ((element = this.getListItemByIndex(pe.newValue))) - element.lead = true; - this.scrollIndexIntoView(pe.newValue); - // If the lead item has a different height than other items, then we - // may run into a problem that requires a second attempt to scroll - // it into view. The first scroll attempt will trigger a redraw, - // which will clear out the list and repopulate it with new items. - // During the redraw, the list may shrink temporarily, which if the - // lead item is the last item, will move the scrollTop up since it - // cannot extend beyond the end of the list. (Sadly, being scrolled to - // the bottom of the list is not "sticky.") So, we set a timeout to - // rescroll the list after this all gets sorted out. This is perhaps - // not the most elegant solution, but no others seem obvious. - var self = this; - window.setTimeout(function() { - self.scrollIndexIntoView(pe.newValue); - }); - } - }, - - /** - * This handles data model 'permuted' event. - * this event is dispatched as a part of sort or splice. - * We need to - * - adjust the cache. - * - adjust selection. - * - redraw. - * - scroll the list to show selection. - * It is important that the cache adjustment happens before selection model - * adjustments. - * @param {Event} e The 'permuted' event. - */ - handleDataModelPermuted_: function(e) { - var newCachedItems = {}; - for (var index in this.cachedItems_) { - if (e.permutation[index] != -1) - newCachedItems[e.permutation[index]] = this.cachedItems_[index]; - else - delete this.cachedItems_[index]; - } - this.cachedItems_ = newCachedItems; - - this.startBatchUpdates(); - - var sm = this.selectionModel; - sm.adjustLength(e.newLength); - sm.adjustToReordering(e.permutation); - - this.endBatchUpdates(); - - if (sm.leadIndex != -1) - this.scrollIndexIntoView(sm.leadIndex); - }, - - handleDataModelChange_: function(e) { - if (e.index >= this.firstIndex_ && e.index < this.lastIndex_) { - if (this.cachedItems_[e.index]) - delete this.cachedItems_[e.index]; - this.redraw(); - } - }, - - /** - * @param {number} index The index of the item. - * @return {number} The top position of the item inside the list, not taking - * into account lead item. May vary in the case of multiple columns. - */ - getItemTop: function(index) { - return index * this.getItemHeight_(); - }, - - /** - * @param {number} index The index of the item. - * @return {number} The row of the item. May vary in the case - * of multiple columns. - */ - getItemRow: function(index) { - return index; - }, - - /** - * @param {number} row The row. - * @return {number} The index of the first item in the row. - */ - getFirstItemInRow: function(row) { - return row; - }, - - /** - * Ensures that a given index is inside the viewport. - * @param {number} index The index of the item to scroll into view. - * @return {boolean} Whether any scrolling was needed. - */ - scrollIndexIntoView: function(index) { - var dataModel = this.dataModel; - if (!dataModel || index < 0 || index >= dataModel.length) - return false; - - var itemHeight = this.getItemHeight_(); - var scrollTop = this.scrollTop; - var top = this.getItemTop(index); - var leadIndex = this.selectionModel.leadIndex; - - // Adjust for the lead item if it is above the given index. - if (leadIndex > -1 && leadIndex < index) - top += this.leadItemHeight - itemHeight; - else if (leadIndex == index) - itemHeight = this.leadItemHeight; - - if (top < scrollTop) { - this.scrollTop = top; - return true; - } else { - var clientHeight = this.clientHeight; - var cs = getComputedStyle(this); - var paddingY = parseInt(cs.paddingTop, 10) + - parseInt(cs.paddingBottom, 10); - - if (top + itemHeight > scrollTop + clientHeight - paddingY) { - this.scrollTop = top + itemHeight - clientHeight + paddingY; - return true; - } - } - - return false; - }, - - /** - * @return {!ClientRect} The rect to use for the context menu. - */ - getRectForContextMenu: function() { - // TODO(arv): Add trait support so we can share more code between trees - // and lists. - var index = this.selectionModel.selectedIndex; - var el = this.getListItemByIndex(index); - if (el) - return el.getBoundingClientRect(); - return this.getBoundingClientRect(); - }, - - /** - * Takes a value from the data model and finds the associated list item. - * @param {*} value The value in the data model that we want to get the list - * item for. - * @return {ListItem} The first found list item or null if not found. - */ - getListItem: function(value) { - var dataModel = this.dataModel; - if (dataModel) { - var index = dataModel.indexOf(value); - return this.getListItemByIndex(index); - } - return null; - }, - - /** - * Find the list item element at the given index. - * @param {number} index The index of the list item to get. - * @return {ListItem} The found list item or null if not found. - */ - getListItemByIndex: function(index) { - return this.cachedItems_[index] || null; - }, - - /** - * Find the index of the given list item element. - * @param {ListItem} item The list item to get the index of. - * @return {number} The index of the list item, or -1 if not found. - */ - getIndexOfListItem: function(item) { - var index = item.listIndex; - if (this.cachedItems_[index] == item) { - return index; - } - return -1; - }, - - /** - * Creates a new list item. - * @param {*} value The value to use for the item. - * @return {!ListItem} The newly created list item. - */ - createItem: function(value) { - var item = new this.itemConstructor_(value); - item.label = value; - if (typeof item.decorate == 'function') - item.decorate(); - return item; - }, - - /** - * Creates the selection controller to use internally. - * @param {cr.ui.ListSelectionModel} sm The underlying selection model. - * @return {!cr.ui.ListSelectionController} The newly created selection - * controller. - */ - createSelectionController: function(sm) { - return new ListSelectionController(sm); - }, - - /** - * Return the heights (in pixels) of the top of the given item index within - * the list, and the height of the given item itself, accounting for the - * possibility that the lead item may be a different height. - * @param {number} index The index to find the top height of. - * @return {{top: number, height: number}} The heights for the given index. - * @private - */ - getHeightsForIndex_: function(index) { - var itemHeight = this.getItemHeight_(); - var top = this.getItemTop(index); - if (this.selectionModel.leadIndex > -1 && - this.selectionModel.leadIndex < index) { - top += this.leadItemHeight - itemHeight; - } else if (this.selectionModel.leadIndex == index) { - itemHeight = this.leadItemHeight; - } - return {top: top, height: itemHeight}; - }, - - /** - * Find the index of the list item containing the given y offset (measured - * in pixels from the top) within the list. In the case of multiple columns, - * returns the first index in the row. - * @param {number} offset The y offset in pixels to get the index of. - * @return {number} The index of the list item. - * @private - */ - getIndexForListOffset_: function(offset) { - var itemHeight = this.getItemHeight_(); - var leadIndex = this.selectionModel.leadIndex; - var leadItemHeight = this.leadItemHeight; - if (leadIndex < 0 || leadItemHeight == itemHeight) { - // Simple case: no lead item or lead item height is not different. - return this.getFirstItemInRow(Math.floor(offset / itemHeight)); - } - var leadTop = this.getItemTop(leadIndex); - // If the given offset is above the lead item, it's also simple. - if (offset < leadTop) - return this.getFirstItemInRow(Math.floor(offset / itemHeight)); - // If the lead item contains the given offset, we just return its index. - if (offset < leadTop + leadItemHeight) - return this.getFirstItemInRow(this.getItemRow(leadIndex)); - // The given offset must be below the lead item. Adjust and recalculate. - offset -= leadItemHeight - itemHeight; - return this.getFirstItemInRow(Math.floor(offset / itemHeight)); - }, - - /** - * Return the number of items that occupy the range of heights between the - * top of the start item and the end offset. - * @param {number} startIndex The index of the first visible item. - * @param {number} endOffset The y offset in pixels of the end of the list. - * @return {number} The number of list items visible. - * @private - */ - countItemsInRange_: function(startIndex, endOffset) { - var endIndex = this.getIndexForListOffset_(endOffset); - return endIndex - startIndex + 1; - }, - - /** - * Calculates the number of items fitting in viewport given the index of - * first item and heights. - * @param {number} itemHeight The height of the item. - * @param {number} firstIndex Index of the first item in viewport. - * @param {number} scrollTop The scroll top position. - * @return {number} The number of items in view port. - */ - getItemsInViewPort: function(itemHeight, firstIndex, scrollTop) { - // This is a bit tricky. We take the minimum of the available items to - // show and the number we want to show, so as not to go off the end of the - // list. For the number we want to show, we take the maximum of the number - // that would fit without a differently-sized lead item, and with one. We - // do this so that if the size of the lead item changes without a scroll - // event to trigger redrawing the list, we won't end up with empty space. - var clientHeight = this.clientHeight; - return this.autoExpands_ ? this.dataModel.length : Math.min( - this.dataModel.length - firstIndex, - Math.max( - Math.ceil(clientHeight / itemHeight) + 1, - this.countItemsInRange_(firstIndex, scrollTop + clientHeight))); - }, - - /** - * Adds items to the list and {@code newCachedItems}. - * @param {number} firstIndex The index of first item, inclusively. - * @param {number} lastIndex The index of last item, exclusively. - * @param {Object<string, ListItem>} cachedItems Old items cache. - * @param {Object<string, ListItem>} newCachedItems New items cache. - */ - addItems: function(firstIndex, lastIndex, cachedItems, newCachedItems) { - var listItem; - var dataModel = this.dataModel; - - window.l = this; - for (var y = firstIndex; y < lastIndex; y++) { - var dataItem = dataModel.item(y); - listItem = cachedItems[y] || this.createItem(dataItem); - listItem.listIndex = y; - this.appendChild(listItem); - newCachedItems[y] = listItem; - } - }, - - /** - * Returns the height of after filler in the list. - * @param {number} lastIndex The index of item past the last in viewport. - * @param {number} itemHeight The height of the item. - * @return {number} The height of after filler. - */ - getAfterFillerHeight: function(lastIndex, itemHeight) { - return (this.dataModel.length - lastIndex) * itemHeight; - }, - - /** - * Redraws the viewport. - */ - redraw: function() { - if (this.batchCount_ != 0) - return; - - var dataModel = this.dataModel; - if (!dataModel) { - this.textContent = ''; - return; - } - - var scrollTop = this.scrollTop; - var clientHeight = this.clientHeight; - - var itemHeight = this.getItemHeight_(); - - // We cache the list items since creating the DOM nodes is the most - // expensive part of redrawing. - var cachedItems = this.cachedItems_ || {}; - var newCachedItems = {}; - - var desiredScrollHeight = this.getHeightsForIndex_(dataModel.length).top; - - var autoExpands = this.autoExpands_; - var firstIndex = autoExpands ? 0 : this.getIndexForListOffset_(scrollTop); - var itemsInViewPort = this.getItemsInViewPort(itemHeight, firstIndex, - scrollTop); - var lastIndex = firstIndex + itemsInViewPort; - - this.textContent = ''; - - this.beforeFiller_.style.height = - this.getHeightsForIndex_(firstIndex).top + 'px'; - this.appendChild(this.beforeFiller_); - - var sm = this.selectionModel; - var leadIndex = sm.leadIndex; - - this.addItems(firstIndex, lastIndex, cachedItems, newCachedItems); - - var afterFillerHeight = this.getAfterFillerHeight(lastIndex, itemHeight); - if (leadIndex >= lastIndex) - afterFillerHeight += this.leadItemHeight - itemHeight; - this.afterFiller_.style.height = afterFillerHeight + 'px'; - this.appendChild(this.afterFiller_); - - // We don't set the lead or selected properties until after adding all - // items, in case they force relayout in response to these events. - var listItem = null; - if (newCachedItems[leadIndex]) - newCachedItems[leadIndex].lead = true; - for (var y = firstIndex; y < lastIndex; y++) { - if (sm.getIndexSelected(y)) - newCachedItems[y].selected = true; - else if (y != leadIndex) - listItem = newCachedItems[y]; - } - - this.firstIndex_ = firstIndex; - this.lastIndex_ = lastIndex; - - this.cachedItems_ = newCachedItems; - - // Measure again in case the item height has changed due to a page zoom. - // - // The measure above is only done the first time but this measure is done - // after every redraw. It is done in a timeout so it will not trigger - // a reflow (which made the redraw speed 3 times slower on my system). - // By using a timeout the measuring will happen later when there is no - // need for a reflow. - if (listItem) { - var list = this; - window.setTimeout(function() { - if (listItem.parentNode == list) { - list.measured_ = measureItem(list, listItem); - } - }); - } - }, - - /** - * Invalidates list by removing cached items. - */ - invalidate: function() { - this.cachedItems_ = {}; - }, - - /** - * Redraws a single item. - * @param {number} index The row index to redraw. - */ - redrawItem: function(index) { - if (index >= this.firstIndex_ && index < this.lastIndex_) { - delete this.cachedItems_[index]; - this.redraw(); - } - }, - - /** - * Called when a list item is activated, currently only by a double click - * event. - * @param {number} index The index of the activated item. - */ - activateItemAtIndex: function(index) { - }, - }; - - cr.defineProperty(List, 'disabled', cr.PropertyKind.BOOL_ATTR); - - /** - * Whether the list or one of its descendents has focus. This is necessary - * because list items can contain controls that can be focused, and for some - * purposes (e.g., styling), the list can still be conceptually focused at - * that point even though it doesn't actually have the page focus. - */ - cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); - - return { - List: List - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_item.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_item.js deleted file mode 100644 index 68431bc..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_item.js +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright (c) 2011 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. - -cr.define('cr.ui', function() { - - /** - * Creates a new list item element. - * @param {string} opt_label The text label for the item. - * @constructor - * @extends {HTMLLIElement} - */ - var ListItem = cr.ui.define('li'); - - ListItem.prototype = { - __proto__: HTMLLIElement.prototype, - - /** - * Plain text label. - * @type {string} - */ - get label() { - return this.textContent; - }, - set label(label) { - this.textContent = label; - }, - - /** - * This item's index in the containing list. - * @type {number} - */ - listIndex_: -1, - - /** - * Called when an element is decorated as a list item. - */ - decorate: function() { - this.setAttribute('role', 'listitem'); - }, - - /** - * Called when the selection state of this element changes. - */ - selectionChanged: function() { - }, - }; - - /** - * Whether the item is selected. Setting this does not update the underlying - * selection model. This is only used for display purpose. - * @type {boolean} - */ - cr.defineProperty(ListItem, 'selected', cr.PropertyKind.BOOL_ATTR, - function() { - this.selectionChanged(); - }); - - /** - * Whether the item is the lead in a selection. Setting this does not update - * the underlying selection model. This is only used for display purpose. - * @type {boolean} - */ - cr.defineProperty(ListItem, 'lead', cr.PropertyKind.BOOL_ATTR); - - /** - * This item's index in the containing list. - * @type {number} - */ - cr.defineProperty(ListItem, 'listIndex'); - - return { - ListItem: ListItem - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_selection_controller.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_selection_controller.js deleted file mode 100644 index 74a8a24..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_selection_controller.js +++ /dev/null
@@ -1,289 +0,0 @@ -// Copyright (c) 2010 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. - -cr.define('cr.ui', function() { - /** - * Creates a selection controller that is to be used with lists. This is - * implemented for vertical lists but changing the behavior for horizontal - * lists or icon views is a matter of overriding {@code getIndexBefore}, - * {@code getIndexAfter}, {@code getIndexAbove} as well as - * {@code getIndexBelow}. - * - * @param {cr.ui.ListSelectionModel} selectionModel The selection model to - * interact with. - * - * @constructor - * @extends {!cr.EventTarget} - */ - function ListSelectionController(selectionModel) { - this.selectionModel_ = selectionModel; - } - - ListSelectionController.prototype = { - - /** - * The selection model we are interacting with. - * @type {cr.ui.ListSelectionModel} - */ - get selectionModel() { - return this.selectionModel_; - }, - - /** - * Returns the index below (y axis) the given element. - * @param {number} index The index to get the index below. - * @return {number} The index below or -1 if not found. - */ - getIndexBelow: function(index) { - if (index == this.getLastIndex()) - return -1; - return index + 1; - }, - - /** - * Returns the index above (y axis) the given element. - * @param {number} index The index to get the index above. - * @return {number} The index below or -1 if not found. - */ - getIndexAbove: function(index) { - return index - 1; - }, - - /** - * Returns the index before (x axis) the given element. This returns -1 - * by default but override this for icon view and horizontal selection - * models. - * - * @param {number} index The index to get the index before. - * @return {number} The index before or -1 if not found. - */ - getIndexBefore: function(index) { - return -1; - }, - - /** - * Returns the index after (x axis) the given element. This returns -1 - * by default but override this for icon view and horizontal selection - * models. - * - * @param {number} index The index to get the index after. - * @return {number} The index after or -1 if not found. - */ - getIndexAfter: function(index) { - return -1; - }, - - /** - * Returns the next list index. This is the next logical and should not - * depend on any kind of layout of the list. - * @param {number} index The index to get the next index for. - * @return {number} The next index or -1 if not found. - */ - getNextIndex: function(index) { - if (index == this.getLastIndex()) - return -1; - return index + 1; - }, - - /** - * Returns the prevous list index. This is the previous logical and should - * not depend on any kind of layout of the list. - * @param {number} index The index to get the previous index for. - * @return {number} The previous index or -1 if not found. - */ - getPreviousIndex: function(index) { - return index - 1; - }, - - /** - * @return {number} The first index. - */ - getFirstIndex: function() { - return 0; - }, - - /** - * @return {number} The last index. - */ - getLastIndex: function() { - return this.selectionModel.length - 1; - }, - - /** - * Called by the view when the user does a mousedown or mouseup on the list. - * @param {!Event} e The browser mousedown event. - * @param {number} index The index that was under the mouse pointer, -1 if - * none. - */ - handleMouseDownUp: function(e, index) { - var sm = this.selectionModel; - var anchorIndex = sm.anchorIndex; - var isDown = e.type == 'mousedown'; - - sm.beginChange(); - - if (index == -1) { - // On Mac we always clear the selection if the user clicks a blank area. - // On Windows, we only clear the selection if neither Shift nor Ctrl are - // pressed. - if (cr.isMac) { - sm.leadIndex = sm.anchorIndex = -1; - if (sm.multiple) - sm.unselectAll(); - } else if (!isDown && !e.shiftKey && !e.ctrlKey) - // Keep anchor and lead indexes. Note that this is intentionally - // different than on the Mac. - if (sm.multiple) - sm.unselectAll(); - } else { - if (sm.multiple && (cr.isMac ? e.metaKey : - (e.ctrlKey && !e.shiftKey))) { - // Selection is handled at mouseUp on windows/linux, mouseDown on mac. - if (cr.isMac? isDown : !isDown) { - // Toggle the current one and make it anchor index. - sm.setIndexSelected(index, !sm.getIndexSelected(index)); - sm.leadIndex = index; - sm.anchorIndex = index; - } - } else if (e.shiftKey && anchorIndex != -1 && anchorIndex != index) { - // Shift is done in mousedown. - if (isDown) { - sm.unselectAll(); - sm.leadIndex = index; - if (sm.multiple) - sm.selectRange(anchorIndex, index); - else - sm.setIndexSelected(index, true); - } - } else { - // Right click for a context menu needs to not clear the selection. - var isRightClick = e.button == 2; - - // If the index is selected this is handled in mouseup. - var indexSelected = sm.getIndexSelected(index); - if ((indexSelected && !isDown || !indexSelected && isDown) && - !(indexSelected && isRightClick)) { - sm.unselectAll(); - sm.setIndexSelected(index, true); - sm.leadIndex = index; - sm.anchorIndex = index; - } - } - } - - sm.endChange(); - }, - - /** - * Called by the view when it receives a keydown event. - * @param {Event} e The keydown event. - */ - handleKeyDown: function(e) { - const SPACE_KEY_CODE = 32; - var tagName = e.target.tagName; - // If focus is in an input field of some kind, only handle navigation keys - // that aren't likely to conflict with input interaction (e.g., text - // editing, or changing the value of a checkbox or select). - if (tagName == 'INPUT') { - var inputType = e.target.type; - // Just protect space (for toggling) for checkbox and radio. - if (inputType == 'checkbox' || inputType == 'radio') { - if (e.keyCode == SPACE_KEY_CODE) - return; - // Protect all but the most basic navigation commands in anything else. - } else if (e.key != 'ArrowUp' && e.key != 'ArrowDown') { - return; - } - } - // Similarly, don't interfere with select element handling. - if (tagName == 'SELECT') - return; - - var sm = this.selectionModel; - var newIndex = -1; - var leadIndex = sm.leadIndex; - var prevent = true; - - // Ctrl/Meta+A - if (sm.multiple && e.keyCode == 65 && - (cr.isMac && e.metaKey || !cr.isMac && e.ctrlKey)) { - sm.selectAll(); - e.preventDefault(); - return; - } - - // Space - if (e.keyCode == SPACE_KEY_CODE) { - if (leadIndex != -1) { - var selected = sm.getIndexSelected(leadIndex); - if (e.ctrlKey || !selected) { - sm.setIndexSelected(leadIndex, !selected || !sm.multiple); - return; - } - } - } - - switch (e.key) { - case 'Home': - newIndex = this.getFirstIndex(); - break; - case 'End': - newIndex = this.getLastIndex(); - break; - case 'ArrowUp': - newIndex = leadIndex == -1 ? - this.getLastIndex() : this.getIndexAbove(leadIndex); - break; - case 'ArrowDown': - newIndex = leadIndex == -1 ? - this.getFirstIndex() : this.getIndexBelow(leadIndex); - break; - case 'ArrrowLeft': - newIndex = leadIndex == -1 ? - this.getLastIndex() : this.getIndexBefore(leadIndex); - break; - case 'ArrowRight': - newIndex = leadIndex == -1 ? - this.getFirstIndex() : this.getIndexAfter(leadIndex); - break; - default: - prevent = false; - } - - if (newIndex != -1) { - sm.beginChange(); - - sm.leadIndex = newIndex; - if (e.shiftKey) { - var anchorIndex = sm.anchorIndex; - if (sm.multiple) - sm.unselectAll(); - if (anchorIndex == -1) { - sm.setIndexSelected(newIndex, true); - sm.anchorIndex = newIndex; - } else { - sm.selectRange(anchorIndex, newIndex); - } - } else if (e.ctrlKey && !cr.isMac) { - // Setting the lead index is done above. - // Mac does not allow you to change the lead. - } else { - if (sm.multiple) - sm.unselectAll(); - sm.setIndexSelected(newIndex, true); - sm.anchorIndex = newIndex; - } - - sm.endChange(); - - if (prevent) - e.preventDefault(); - } - } - }; - - return { - ListSelectionController: ListSelectionController - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_selection_model.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_selection_model.js deleted file mode 100644 index 8dba53a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_selection_model.js +++ /dev/null
@@ -1,274 +0,0 @@ -// Copyright (c) 2011 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. - -cr.define('cr.ui', function() { - /** @const */ var EventTarget = cr.EventTarget; - - /** - * Creates a new selection model that is to be used with lists. - * - * @param {number=} opt_length The number items in the selection. - * - * @constructor - * @extends {!cr.EventTarget} - */ - function ListSelectionModel(opt_length) { - this.length_ = opt_length || 0; - // Even though selectedIndexes_ is really a map we use an array here to get - // iteration in the order of the indexes. - this.selectedIndexes_ = []; - } - - ListSelectionModel.prototype = { - __proto__: EventTarget.prototype, - - /** - * The number of items in the model. - * @type {number} - */ - get length() { - return this.length_; - }, - - /** - * @type {!Array} The selected indexes. - */ - get selectedIndexes() { - return Object.keys(this.selectedIndexes_).map(Number); - }, - set selectedIndexes(selectedIndexes) { - this.beginChange(); - this.unselectAll(); - for (var i = 0; i < selectedIndexes.length; i++) { - this.setIndexSelected(selectedIndexes[i], true); - } - if (selectedIndexes.length) { - this.leadIndex = this.anchorIndex = selectedIndexes[0]; - } else { - this.leadIndex = this.anchorIndex = -1; - } - this.endChange(); - }, - - /** - * Convenience getter which returns the first selected index. - * @type {number} - */ - get selectedIndex() { - for (var i in this.selectedIndexes_) { - return Number(i); - } - return -1; - }, - set selectedIndex(selectedIndex) { - this.beginChange(); - this.unselectAll(); - if (selectedIndex != -1) { - this.selectedIndexes = [selectedIndex]; - } else { - this.leadIndex = this.anchorIndex = -1; - } - this.endChange(); - }, - - /** - * Selects a range of indexes, starting with {@code start} and ends with - * {@code end}. - * @param {number} start The first index to select. - * @param {number} end The last index to select. - */ - selectRange: function(start, end) { - // Swap if starts comes after end. - if (start > end) { - var tmp = start; - start = end; - end = tmp; - } - - this.beginChange(); - - for (var index = start; index != end; index++) { - this.setIndexSelected(index, true); - } - this.setIndexSelected(end, true); - - this.endChange(); - }, - - /** - * Selects all indexes. - */ - selectAll: function() { - this.selectRange(0, this.length - 1); - }, - - /** - * Clears the selection - */ - clear: function() { - this.beginChange(); - this.length_ = 0; - this.anchorIndex = this.leadIndex = -1; - this.unselectAll(); - this.endChange(); - }, - - /** - * Unselects all selected items. - */ - unselectAll: function() { - this.beginChange(); - for (var i in this.selectedIndexes_) { - this.setIndexSelected(i, false); - } - this.endChange(); - }, - - /** - * Sets the selected state for an index. - * @param {number} index The index to set the selected state for. - * @param {boolean} b Whether to select the index or not. - */ - setIndexSelected: function(index, b) { - var oldSelected = index in this.selectedIndexes_; - if (oldSelected == b) - return; - - if (b) - this.selectedIndexes_[index] = true; - else - delete this.selectedIndexes_[index]; - - this.beginChange(); - - // Changing back? - if (index in this.changedIndexes_ && this.changedIndexes_[index] == !b) { - delete this.changedIndexes_[index]; - } else { - this.changedIndexes_[index] = b; - } - - // End change dispatches an event which in turn may update the view. - this.endChange(); - }, - - /** - * Whether a given index is selected or not. - * @param {number} index The index to check. - * @return {boolean} Whether an index is selected. - */ - getIndexSelected: function(index) { - return index in this.selectedIndexes_; - }, - - /** - * This is used to begin batching changes. Call {@code endChange} when you - * are done making changes. - */ - beginChange: function() { - if (!this.changeCount_) { - this.changeCount_ = 0; - this.changedIndexes_ = {}; - } - this.changeCount_++; - }, - - /** - * Call this after changes are done and it will dispatch a change event if - * any changes were actually done. - */ - endChange: function() { - this.changeCount_--; - if (!this.changeCount_) { - var indexes = Object.keys(this.changedIndexes_); - if (indexes.length) { - var e = new Event('change'); - e.changes = indexes.map(function(index) { - return { - index: index, - selected: this.changedIndexes_[index] - }; - }, this); - this.dispatchEvent(e); - } - this.changedIndexes_ = {}; - } - }, - - leadIndex_: -1, - - /** - * The leadIndex is used with multiple selection and it is the index that - * the user is moving using the arrow keys. - * @type {number} - */ - get leadIndex() { - return this.leadIndex_; - }, - set leadIndex(leadIndex) { - var li = Math.max(-1, Math.min(this.length_ - 1, leadIndex)); - if (li != this.leadIndex_) { - var oldLeadIndex = this.leadIndex_; - this.leadIndex_ = li; - cr.dispatchPropertyChange(this, 'leadIndex', li, oldLeadIndex); - } - }, - - anchorIndex_: -1, - - /** - * The anchorIndex is used with multiple selection. - * @type {number} - */ - get anchorIndex() { - return this.anchorIndex_; - }, - set anchorIndex(anchorIndex) { - var ai = Math.max(-1, Math.min(this.length_ - 1, anchorIndex)); - if (ai != this.anchorIndex_) { - var oldAnchorIndex = this.anchorIndex_; - this.anchorIndex_ = ai; - cr.dispatchPropertyChange(this, 'anchorIndex', ai, oldAnchorIndex); - } - }, - - /** - * Whether the selection model supports multiple selected items. - * @type {boolean} - */ - get multiple() { - return true; - }, - - /** - * Adjusts the selection after reordering of items in the table. - * @param {!Array<number>} permutation The reordering permutation. - */ - adjustToReordering: function(permutation) { - var oldLeadIndex = this.leadIndex; - - var oldSelectedIndexes = this.selectedIndexes; - this.selectedIndexes = oldSelectedIndexes.map(function(oldIndex) { - return permutation[oldIndex]; - }).filter(function(index) { - return index != -1; - }); - - if (oldLeadIndex != -1) - this.leadIndex = permutation[oldLeadIndex]; - }, - - /** - * Adjusts selection model length. - * @param {number} length New selection model length. - */ - adjustLength: function(length) { - this.length_ = length; - } - }; - - return { - ListSelectionModel: ListSelectionModel - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_single_selection_model.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_single_selection_model.js deleted file mode 100644 index 8c5ef786..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/cr/ui/list_single_selection_model.js +++ /dev/null
@@ -1,220 +0,0 @@ -// Copyright (c) 2011 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. - -cr.define('cr.ui', function() { - /** @const */ var EventTarget = cr.EventTarget; - - /** - * Creates a new selection model that is to be used with lists. This only - * allows a single index to be selected. - * - * @param {number=} opt_length The number items in the selection. - * - * @constructor - * @extends {!cr.EventTarget} - */ - function ListSingleSelectionModel(opt_length) { - this.length_ = opt_length || 0; - this.selectedIndex = -1; - } - - ListSingleSelectionModel.prototype = { - __proto__: EventTarget.prototype, - - /** - * The number of items in the model. - * @type {number} - */ - get length() { - return this.length_; - }, - - /** - * @type {!Array} The selected indexes. - */ - get selectedIndexes() { - var i = this.selectedIndex; - return i != -1 ? [this.selectedIndex] : []; - }, - - /** - * Convenience getter which returns the first selected index. - * @type {number} - */ - get selectedIndex() { - return this.selectedIndex_; - }, - set selectedIndex(selectedIndex) { - var oldSelectedIndex = this.selectedIndex; - var i = Math.max(-1, Math.min(this.length_ - 1, selectedIndex)); - - if (i != oldSelectedIndex) { - this.beginChange(); - this.selectedIndex_ = i - this.endChange(); - } - }, - - /** - * Selects a range of indexes, starting with {@code start} and ends with - * {@code end}. - * @param {number} start The first index to select. - * @param {number} end The last index to select. - */ - selectRange: function(start, end) { - // Only select first index. - this.selectedIndex = Math.min(start, end); - }, - - /** - * Selects all indexes. - */ - selectAll: function() { - // Select all is not allowed on a single selection model - }, - - /** - * Clears the selection - */ - clear: function() { - this.beginChange(); - this.length_ = 0; - this.selectedIndex = this.anchorIndex = this.leadIndex = -1; - this.endChange(); - }, - - /** - * Unselects all selected items. - */ - unselectAll: function() { - this.selectedIndex = -1; - }, - - /** - * Sets the selected state for an index. - * @param {number} index The index to set the selected state for. - * @param {boolean} b Whether to select the index or not. - */ - setIndexSelected: function(index, b) { - // Only allow selection - var oldSelected = index == this.selectedIndex_; - if (oldSelected == b) - return; - - if (b) - this.selectedIndex = index; - else if (index == this.selectedIndex_) - this.selectedIndex = -1; - }, - - /** - * Whether a given index is selected or not. - * @param {number} index The index to check. - * @return {boolean} Whether an index is selected. - */ - getIndexSelected: function(index) { - return index == this.selectedIndex_; - }, - - /** - * This is used to begin batching changes. Call {@code endChange} when you - * are done making changes. - */ - beginChange: function() { - if (!this.changeCount_) { - this.changeCount_ = 0; - this.selectedIndexBefore_ = this.selectedIndex_; - } - this.changeCount_++; - }, - - /** - * Call this after changes are done and it will dispatch a change event if - * any changes were actually done. - */ - endChange: function() { - this.changeCount_--; - if (!this.changeCount_) { - if (this.selectedIndexBefore_ != this.selectedIndex_) { - var e = new Event('change'); - var indexes = [this.selectedIndexBefore_, this.selectedIndex_]; - e.changes = indexes.filter(function(index) { - return index != -1; - }).map(function(index) { - return { - index: index, - selected: index == this.selectedIndex_ - }; - }, this); - this.dispatchEvent(e); - } - } - }, - - leadIndex_: -1, - - /** - * The leadIndex is used with multiple selection and it is the index that - * the user is moving using the arrow keys. - * @type {number} - */ - get leadIndex() { - return this.leadIndex_; - }, - set leadIndex(leadIndex) { - var li = Math.max(-1, Math.min(this.length_ - 1, leadIndex)); - if (li != this.leadIndex_) { - var oldLeadIndex = this.leadIndex_; - this.leadIndex_ = li; - cr.dispatchPropertyChange(this, 'leadIndex', li, oldLeadIndex); - cr.dispatchPropertyChange(this, 'anchorIndex', li, oldLeadIndex); - } - }, - - /** - * The anchorIndex is used with multiple selection. - * @type {number} - */ - get anchorIndex() { - return this.leadIndex; - }, - set anchorIndex(anchorIndex) { - this.leadIndex = anchorIndex; - }, - - /** - * Whether the selection model supports multiple selected items. - * @type {boolean} - */ - get multiple() { - return false; - }, - - /** - * Adjusts the selection after reordering of items in the table. - * @param {!Array<number>} permutation The reordering permutation. - */ - adjustToReordering: function(permutation) { - if (this.leadIndex != -1) - this.leadIndex = permutation[this.leadIndex]; - - var oldSelectedIndex = this.selectedIndex; - if (oldSelectedIndex != -1) { - this.selectedIndex = permutation[oldSelectedIndex]; - } - }, - - /** - * Adjusts selection model length. - * @param {number} length New selection model length. - */ - adjustLength: function(length) { - this.length_ = length; - } - }; - - return { - ListSingleSelectionModel: ListSingleSelectionModel - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/util.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/util.js deleted file mode 100644 index 1efbf19..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/domui/js/util.js +++ /dev/null
@@ -1,151 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * The global object. - * @type {!Object} - */ -const global = this; - -/** - * Alias for document.getElementById. - * @param {string} id The ID of the element to find. - * @return {HTMLElement} The found element or null if not found. - */ -function $(id) { - return document.getElementById(id); -} - -/** - * Calls chrome.send with a callback and restores the original afterwards. - * @param {string} name The name of the message to send. - * @param {!Array} params The parameters to send. - * @param {string} callbackName The name of the function that the backend calls. - * @param {!Function} The function to call. - */ -function chromeSend(name, params, callbackName, callback) { - var old = global[callbackName]; - global[callbackName] = function() { - // restore - global[callbackName] = old; - - var args = Array.prototype.slice.call(arguments); - return callback.apply(global, args); - }; - chrome.send(name, params); -} - -/** - * Generates a CSS url string. - * @param {string} s The URL to generate the CSS url for. - * @return {string} The CSS url string. - */ -function url(s) { - // http://www.w3.org/TR/css3-values/#uris - // Parentheses, commas, whitespace characters, single quotes (') and double - // quotes (") appearing in a URI must be escaped with a backslash - var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1'); - // WebKit has a bug when it comes to URLs that end with \ - // https://bugs.webkit.org/show_bug.cgi?id=28885 - if (/\\\\$/.test(s2)) { - // Add a space to work around the WebKit bug. - s2 += ' '; - } - return 'url("' + s2 + '")'; -} - -/** - * Parses query parameters from Location. - * @param {string} s The URL to generate the CSS url for. - * @return {object} Dictionary containing name value pairs for URL - */ -function parseQueryParams(location) { - var params = {}; - var query = unescape(location.search.substring(1)); - var vars = query.split("&"); - for (var i=0; i < vars.length; i++) { - var pair = vars[i].split("="); - params[pair[0]] = pair[1]; - } - return params; -} - -function findAncestorByClass(el, className) { - return findAncestor(el, function(el) { - if (el.classList) - return el.classList.contains(className); - return null; - }); -} - -/** - * Return the first ancestor for which the {@code predicate} returns true. - * @param {Node} node The node to check. - * @param {function(Node) : boolean} predicate The function that tests the - * nodes. - * @return {Node} The found ancestor or null if not found. - */ -function findAncestor(node, predicate) { - var last = false; - while (node != null && !(last = predicate(node))) { - node = node.parentNode; - } - return last ? node : null; -} - -function swapDomNodes(a, b) { - var afterA = a.nextSibling; - if (afterA == b) { - swapDomNodes(b, a); - return; - } - var aParent = a.parentNode; - b.parentNode.replaceChild(a, b); - aParent.insertBefore(b, afterA); -} - -/** - * Disables text selection and dragging. - */ -function disableTextSelectAndDrag() { - // Disable text selection. - document.onselectstart = function(e) { - e.preventDefault(); - } - - // Disable dragging. - document.ondragstart = function(e) { - e.preventDefault(); - } -} - -// Handle click on a link. If the link points to a chrome: or file: url, then -// call into the browser to do the navigation. -document.addEventListener('click', function(e) { - // Allow preventDefault to work. - if (!e.returnValue) - return; - - var el = e.target; - if (el.nodeType == Node.ELEMENT_NODE && - el.webkitMatchesSelector('A, A *')) { - while (el.tagName != 'A') { - el = el.parentElement; - } - - if ((el.protocol == 'file:' || el.protocol == 'about:') && - (e.button == 0 || e.button == 1)) { - chrome.send('navigateToUrl', [ - el.href, - el.target, - e.button, - e.altKey, - e.ctrlKey, - e.metaKey, - e.shiftKey - ]); - e.preventDefault(); - } - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/chrome_stubs.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/chrome_stubs.js deleted file mode 100644 index 63e61b2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/chrome_stubs.js +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Stubs for Chrome extension APIs that aren't available to - * regular web pages, to allow tests to run. - */ - -chrome = chrome || {}; -chrome.extension = chrome.extension || {}; -chrome.contentSettings = chrome.contentSettings || {}; - -var _rules = {}; -chrome.contentSettings.plugins = { - 'set': function(details, callback) { - assertObjectEquals({'id': 'myplugin'}, details.resourceIdentifier); - var pattern = details.primaryPattern; - var setting = details.setting; - if (pattern == '__invalid_pattern') { - chrome.runtime.lastError = {'message': 'Invalid pattern'}; - } else if (setting == '__invalid_setting') { - throw Error('Invalid setting'); - } else { - chrome.runtime.lastError = undefined; - _rules[pattern] = setting; - } - callback(); - }, - - 'clear': function(details, callback) { - assertObjectEquals({}, details); - _rules = {}; - callback(); - } -}; - -chrome.i18n = chrome.i18n || {}; -chrome.i18n.getMessage = function(id) { - var messages = { - 'patternColumnHeader': 'Hostname Pattern', - 'settingColumnHeader': 'Behavior', - 'allowRule': 'Allow', - 'blockRule': 'Block', - 'addNewPattern': 'Add a new hostname pattern', - }; - return messages[id]; -} - -/** - * Creates a new Settings object with a set of rules for a dummy plugin. - * Because we provide stub implementations for the Chrome contentSettings - * extension API, we know that the methods will execute immediately instead of - * asynchronously. - * @param {!Object} rules A map from content settings pattern to setting. - * @return {!pluginSettings.Settings} A newly created Settings object with the - * passed in set of rules. - */ -function createSettings(rules) { - var settings = new pluginSettings.Settings('myplugin'); - if (rules) { - for (var pattern in rules) { - settings.set(pattern, rules[pattern], function() {}); - } - } - return settings; -} -
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/main.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/main.js deleted file mode 100644 index c731ff737..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/main.js +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Main entry point that creates a new plugin list on document - * load. - */ - -document.addEventListener('DOMContentLoaded', function() { - chrome.contentSettings.plugins.getResourceIdentifiers(function(r) { - if (chrome.runtime.lastError) { - $('error').textContent = - 'Error: ' + chrome.runtime.lastError.message; - return; - } - var pluginList = $('plugin-list'); - pluginSettings.ui.PluginList.decorate(pluginList); - pluginList.dataModel = new cr.ui.ArrayDataModel(r); - }); -}); -
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_list.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_list.js deleted file mode 100644 index a0dff4c7..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_list.js +++ /dev/null
@@ -1,297 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Defines a list of plugins that shows for each plugin a list - * of content setting rules. - */ - -cr.define('pluginSettings.ui', function() { - const List = cr.ui.List; - const ListItem = cr.ui.ListItem; - const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel; - - /** - * CSS classes used by this class. - * @enum {string} - */ - const CSSClass = { - - /** - * Hides an element. - */ - HIDDEN: 'hidden', - - /** - * A plugin list. - */ - PLUGIN_LIST: 'plugin-list', - - /** - * Set on a plugin list entry to show details about the plugin. - */ - PLUGIN_SHOW_DETAILS: 'plugin-show-details', - - /** - * The plugin name. - */ - PLUGIN_NAME: 'plugin-name', - - /** - * The number of rules set for a plugin. - */ - NUM_RULES: 'num-rules', - - /** - * The element containing details about a plugin. - */ - PLUGIN_DETAILS: 'plugin-details', - - /** - * The element containing the column headers for the list of rules. - */ - COLUMN_HEADERS: 'column-headers', - - /** - * The header for the pattern column. - */ - PATTERN_COLUMN_HEADER: 'pattern-column-header', - - /** - * The header for the setting column. - */ - SETTING_COLUMN_HEADER: 'setting-column-header', - }; - - /** - * Returns the item's height, like offsetHeight but such that it works better - * when the page is zoomed. See the similar calculation in @{code cr.ui.List}. - * This version also accounts for the animation done in this file. - * @param {!Element} item The item to get the height of. - * @return {number} The height of the item, calculated with zooming in mind. - */ - function getItemHeight(item) { - var height = item.style.height; - // Use the fixed animation target height if set, in case the element is - // currently being animated and we'd get an intermediate height below. - if (height && height.substr(-2) == 'px') { - return parseInt(height.substr(0, height.length - 2)); - } - return item.getBoundingClientRect().height; - } - - /** - * Creates a new plugin list item element. - * @param {!PluginList} list The plugin list containing this item. - * @param {!Object} info Information about the plugin. - * @constructor - * @extends {cr.ui.ListItem} - */ - function PluginListItem(list, info) { - var el = cr.doc.createElement('li'); - - /** - * The plugin list containing this item. - * @type {!PluginList} - * @private - */ - el.list_ = list; - - /** - * Information about the plugin. - * @type {!Object} - * @private - */ - el.info_ = info; - - el.__proto__ = PluginListItem.prototype; - el.decorate(); - return el; - } - - PluginListItem.prototype = { - __proto__: ListItem.prototype, - - /** - * The element containing details about the plugin. This is only null in - * the prototype. - * @type {?HTMLDivElement} - * @private - */ - detailsElement_: null, - - /** - * Initializes the element. - */ - decorate: function() { - ListItem.prototype.decorate.call(this); - - var info = this.info_; - - var contentElement = this.ownerDocument.createElement('div'); - - var titleEl = this.ownerDocument.createElement('div'); - var nameEl = this.ownerDocument.createElement('span'); - nameEl.className = CSSClass.PLUGIN_NAME; - nameEl.textContent = info.description; - nameEl.title = info.description; - titleEl.appendChild(nameEl); - this.numRulesEl_ = this.ownerDocument.createElement('span'); - this.numRulesEl_.className = CSSClass.NUM_RULES; - titleEl.appendChild(this.numRulesEl_); - contentElement.appendChild(titleEl); - - this.detailsElement_ = this.ownerDocument.createElement('div'); - this.detailsElement_.classList.add(CSSClass.PLUGIN_DETAILS); - this.detailsElement_.classList.add(CSSClass.HIDDEN); - - var columnHeadersEl = this.ownerDocument.createElement('div'); - columnHeadersEl.className = CSSClass.COLUMN_HEADERS; - var patternColumnEl = this.ownerDocument.createElement('div'); - patternColumnEl.textContent = - chrome.i18n.getMessage('patternColumnHeader'); - patternColumnEl.className = CSSClass.PATTERN_COLUMN_HEADER; - var settingColumnEl = this.ownerDocument.createElement('div'); - settingColumnEl.textContent = - chrome.i18n.getMessage('settingColumnHeader'); - settingColumnEl.className = CSSClass.SETTING_COLUMN_HEADER; - columnHeadersEl.appendChild(patternColumnEl); - columnHeadersEl.appendChild(settingColumnEl); - this.detailsElement_.appendChild(columnHeadersEl); - contentElement.appendChild(this.detailsElement_); - - this.appendChild(contentElement); - - var settings = new pluginSettings.Settings(this.info_.id); - this.updateRulesCount_(settings); - settings.addEventListener( - 'change', - this.updateRulesCount_.bind(this, settings)); - - // Create the rule list asynchronously, to make sure that it is already - // fully integrated in the DOM tree. - window.setTimeout(this.loadRules_.bind(this, settings), 0); - }, - - /** - * Create the list of content setting rules applying to this plugin. - * @param {!pluginSettings.Settings} The settings object storing the content - * setting rules. - * @private - */ - loadRules_: function(settings) { - var rulesEl = this.ownerDocument.createElement('list'); - this.detailsElement_.appendChild(rulesEl); - - pluginSettings.ui.RuleList.decorate(rulesEl); - rulesEl.setPluginSettings(settings); - }, - - /** - * Called when the list of rules changes to update the rule count shown when - * the list is not expanded. - * @param {!pluginSettings.Settings} The settings object storing the content - * setting rules. - * @private - */ - updateRulesCount_: function(settings) { - this.numRulesEl_.textContent = '(' + settings.getAll().length + ' rules)'; - }, - - /** - * Whether this item is expanded or not. - * @type {boolean} - */ - expanded_: false, - /** - * Whether this item is expanded or not. - * @type {boolean} - */ - get expanded() { - return this.expanded_; - }, - set expanded(expanded) { - if (this.expanded_ == expanded) { - return; - } - this.expanded_ = expanded; - if (expanded) { - var oldExpanded = this.list_.expandItem; - this.list_.expandItem = this; - this.detailsElement_.classList.remove(CSSClass.HIDDEN); - if (oldExpanded) { - oldExpanded.expanded = false; - } - this.classList.add(CSSClass.PLUGIN_SHOW_DETAILS); - } else { - if (this.list_.expandItem == this) { - this.list_.leadItemHeight = 0; - this.list_.expandItem = null; - } - this.style.height = ''; - this.detailsElement_.classList.add(CSSClass.HIDDEN); - this.classList.remove(CSSClass.PLUGIN_SHOW_DETAILS); - } - }, - }; - - /** - * Creates a new plugin list. - * @constructor - * @extends {cr.ui.List} - */ - var PluginList = cr.ui.define('list'); - - PluginList.prototype = { - __proto__: List.prototype, - - /** - * Initializes the element. - */ - decorate: function() { - List.prototype.decorate.call(this); - this.classList.add(CSSClass.PLUGIN_LIST); - var sm = new ListSingleSelectionModel(); - sm.addEventListener('change', this.handleSelectionChange_.bind(this)); - this.selectionModel = sm; - this.autoExpands = true; - }, - - /** - * Creates a new plugin list item. - * @param {!Object} info Information about the plugin. - */ - createItem: function(info) { - return new PluginListItem(this, info); - }, - - /** - * Called when the selection changes. - * @param {!Event} ce The change event. - * @private - */ - handleSelectionChange_: function(ce) { - ce.changes.forEach(function(change) { - var listItem = this.getListItemByIndex(change.index); - if (listItem) { - if (!change.selected) { - // TODO(bsmith) explain window timeout (from cookies_list.js) - window.setTimeout(function() { - if (!listItem.selected || !listItem.lead) { - listItem.expanded = false; - } - }, 0); - } else if (listItem.lead) { - listItem.expanded = true; - } - } - }, this); - }, - }; - - return { - PluginList: PluginList, - PluginListItem: PluginListItem, - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_list_test.html b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_list_test.html deleted file mode 100644 index 9fd852a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_list_test.html +++ /dev/null
@@ -1,68 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<style> -#error { - display: none; -} -</style> -<link rel="stylesheet" href="../domui/css/button.css"> -<link rel="stylesheet" href="../domui/css/chrome_shared.css"> -<link rel="stylesheet" href="../domui/css/list.css"> -<link rel="stylesheet" href="../domui/css/select.css"> - -<link rel="stylesheet" href="../options/css/list.css"> - -<link rel="stylesheet" href="../css/plugin_list.css"> -<link rel="stylesheet" href="../css/rule_list.css"> - -<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script> -<script src="../domui/js/cr.js"></script> -<script src="../domui/js/cr/event_target.js"></script> -<script src="../domui/js/cr/ui.js"></script> -<script src="../domui/js/cr/ui/array_data_model.js"></script> -<script src="../domui/js/cr/ui/list_item.js"></script> -<script src="../domui/js/cr/ui/list_selection_controller.js"></script> -<script src="../domui/js/cr/ui/list_selection_model.js"></script> -<script src="../domui/js/cr/ui/list_single_selection_model.js"></script> -<script src="../domui/js/cr/ui/list.js"></script> -<script src="../domui/js/util.js"></script> - -<script src="../options/js/deletable_item_list.js"></script> -<script src="../options/js/inline_editable_list.js"></script> - -<script src="plugin_list.js" type="text/javascript"></script> -<script src="plugin_settings.js" type="text/javascript"></script> -<script src="rule_list.js" type="text/javascript"></script> - -<script> -goog.require('goog.testing.jsunit'); -</script> -<script src="chrome_stubs.js" type="text/javascript"></script> -</head> -<body> -<div id="error"></div> -<script> -function testConstruction() { - var pluginList = document.createElement('list'); - document.body.appendChild(pluginList); - pluginSettings.ui.PluginList.decorate(pluginList); - var plugins = [ - { - 'id': 'myplugin', - 'description': 'My Plugin' - } - ]; - var rules = { - 'http://example.com/*': 'block', - 'http://moose.org/*': 'allow', - }; - createSettings(rules); - pluginList.dataModel = new cr.ui.ArrayDataModel(plugins); - assertEquals('My Plugin', - pluginList.querySelector('.plugin-name').textContent); - assertEquals('(2 rules)', pluginList.querySelector('.num-rules').textContent); -} -</script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_settings.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_settings.js deleted file mode 100644 index 1727356..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_settings.js +++ /dev/null
@@ -1,219 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Defines a class that provides some convenient wrapper methods - * around the Chrome contentSettings extension API. - */ - -cr.define('pluginSettings', function() { - /** @const */ var EventTarget = cr.EventTarget; - - /** - * Creates a new content settings model. - * @param {string} plugin Identifies the plugin for which this object stores - * settings. - * @constructor - * @extends {cr.EventTarget} - */ - function Settings(plugin) { - /** - * Identifies the plugin for which this object stores settings. - * @type {string} - * @private - */ - this.plugin_ = plugin; - } - - Settings.prototype = { - __proto__: cr.EventTarget.prototype, - - /** - * Clears all content settings, and recreates them from local storage. If a - * content setting can't be set (which shouldn't really happen, as it has - * been successfully set previously), it is removed from local storage as - * well. - * @param {function()} callback Called when the content settings have been - * recreated, or on error. - * @private - */ - recreateRules_: function(callback) { - chrome.contentSettings.plugins.clear( - {}, this.didClearRules_.bind(this, callback)); - }, - - /** - * Recreates all content settings from local storage. - * @param {function()} callback Called when the content settings have been - * recreated, or on error. - * @private - */ - didClearRules_: function(callback) { - if (chrome.runtime.lastError) { - console.error('Error clearing rules'); - callback(); - return; - } - var length = window.localStorage.length; - if (length == 0) { - cr.dispatchSimpleEvent(settings, 'change'); - callback(); - return; - } - var counter = { - 'value': length - }; - for (var i = 0; i < length; i++) { - var key = window.localStorage.key(i); - var keyArray = JSON.parse(key); - var plugin = keyArray[0]; - var pattern = keyArray[1]; - var setting = window.localStorage.getItem(key) - chrome.contentSettings.plugins.set( - { - 'primaryPattern': pattern, - 'resourceIdentifier': {'id': plugin}, - 'setting': setting, - }, - this.didSetContentSetting_.bind( - this, key, setting, counter, callback)); - } - }, - - /** - * Checks if we're finished with recreating content settings and calls the - * passed in callback if so. - * @param {string} key The local storage key under which the content - * setting was stored. - * @param {string} value The content setting value in local storage. - * @param {{value:number}} counter Contains the number of callbacks still - * outstanding. - * @param {function()} callback Called when the content settings have been - * recreated, or on error. - * @private - */ - didSetContentSetting_: function(plugin, pattern, key, counter, callback) { - if (chrome.runtime.lastError) { - console.error( - 'Error restoring [' + key + ': ' + value + ']: ' + - chrome.runtime.lastError.message); - window.localStorage.removeItem(key); - } - counter.value--; - if (counter.value == 0) { - cr.dispatchSimpleEvent(this, 'change'); - callback(); - } - }, - - /** - * Creates a content setting rule and calls the passed in callback with the - * result. - * @param {string} pattern The content setting pattern for the rule. - * @param {string} setting The setting for the rule. - * @param {function(?string)} callback Called when the content settings - * have been updated, or on error. - */ - set: function(pattern, setting, callback) { - var plugin = this.plugin_; - var settings = this; - chrome.contentSettings.plugins.set({ - 'primaryPattern': pattern, - 'resourceIdentifier': { 'id': plugin }, - 'setting': setting, - }, function() { - if (chrome.runtime.lastError) { - callback(chrome.runtime.lastError.message); - } else { - window.localStorage.setItem(JSON.stringify([plugin, pattern]), - setting); - cr.dispatchSimpleEvent(settings, 'change'); - callback(); - } - }); - }, - - /** - * Removes the content setting rule with a given pattern, and calls the - * passed in callback afterwards. - * @param {string} pattern The content setting pattern for the rule. - * @param {function()} callback Called when the content settings have - * been updated. - */ - clear: function(pattern, callback) { - window.localStorage.removeItem( - JSON.stringify([this.plugin_, pattern])); - this.recreateRules_(callback); - }, - - /** - * Updates the content setting rule with a given pattern to a new pattern - * and setting and calls the passed in callback with the result. - * @param {string} oldPattern The old content setting pattern for the rule. - * @param {string} newPattern The new content setting pattern for the rule. - * @param {string} setting The setting for the rule. - * @param {function(?string)} callback Called when the content settings - * have been updated, or on error. - */ - update: function(oldPattern, newPattern, setting, callback) { - if (oldPattern == newPattern) { - // Avoid recreating all rules if only the setting changed. - this.set(newPattern, setting, callback); - return; - } - var oldSetting = this.get(oldPattern); - var settings = this; - // Remove the old rule. - this.clear(oldPattern, function() { - // Try to set the new rule. - settings.set(newPattern, setting, function(error) { - if (error) { - // If setting the new rule failed, restore the old rule. - settings.set(oldPattern, oldSetting, function(restoreError) { - if (restoreError) { - console.error('Error restoring [' + settings.plugin_ + ', ' + - oldPattern + oldSetting + ']: ' + restoreError); - } - callback(error); - }); - } else { - callback(); - } - }); - }); - }, - - /** - * Returns the content setting for a given pattern. - * @param {string} pattern The content setting pattern for the rule. - * @return {string} The setting for the rule. - */ - get: function(primaryPattern) { - return window.localStorage.getItem( - JSON.stringify([this.plugin_, primaryPattern])); - }, - - /** - * @return {!Array} A list of all content setting rules for this plugin. - */ - getAll: function() { - var rules = []; - for (var i = 0; i < window.localStorage.length; i++) { - var key = window.localStorage.key(i); - var keyArray = JSON.parse(key); - if (keyArray[0] == this.plugin_) { - rules.push({ - 'primaryPattern': keyArray[1], - 'setting': window.localStorage.getItem(key), - }); - } - } - return rules; - } - }; - - return { - Settings: Settings, - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_settings_test.html b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_settings_test.html deleted file mode 100644 index 7bcad36b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/plugin_settings_test.html +++ /dev/null
@@ -1,143 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script> -<script src="../domui/js/cr.js"></script> -<script src="../domui/js/cr/event_target.js"></script> -<script src="plugin_settings.js" type="text/javascript"></script> -<script> -goog.require('goog.testing.jsunit'); -</script> -<script src="chrome_stubs.js" type="text/javascript"></script> -</head> -<body> -<script> -function testConstruction() { - var settings = createSettings(); -} - -function testSet() { - var settings = createSettings(); - var rules = { - 'http://example.com/*': 'block', - 'http://google.com/*': 'allow', - 'http://moose.org/*': 'allow', - }; - var numCallbacks = 0; - for (var pattern in rules) { - settings.set(pattern, rules[pattern], function(error) { - numCallbacks++; - assertUndefined(error); - }); - } - assertEquals(Object.keys(rules).length, numCallbacks); - assertObjectEquals(rules, _rules); -} - -function testSetInvalid() { - var settings = createSettings(); - // Attempting to set an invalid pattern should return an error in the - // callback. - var callbackCalled = false; - settings.set('__invalid_pattern', 'block', function(error) { - callbackCalled = true; - assertEquals('Invalid pattern', error); - }); - assertTrue(callbackCalled); - assertObjectEquals({}, _rules); - - // Attempting to set an invalid setting should immediately throw an exception. - callbackCalled = false; - assertThrows(function() { - settings.set('http://example.com/*', '__invalid_setting', function() { - callbackCalled = true; - }); - }); - assertFalse(callbackCalled); - assertObjectEquals({}, _rules); -} - -function testGet() { - var rules = { - 'http://example.com/*': 'block', - 'http://google.com/*': 'allow', - 'http://moose.org/*': 'allow', - }; - var settings = createSettings(rules); - for (var pattern in rules) - assertEquals(rules[pattern], settings.get(pattern)); -} - -function testGetAll() { - var settings = createSettings({ - 'http://example.com/*': 'block', - 'http://google.com/*': 'allow', - 'http://moose.org/*': 'allow', - }); - var rules = settings.getAll(); - // Sort the rules lexicographically by their pattern. - rules.sort(function(a, b) { - if (a.primaryPattern == b.primaryPattern) { - return 0; - } - if (a.primaryPattern > b.primaryPattern) { - return 1; - } - return -1; - }); - assertEquals(3, rules.length); - assertObjectEquals({'primaryPattern': 'http://example.com/*', - 'setting': 'block'}, - rules[0]); - assertObjectEquals({'primaryPattern': 'http://google.com/*', - 'setting': 'allow'}, - rules[1]); - assertObjectEquals({'primaryPattern': 'http://moose.org/*', - 'setting': 'allow'}, - rules[2]); -} - -function testUpdate() { - var settings = createSettings({ - 'http://example.com/*': 'block', - 'http://google.com/*': 'allow', - 'http://moose.org/*': 'allow', - }); - var numCallbacks = 0; - settings.update('http://google.com/*', 'http://google.com/*', 'ask', - function(error) { - numCallbacks++; - assertUndefined(error); - }); - assertEquals('ask', _rules['http://google.com/*']); - - settings.update('http://google.com/*', 'http://blurp.net/*', 'ask', - function(error) { - numCallbacks++; - assertUndefined(error); - }); - assertUndefined(_rules['http://google.com/*']); - assertEquals('ask', _rules['http://blurp.net/*']); - - // Attempting to update a rule to an invalid pattern should return an error - // and leave the rules unchanged. - settings.update('http://example.com/*', '__invalid_pattern', 'ask', - function(error) { - numCallbacks++; - assertEquals('Invalid pattern', error); - }); - assertUndefined(_rules['__invalid_pattern']); - assertEquals('block', _rules['http://example.com/*']); - - assertEquals(3, numCallbacks); -} - -function tearDown() { - // Clear local storage and |rules_| to make sure no state leaks into the next - // test. - window.localStorage.clear(); - _rules = {}; -} -</script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/rule_list.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/rule_list.js deleted file mode 100644 index 63cb846..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/rule_list.js +++ /dev/null
@@ -1,423 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * @fileoverview Defines a list of content setting rules. - */ - -cr.define('pluginSettings.ui', function() { - const InlineEditableItemList = options.InlineEditableItemList; - const InlineEditableItem = options.InlineEditableItem; - const ArrayDataModel = cr.ui.ArrayDataModel; - - /** - * CSS classes used by this class. - * @enum {string} - */ - const CSSClass = { - /** - * A list of content setting rules. - */ - RULE_LIST: 'rule-list', - - /** - * The element containing the content setting pattern for a rule. - */ - RULE_PATTERN: 'rule-pattern', - - /** - * The element containing the behavior (allow or block) for a rule. - */ - RULE_BEHAVIOR: 'rule-behavior', - - /** - * Static text (as opposed to an editable text field). - */ - STATIC_TEXT: 'static-text', - }; - /** - * A single item in a list of rules. - * @param {!RuleList} list The rule list containing this item. - * @param {!Object} rule The content setting rule. - * @constructor - * @extends {options.InlineEditableItem} - */ - function RuleListItem(list, rule) { - var el = cr.doc.createElement('li'); - - /** - * The content setting rule. - * @type {!Object} - * @private - */ - el.dataItem_ = rule; - - /** - * The rule list containing this item. - * @type {!RuleList} - * @private - */ - el.list_ = list; - el.__proto__ = RuleListItem.prototype; - el.decorate(); - - return el; - } - - RuleListItem.prototype = { - __proto__: InlineEditableItem.prototype, - - /** - * The text input element for the pattern. This is only null in the - * prototype. - * @type {?HTMLInputElement} - * @private - */ - input_: null, - - /** - * The popup button for the setting. This is only null in the prototype. - * @type {?HTMLSelectElement} - * @private - */ - select_: null, - - /** - * The static text field containing the pattern. - * @type {?HTMLDivElement} - * @private - */ - patternLabel_: null, - - /** - * The static text field containing the setting. - * @type {?HTMLDivElement} - * @private - */ - settingLabel_: null, - - /** - * Decorates an elements as a list item. - */ - decorate: function() { - InlineEditableItem.prototype.decorate.call(this); - - this.isPlaceholder = !this.pattern; - var patternCell = this.createEditableTextCell(this.pattern); - patternCell.className = CSSClass.RULE_PATTERN; - this.contentElement.appendChild(patternCell); - var input = patternCell.querySelector('input'); - if (this.pattern) { - this.patternLabel_ = - patternCell.querySelector('.' + CSSClass.STATIC_TEXT); - } else { - input.placeholder = chrome.i18n.getMessage('addNewPattern'); - } - - // Setting label for display mode. |pattern| will be null for the 'add new - // exception' row. - if (this.pattern) { - var settingLabel = cr.doc.createElement('span'); - settingLabel.textContent = this.settingForDisplay(); - settingLabel.className = CSSClass.RULE_BEHAVIOR; - settingLabel.setAttribute('displaymode', 'static'); - this.contentElement.appendChild(settingLabel); - this.settingLabel_ = settingLabel; - } - - // Setting select element for edit mode. - var select = cr.doc.createElement('select'); - var optionAllow = cr.doc.createElement('option'); - optionAllow.textContent = chrome.i18n.getMessage('allowRule'); - optionAllow.value = 'allow'; - select.appendChild(optionAllow); - - var optionBlock = cr.doc.createElement('option'); - optionBlock.textContent = chrome.i18n.getMessage('blockRule'); - optionBlock.value = 'block'; - select.appendChild(optionBlock); - - this.contentElement.appendChild(select); - select.className = CSSClass.RULE_BEHAVIOR; - if (this.pattern) { - select.setAttribute('displaymode', 'edit'); - } - - this.input_ = input; - this.select_ = select; - - this.updateEditables(); - - // Listen for edit events. - this.addEventListener('canceledit', this.onEditCancelled_); - this.addEventListener('commitedit', this.onEditCommitted_); - }, - - /** - * The pattern (e.g., a URL) for the rule. - * @type {string} - */ - get pattern() { - return this.dataItem_['primaryPattern']; - }, - set pattern(pattern) { - this.dataItem_['primaryPattern'] = pattern; - }, - - /** - * The setting (allow/block) for the rule. - * @type {string} - */ - get setting() { - return this.dataItem_['setting']; - }, - set setting(setting) { - this.dataItem_['setting'] = setting; - }, - - /** - * Gets a human-readable setting string. - * @type {string} - */ - settingForDisplay: function() { - var setting = this.setting; - if (setting == 'allow') { - return chrome.i18n.getMessage('allowRule'); - } - if (setting == 'block') { - return chrome.i18n.getMessage('blockRule'); - } - }, - - /** - * Set the <input> to its original contents. Used when the user quits - * editing. - */ - resetInput: function() { - this.input_.value = this.pattern; - }, - - /** - * Copy the data model values to the editable nodes. - */ - updateEditables: function() { - this.resetInput(); - - var settingOption = - this.select_.querySelector('[value=\'' + this.setting + '\']'); - if (settingOption) { - settingOption.selected = true; - } - }, - - /** @inheritDoc */ - get hasBeenEdited() { - var livePattern = this.input_.value; - var liveSetting = this.select_.value; - return livePattern != this.pattern || liveSetting != this.setting; - }, - - /** - * Called when committing an edit. - * @param {!Event} e The end event. - * @private - */ - onEditCommitted_: function(e) { - var newPattern = this.input_.value; - var newSetting = this.select_.value; - - this.finishEdit(newPattern, newSetting); - }, - - /** - * Called when cancelling an edit; resets the control states. - * @param {!Event} e The cancel event. - * @private - */ - onEditCancelled_: function() { - this.updateEditables(); - }, - - /** - * Editing is complete; update the model. - * @param {string} newPattern The pattern that the user entered. - * @param {string} newSetting The setting the user chose. - */ - finishEdit: function(newPattern, newSetting) { - this.patternLabel_.textContent = newPattern; - this.settingLabel_.textContent = this.settingForDisplay(); - var oldPattern = this.pattern; - this.pattern = newPattern; - this.setting = newSetting; - - this.list_.settings.update(oldPattern, newPattern, newSetting, - this.list_.settingsChangedCallback()); - } - }; - - /** - * Create a new list item to add a rule. - * @param {!RuleList} list The rule list containing this item. - * @constructor - * @extends {AddRuleListItem} - */ - function AddRuleListItem(list) { - var el = cr.doc.createElement('div'); - el.dataItem_ = {}; - el.list_ = list; - el.__proto__ = AddRuleListItem.prototype; - el.decorate(); - - return el; - } - - AddRuleListItem.prototype = { - __proto__: RuleListItem.prototype, - - /** - * Initializes the element. - */ - decorate: function() { - RuleListItem.prototype.decorate.call(this); - - this.setting = 'allow'; - }, - - /** - * Clear the <input> and let the placeholder text show again. - */ - resetInput: function() { - this.input_.value = ''; - }, - - /** @inheritDoc */ - get hasBeenEdited() { - return this.input_.value != ''; - }, - - /** - * Editing is complete; update the model. As long as the pattern isn't - * empty, we'll just add it. - * @param {string} newPattern The pattern that the user entered. - * @param {string} newSetting The setting the user chose. - */ - finishEdit: function(newPattern, newSetting) { - this.resetInput(); - this.list_.settings.set(newPattern, newSetting, - this.list_.settingsChangedCallback()); - }, - }; - - /** - * A list of content setting rules. - * @constructor - * @extends {cr.ui.List} - */ - var RuleList = cr.ui.define('list'); - - RuleList.prototype = { - __proto__: InlineEditableItemList.prototype, - - /** - * The content settings model for this list. - * @type {?Settings} - */ - settings: null, - - /** - * Called when an element is decorated as a list. - */ - decorate: function() { - InlineEditableItemList.prototype.decorate.call(this); - - this.classList.add(CSSClass.RULE_LIST); - - this.autoExpands = true; - this.reset(); - }, - - /** - * Creates an item to go in the list. - * @param {?Object} entry The element from the data model for this row. - */ - createItem: function(entry) { - if (entry) { - return new RuleListItem(this, entry); - } else { - var addRuleItem = new AddRuleListItem(this); - addRuleItem.deletable = false; - return addRuleItem; - } - }, - - /** - * Sets the rules in the js model. - * @param {!Array} entries A list of dictionaries of values, each dictionary - * represents a rule. - */ - setRules_: function(entries) { - var deleteCount = this.dataModel.length - 1; - - var args = [0, deleteCount]; - args.push.apply(args, entries); - this.dataModel.splice.apply(this.dataModel, args); - }, - - /** - * Called when the list of content setting rules has been changed. - * @param {?string} error The error message, if an error occurred. - * Otherwise, this is null. - * @private - */ - settingsChanged_: function(error) { - if (error) { - $('error').textContent = 'Error: ' + error; - } else { - $('error').textContent = ''; - } - this.setRules_(this.settings.getAll()); - }, - - /** - * @return {function()} A bound callback to update the UI after the - * settings have been changed. - */ - settingsChangedCallback: function() { - return this.settingsChanged_.bind(this); - }, - - /** - * Binds this list to the content settings model. - * @param {!Settings} settings The content settings model. - */ - setPluginSettings: function(settings) { - this.settings = settings; - this.settingsChanged_(); - }, - - /** - * Removes all rules from the js model. - */ - reset: function() { - // The null creates the Add New Rule row. - this.dataModel = new ArrayDataModel([null]); - }, - - /** @inheritDoc */ - deleteItemAtIndex: function(index) { - var listItem = this.getListItemByIndex(index); - if (listItem.undeletable) { - return; - } - - this.settings.clear(listItem.pattern, this.settingsChangedCallback()); - }, - }; - - return { - RuleListItem: RuleListItem, - AddRuleListItem: AddRuleListItem, - RuleList: RuleList, - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/rule_list_test.html b/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/rule_list_test.html deleted file mode 100644 index fee89f5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/js/rule_list_test.html +++ /dev/null
@@ -1,64 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<link rel="stylesheet" href="../domui/css/button.css"> -<link rel="stylesheet" href="../domui/css/chrome_shared.css"> -<link rel="stylesheet" href="../domui/css/list.css"> -<link rel="stylesheet" href="../domui/css/select.css"> - -<link rel="stylesheet" href="../options/css/list.css"> - -<link rel="stylesheet" href="../css/rule_list.css"> - -<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script> -<script src="../domui/js/cr.js"></script> -<script src="../domui/js/cr/event_target.js"></script> -<script src="../domui/js/cr/ui.js"></script> -<script src="../domui/js/cr/ui/array_data_model.js"></script> -<script src="../domui/js/cr/ui/list_item.js"></script> -<script src="../domui/js/cr/ui/list_selection_controller.js"></script> -<script src="../domui/js/cr/ui/list_selection_model.js"></script> -<script src="../domui/js/cr/ui/list_single_selection_model.js"></script> -<script src="../domui/js/cr/ui/list.js"></script> -<script src="../domui/js/util.js"></script> - -<script src="../options/js/deletable_item_list.js"></script> -<script src="../options/js/inline_editable_list.js"></script> - -<script src="plugin_settings.js" type="text/javascript"></script> -<script src="rule_list.js" type="text/javascript"></script> - -<script> -goog.require('goog.testing.jsunit'); -</script> -<script src="chrome_stubs.js" type="text/javascript"></script> -</head> -<body> -<list id="rule-list"></list> -<div id="error"></div> -<script> -function testConstruction() { - var rulesEl = document.createElement('list'); - document.body.appendChild(rulesEl); - pluginSettings.ui.RuleList.decorate(rulesEl); - var rules = { - 'http://example.com/*': 'block', - 'http://moose.org/*': 'allow', - }; - rulesEl.setPluginSettings(createSettings(rules)); - var ruleElements = rulesEl.querySelectorAll('[role=listitem]'); - assertEquals(3, ruleElements.length); - assertEquals('http://example.com/*', - ruleElements[0].querySelector('.rule-pattern').textContent); - assertEquals('http://moose.org/*', - ruleElements[1].querySelector('.rule-pattern').textContent); - assertEquals('', ruleElements[2].querySelector('.rule-pattern').textContent); - assertEquals('Block', - ruleElements[0].querySelector('.rule-behavior').textContent); - assertEquals('Allow', - ruleElements[1].querySelector('.rule-behavior').textContent); - assertEquals('allow', ruleElements[2].querySelector('.rule-behavior').value); -} -</script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/manifest.json b/chrome/common/extensions/docs/examples/extensions/plugin_settings/manifest.json deleted file mode 100644 index a6181e2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/manifest.json +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "name" : "__MSG_extName__", - "version" : "0.6", - "description" : "__MSG_extDescription__", - "options_page": "options.html", - "permissions": [ - "contentSettings" - ], - "icons": { - "128": "bunny128.png", - "48": "bunny48.png" - }, - "minimum_chrome_version": "16.0.912", - "default_locale": "en", - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options.html b/chrome/common/extensions/docs/examples/extensions/plugin_settings/options.html deleted file mode 100644 index abfdd7e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options.html +++ /dev/null
@@ -1,38 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<link rel="stylesheet" href="domui/css/button.css"> -<link rel="stylesheet" href="domui/css/chrome_shared.css"> -<link rel="stylesheet" href="domui/css/list.css"> -<link rel="stylesheet" href="domui/css/select.css"> - -<link rel="stylesheet" href="options/css/list.css"> - -<link rel="stylesheet" href="css/plugin_list.css"> -<link rel="stylesheet" href="css/rule_list.css"> - -<script src="domui/js/cr.js"></script> -<script src="domui/js/cr/event_target.js"></script> -<script src="domui/js/cr/ui.js"></script> -<script src="domui/js/cr/ui/array_data_model.js"></script> -<script src="domui/js/cr/ui/list_item.js"></script> -<script src="domui/js/cr/ui/list_selection_controller.js"></script> -<script src="domui/js/cr/ui/list_selection_model.js"></script> -<script src="domui/js/cr/ui/list_single_selection_model.js"></script> -<script src="domui/js/cr/ui/list.js"></script> -<script src="domui/js/util.js"></script> - -<script src="options/js/deletable_item_list.js"></script> -<script src="options/js/inline_editable_list.js"></script> - -<script src="js/plugin_list.js" type="text/javascript"></script> -<script src="js/plugin_settings.js" type="text/javascript"></script> -<script src="js/rule_list.js" type="text/javascript"></script> - -<script src="js/main.js" type="text/javascript"></script> -</head> -<body> -<list id="plugin-list"></list> -<div id="error"></div> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/css/list.css b/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/css/list.css deleted file mode 100644 index 4ff7b90b..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/css/list.css +++ /dev/null
@@ -1,116 +0,0 @@ -/* Copyright 2011 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. */ - -.raw-button, -.raw-button:hover, -.raw-button:active { - -webkit-box-shadow: none; - background-color: transparent; - background-repeat: no-repeat; - border: none; - min-width: 0; - padding: 1px 6px; -} - -list > * { - -webkit-box-align: center; - box-sizing: border-box; - border-radius: 0; - display: -webkit-box; - height: 32px; - border: none; - margin: 0; - transition: .15s background-color; -} - -list:not([disabled]) > :hover { - background-color: #e4ecf7; -} - -list:not([hasElementFocus]) > [selected], -list:not([hasElementFocus]) > [lead][selected] { - background-color: #d0d0d0; - background-image: none; -} - -list[hasElementFocus] > [selected], -list[hasElementFocus] > [lead][selected], -list:not([hasElementFocus]) > [selected]:hover, -list:not([hasElementFocus]) > [selected][lead]:hover { - background-color: #bbcee9; - background-image: none; -} - -list[disabled] { - opacity: 0.6; -} - -list > .heading { - color: #666666; -} - -list > .heading:hover { - background-color: transparent; - border-color: transparent; -} - -list .deletable-item { - -webkit-box-align: center; -} - -list .deletable-item > :first-child { - -webkit-box-align: center; - -webkit-box-flex: 1; - display: -webkit-box; - padding-inline-end: 5px; -} - -list .close-button { - background-color: transparent; - background-image: url("../images/close_bar.png"); - border: none; - display: block; - height: 16px; - opacity: 1; - transition: .15s opacity; - width: 16px; -} - -list > *:not(:hover):not([lead]) .close-button, -list > *:not(:hover):not([selected]) .close-button, -list:not([hasElementFocus]) > *:not(:hover) .close-button, -list[disabled] .close-button, -list .close-button[disabled] { - opacity: 0; - pointer-events: none; -} - -list .close-button:hover { - background-image: url("../images/close_bar_h.png"); -} - -list .close-button:active { - background-image: url("../images/close_bar_p.png"); -} - -list .static-text { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -list[inlineeditable] input { - box-sizing: border-box; - margin: 0; - width: 100%; -} - -list[inlineeditable] > :not([editing]) [displaymode="edit"], -list[inlineeditable] > [editing] [displaymode="static"] { - display: none; -} - -list > [editing] input:invalid { - background-color: pink; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar.png b/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar.png deleted file mode 100644 index 912df05d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar_h.png b/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar_h.png deleted file mode 100644 index 66f1d89..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar_h.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar_p.png b/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar_p.png deleted file mode 100644 index f9761b0..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/images/close_bar_p.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/js/deletable_item_list.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/js/deletable_item_list.js deleted file mode 100644 index 4d2e68e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/js/deletable_item_list.js +++ /dev/null
@@ -1,185 +0,0 @@ -// Copyright (c) 2011 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. - -cr.define('options', function() { - const List = cr.ui.List; - const ListItem = cr.ui.ListItem; - - /** - * Creates a deletable list item, which has a button that will trigger a call - * to deleteItemAtIndex(index) in the list. - */ - var DeletableItem = cr.ui.define('li'); - - DeletableItem.prototype = { - __proto__: ListItem.prototype, - - /** - * The element subclasses should populate with content. - * @type {HTMLElement} - * @private - */ - contentElement_: null, - - /** - * The close button element. - * @type {HTMLElement} - * @private - */ - closeButtonElement_: null, - - /** - * Whether or not this item can be deleted. - * @type {boolean} - * @private - */ - deletable_: true, - - /** @inheritDoc */ - decorate: function() { - ListItem.prototype.decorate.call(this); - - this.classList.add('deletable-item'); - - this.contentElement_ = this.ownerDocument.createElement('div'); - this.appendChild(this.contentElement_); - - this.closeButtonElement_ = this.ownerDocument.createElement('button'); - this.closeButtonElement_.classList.add('raw-button'); - this.closeButtonElement_.classList.add('close-button'); - this.closeButtonElement_.addEventListener('mousedown', - this.handleMouseDownUpOnClose_); - this.closeButtonElement_.addEventListener('mouseup', - this.handleMouseDownUpOnClose_); - this.closeButtonElement_.addEventListener('focus', - this.handleFocus_.bind(this)); - this.appendChild(this.closeButtonElement_); - }, - - /** - * Returns the element subclasses should add content to. - * @return {HTMLElement} The element subclasses should popuplate. - */ - get contentElement() { - return this.contentElement_; - }, - - /* Gets/sets the deletable property. An item that is not deletable doesn't - * show the delete button (although space is still reserved for it). - */ - get deletable() { - return this.deletable_; - }, - set deletable(value) { - this.deletable_ = value; - this.closeButtonElement_.disabled = !value; - }, - - /** - * Called when a focusable child element receives focus. Selects this item - * in the list selection model. - * @private - */ - handleFocus_: function() { - var list = this.parentNode; - var index = list.getIndexOfListItem(this); - list.selectionModel.selectedIndex = index; - list.selectionModel.anchorIndex = index; - }, - - /** - * Don't let the list have a crack at the event. We don't want clicking the - * close button to change the selection of the list. - * @param {Event} e The mouse down/up event object. - * @private - */ - handleMouseDownUpOnClose_: function(e) { - if (!e.target.disabled) - e.stopPropagation(); - }, - }; - - var DeletableItemList = cr.ui.define('list'); - - DeletableItemList.prototype = { - __proto__: List.prototype, - - /** @inheritDoc */ - decorate: function() { - List.prototype.decorate.call(this); - this.addEventListener('click', this.handleClick_); - this.addEventListener('keydown', this.handleKeyDown_); - }, - - /** - * Callback for onclick events. - * @param {Event} e The click event object. - * @private - */ - handleClick_: function(e) { - if (this.disabled) - return; - - var target = e.target; - if (target.classList.contains('close-button')) { - var listItem = this.getListItemAncestor(target); - var selected = this.selectionModel.selectedIndexes; - - // Check if the list item that contains the close button being clicked - // is not in the list of selected items. Only delete this item in that - // case. - var idx = this.getIndexOfListItem(listItem); - if (selected.indexOf(idx) == -1) { - this.deleteItemAtIndex(idx); - } else { - this.deleteSelectedItems_(); - } - } - }, - - /** - * Callback for keydown events. - * @param {Event} e The keydown event object. - * @private - */ - handleKeyDown_: function(e) { - // Map delete (and backspace on Mac) to item deletion (unless focus is - // in an input field, where it's intended for text editing). - if ((e.keyCode == 46 || (e.keyCode == 8 && cr.isMac)) && - e.target.tagName != 'INPUT') { - this.deleteSelectedItems_(); - // Prevent the browser from going back. - e.preventDefault(); - } - }, - - /** - * Deletes all the currently selected items that are deletable. - * @private - */ - deleteSelectedItems_: function() { - var selected = this.selectionModel.selectedIndexes; - // Reverse through the list of selected indexes to maintain the - // correct index values after deletion. - for (var j = selected.length - 1; j >= 0; j--) { - var index = selected[j]; - if (this.getListItemByIndex(index).deletable) - this.deleteItemAtIndex(index); - } - }, - - /** - * Called when an item should be deleted; subclasses are responsible for - * implementing. - * @param {number} index The index of the item that is being deleted. - */ - deleteItemAtIndex: function(index) { - }, - }; - - return { - DeletableItemList: DeletableItemList, - DeletableItem: DeletableItem, - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/js/inline_editable_list.js b/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/js/inline_editable_list.js deleted file mode 100644 index c09d920..0000000 --- a/chrome/common/extensions/docs/examples/extensions/plugin_settings/options/js/inline_editable_list.js +++ /dev/null
@@ -1,414 +0,0 @@ -// Copyright (c) 2011 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. - -cr.define('options', function() { - const DeletableItem = options.DeletableItem; - const DeletableItemList = options.DeletableItemList; - - /** - * Creates a new list item with support for inline editing. - * @constructor - * @extends {options.DeletableListItem} - */ - function InlineEditableItem() { - var el = cr.doc.createElement('div'); - InlineEditableItem.decorate(el); - return el; - } - - /** - * Decorates an element as a inline-editable list item. Note that this is - * a subclass of DeletableItem. - * @param {!HTMLElement} el The element to decorate. - */ - InlineEditableItem.decorate = function(el) { - el.__proto__ = InlineEditableItem.prototype; - el.decorate(); - }; - - InlineEditableItem.prototype = { - __proto__: DeletableItem.prototype, - - /** - * Whether or not this item can be edited. - * @type {boolean} - * @private - */ - editable_: true, - - /** - * Whether or not this is a placeholder for adding a new item. - * @type {boolean} - * @private - */ - isPlaceholder_: false, - - /** - * Fields associated with edit mode. - * @type {array} - * @private - */ - editFields_: null, - - /** - * Whether or not the current edit should be considered cancelled, rather - * than committed, when editing ends. - * @type {boolean} - * @private - */ - editCancelled_: true, - - /** - * The editable item corresponding to the last click, if any. Used to decide - * initial focus when entering edit mode. - * @type {HTMLElement} - * @private - */ - editClickTarget_: null, - - /** @inheritDoc */ - decorate: function() { - DeletableItem.prototype.decorate.call(this); - - this.editFields_ = []; - this.addEventListener('mousedown', this.handleMouseDown_); - this.addEventListener('keydown', this.handleKeyDown_); - this.addEventListener('leadChange', this.handleLeadChange_); - }, - - /** @inheritDoc */ - selectionChanged: function() { - this.updateEditState(); - }, - - /** - * Called when this element gains or loses 'lead' status. Updates editing - * mode accordingly. - * @private - */ - handleLeadChange_: function() { - this.updateEditState(); - }, - - /** - * Updates the edit state based on the current selected and lead states. - */ - updateEditState: function() { - if (this.editable) - this.editing = this.selected && this.lead; - }, - - /** - * Whether the user is currently editing the list item. - * @type {boolean} - */ - get editing() { - return this.hasAttribute('editing'); - }, - set editing(editing) { - if (this.editing == editing) - return; - - if (editing) - this.setAttribute('editing', ''); - else - this.removeAttribute('editing'); - - if (editing) { - this.editCancelled_ = false; - - cr.dispatchSimpleEvent(this, 'edit', true); - - var focusElement = this.editClickTarget_ || this.initialFocusElement; - this.editClickTarget_ = null; - - // When this is called in response to the selectedChange event, - // the list grabs focus immediately afterwards. Thus we must delay - // our focus grab. - var self = this; - if (focusElement) { - window.setTimeout(function() { - // Make sure we are still in edit mode by the time we execute. - if (self.editing) { - focusElement.focus(); - focusElement.select(); - } - }, 50); - } - } else { - if (!this.editCancelled_ && this.hasBeenEdited && - this.currentInputIsValid) { - if (this.isPlaceholder) - this.parentNode.focusPlaceholder = true; - - this.updateStaticValues_(); - cr.dispatchSimpleEvent(this, 'commitedit', true); - } else { - this.resetEditableValues_(); - cr.dispatchSimpleEvent(this, 'canceledit', true); - } - } - }, - - /** - * Whether the item is editable. - * @type {boolean} - */ - get editable() { - return this.editable_; - }, - set editable(editable) { - this.editable_ = editable; - if (!editable) - this.editing = false; - }, - - /** - * Whether the item is a new item placeholder. - * @type {boolean} - */ - get isPlaceholder() { - return this.isPlaceholder_; - }, - set isPlaceholder(isPlaceholder) { - this.isPlaceholder_ = isPlaceholder; - if (isPlaceholder) - this.deletable = false; - }, - - /** - * The HTML element that should have focus initially when editing starts, - * if a specific element wasn't clicked. - * Defaults to the first <input> element; can be overriden by subclasses if - * a different element should be focused. - * @type {HTMLElement} - */ - get initialFocusElement() { - return this.contentElement.querySelector('input'); - }, - - /** - * Whether the input in currently valid to submit. If this returns false - * when editing would be submitted, either editing will not be ended, - * or it will be cancelled, depending on the context. - * Can be overrided by subclasses to perform input validation. - * @type {boolean} - */ - get currentInputIsValid() { - return true; - }, - - /** - * Returns true if the item has been changed by an edit. - * Can be overrided by subclasses to return false when nothing has changed - * to avoid unnecessary commits. - * @type {boolean} - */ - get hasBeenEdited() { - return true; - }, - - /** - * Returns a div containing an <input>, as well as static text if - * isPlaceholder is not true. - * @param {string} text The text of the cell. - * @return {HTMLElement} The HTML element for the cell. - * @private - */ - createEditableTextCell: function(text) { - var container = this.ownerDocument.createElement('div'); - - if (!this.isPlaceholder) { - var textEl = this.ownerDocument.createElement('div'); - textEl.className = 'static-text'; - textEl.textContent = text; - textEl.setAttribute('displaymode', 'static'); - container.appendChild(textEl); - } - - var inputEl = this.ownerDocument.createElement('input'); - inputEl.type = 'text'; - inputEl.value = text; - if (!this.isPlaceholder) { - inputEl.setAttribute('displaymode', 'edit'); - inputEl.staticVersion = textEl; - } else { - // At this point |this| is not attached to the parent list yet, so give - // a short timeout in order for the attachment to occur. - var self = this; - window.setTimeout(function() { - var list = self.parentNode; - if (list && list.focusPlaceholder) { - list.focusPlaceholder = false; - if (list.shouldFocusPlaceholder()) - inputEl.focus(); - } - }, 50); - } - - inputEl.addEventListener('focus', this.handleFocus_.bind(this)); - container.appendChild(inputEl); - this.editFields_.push(inputEl); - - return container; - }, - - /** - * Resets the editable version of any controls created by createEditable* - * to match the static text. - * @private - */ - resetEditableValues_: function() { - var editFields = this.editFields_; - for (var i = 0; i < editFields.length; i++) { - var staticLabel = editFields[i].staticVersion; - if (!staticLabel && !this.isPlaceholder) - continue; - - if (editFields[i].tagName == 'INPUT') { - editFields[i].value = - this.isPlaceholder ? '' : staticLabel.textContent; - } - // Add more tag types here as new createEditable* methods are added. - - editFields[i].setCustomValidity(''); - } - }, - - /** - * Sets the static version of any controls created by createEditable* - * to match the current value of the editable version. Called on commit so - * that there's no flicker of the old value before the model updates. - * @private - */ - updateStaticValues_: function() { - var editFields = this.editFields_; - for (var i = 0; i < editFields.length; i++) { - var staticLabel = editFields[i].staticVersion; - if (!staticLabel) - continue; - - if (editFields[i].tagName == 'INPUT') - staticLabel.textContent = editFields[i].value; - // Add more tag types here as new createEditable* methods are added. - } - }, - - /** - * Called a key is pressed. Handles committing and cancelling edits. - * @param {Event} e The key down event. - * @private - */ - handleKeyDown_: function(e) { - if (!this.editing) - return; - - var endEdit = false; - switch (e.key) { - case 'Escape': - this.editCancelled_ = true; - endEdit = true; - break; - case 'Enter': - if (this.currentInputIsValid) - endEdit = true; - break; - } - - if (endEdit) { - // Blurring will trigger the edit to end; see InlineEditableItemList. - this.ownerDocument.activeElement.blur(); - // Make sure that handled keys aren't passed on and double-handled. - // (e.g., esc shouldn't both cancel an edit and close a subpage) - e.stopPropagation(); - } - }, - - /** - * Called when the list item is clicked. If the click target corresponds to - * an editable item, stores that item to focus when edit mode is started. - * @param {Event} e The mouse down event. - * @private - */ - handleMouseDown_: function(e) { - if (!this.editable || this.editing) - return; - - var clickTarget = e.target; - var editFields = this.editFields_; - for (var i = 0; i < editFields.length; i++) { - if (editFields[i] == clickTarget || - editFields[i].staticVersion == clickTarget) { - this.editClickTarget_ = editFields[i]; - return; - } - } - }, - }; - - /** - * Takes care of committing changes to inline editable list items when the - * window loses focus. - */ - function handleWindowBlurs() { - window.addEventListener('blur', function(e) { - var itemAncestor = findAncestor(document.activeElement, function(node) { - return node instanceof InlineEditableItem; - }); - if (itemAncestor); - document.activeElement.blur(); - }); - } - handleWindowBlurs(); - - var InlineEditableItemList = cr.ui.define('list'); - - InlineEditableItemList.prototype = { - __proto__: DeletableItemList.prototype, - - /** - * Focuses the input element of the placeholder if true. - * @type {boolean} - */ - focusPlaceholder: false, - - /** @inheritDoc */ - decorate: function() { - DeletableItemList.prototype.decorate.call(this); - this.setAttribute('inlineeditable', ''); - this.addEventListener('hasElementFocusChange', - this.handleListFocusChange_); - }, - - /** - * Called when the list hierarchy as a whole loses or gains focus; starts - * or ends editing for the lead item if necessary. - * @param {Event} e The change event. - * @private - */ - handleListFocusChange_: function(e) { - var leadItem = this.getListItemByIndex(this.selectionModel.leadIndex); - if (leadItem) { - if (e.newValue) - leadItem.updateEditState(); - else - leadItem.editing = false; - } - }, - - /** - * May be overridden by subclasses to disable focusing the placeholder. - * @return true if the placeholder element should be focused on edit commit. - */ - shouldFocusPlaceholder: function() { - return true; - }, - }; - - // Export - return { - InlineEditableItem: InlineEditableItem, - InlineEditableItemList: InlineEditableItemList, - }; -});
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/_locales/en/messages.json b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/_locales/en/messages.json deleted file mode 100644 index 74bc6f3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/_locales/en/messages.json +++ /dev/null
@@ -1,54 +0,0 @@ -{ - "extName": { - "message": "Proxy Extension API Sample", - "description": "The extension name." - }, - "extDescription": { - "message": "Set Chrome-specific proxies; a demonstration of Chrome's Proxy API", - "description": "The extension description." - }, - "headerDirectConnection": { - "message": "Direct Connection", - "description": "Header for 'Direct Connection' configuration `fieldset`." - }, - "errorNoExtensionAccess": { - "message": "Sorry. This browser's proxy settings cannot be controlled via extensions.", - "description": "Error message displayed when `levelOfControl` is 'not_controllable'." - }, - "errorOtherExtensionControls": { - "message": "Sorry. This browser's proxy settings are being controlled by another extension. Please visit chrome://extensions for details.", - "description": "Error message displayed when `levelOfControl` is 'controlled_by_other_extensions'." - }, - "errorSettingRegularProxy": { - "message": "Setting regular proxy settings failed. Sorry!", - "description": "Error message, displayed when failing to set regular proxy settings." - }, - "errorSettingIncognitoProxy": { - "message": "Setting incognito proxy settings failed. Sorry!", - "description": "Error message, displayed when failing to set incognito proxy settings." - }, - "successfullySetProxy": { - "message": "Your proxy settings have been saved successfully; this window will close automagically. Have a nice day!", - "description": "Success message, displayed after proxy settings have been written." - }, - "errorPopupTitle": { - "message": "Error: $1", - "description": "Error message used as popup title." - }, - "errorProxyError": { - "message": "ProxyError: $1.", - "description": "Error message displayed in popup when an error occurs." - }, - "errorProxyDetailedError": { - "message": "ProxyError: $1. $2.", - "description": "Error message displayed in popup when an error occurs." - }, - "errorIdNotFound": { - "message": "Element with ID `$1` doesn't exist in the document", - "description": "Error message thrown when the given `id` doesn't exist" - }, - "errorIdNotForm": { - "message": "Element with ID `$1` isn't a form element.", - "description": "Error message thrown when the given `id` isn't a form element." - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/background.js b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/background.js deleted file mode 100644 index 8640d419..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/background.js +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * @fileoverview This file initializes the background page by loading a - * ProxyErrorHandler, and resetting proxy settings if required. - * - * @author Mike West <mkwst@google.com> - */ - -document.addEventListener("DOMContentLoaded", function () { - var errorHandler = new ProxyErrorHandler(); - - // If this extension has already set the proxy settings, then reset it - // once as the background page initializes. This is essential, as - // incognito settings are wiped on restart. - var persistedSettings = ProxyFormController.getPersistedSettings(); - if (persistedSettings !== null) { - chrome.proxy.settings.set( - {'value': persistedSettings.regular}); - } -});
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon128.png b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon128.png deleted file mode 100644 index 1b1f7dd37..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon16.png b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon16.png deleted file mode 100644 index ef87b6e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon32.png b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon32.png deleted file mode 100644 index ce44a553a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon48.png b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon48.png deleted file mode 100644 index ff7d8ad1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/icon48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/manifest.json b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/manifest.json deleted file mode 100644 index 41e4e86..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/manifest.json +++ /dev/null
@@ -1,27 +0,0 @@ -{ - "name": "__MSG_extName__", - "version": "0.4", - "description": "__MSG_extDescription__", - "default_locale": "en", - "browser_action": { - "default_icon": "icon16.png", - "default_popup": "popup.html" - }, - "icons": { - "16": "icon16.png", - "32": "icon32.png", - "48": "icon48.png", - "128": "icon128.png" - }, - "background": { - "scripts": [ - "proxy_form_controller.js", - "proxy_error_handler.js", - "background.js" - ] - }, - "permissions": [ - "proxy" - ], - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.css b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.css deleted file mode 100644 index e375e2f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.css +++ /dev/null
@@ -1,198 +0,0 @@ -body { - margin: 5px 10px 10px; -} - -h1 { - color: #53637D; - font: 26px/1.2 Helvetica, sans-serif; - font-size: 200%; - margin: 0; - padding-bottom: 4px; - text-shadow: white 0 1px 2px; -} - -div[role='main'] { - border-radius: 5px; - background: #EAEEF3; - font: 14px/1 Arial,Sans Serif; - padding: 10px; - width: 563px; - box-shadow: inset 0px 2px 5px rgba(0,0,0,0.5); - overflow: hidden; - transition: background-color 0.5s ease-out; -} - -div[role='main'].incognito { - background: #496281 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAhCAYAAABeD2IVAAAFz0lEQVRYw8VYC0xcRRQtUEprERQ1VkohSGNpwaCYYNBUjS2K+KEVTUkDiqY0hWD5xxhDINgQqIZviRAkSiiWNDRxWypNpaatEQk/CwvlWyks3+XPAssu7I7nbmabx+suPzfrTU7yljfz5sy95947w5YtpjcLwBLYBuzgsAGs+DuzGZGwBh4BHIDdwHPA8xxuwBOcnIWpPUAL7wQeB54CngYcAWdO4kXgDeBoWFhYSk5OTtmFCxeuxsbGpuBv3sCTwFZTkrLmXtgH+AJ+QAAQCBzz8/P7MiUl5aebN29Kh4eHFVNTU2xoaIgNDAywe/fusYyMjO858R2mJEUe2ldZWfljd3f3P+3t7bK2trZBuVyuYCJbXFxkXV1drLOzU4e7d++yzMzMasz3AexMSYq89CoRYuuwvr6+B6Q6OjpYUVFRG+Yf4iE0iZYoc5woVK2trUPrIUXh05Mir9XW1qow/33gmf8idj0ZypjHuIgj5ubm1OshpdFoVoTwzp07zMbGJsTb23s/16fFZlKcyDjY29u7+fr6HoJFV1dXt7EN2MjIyANSUqmUubq6Jtna2r7OvWW7kUy04IR2+fj4HDx+/HhUYmJiIQQuhZ5mN0JKqVSuEHtWVlbd6dOns+3s7N7h9YtKynbuhFWNQuYQGBh4ODs7u2B0dHRauNDMzIx2eXmZabXadRG7f/++jhSylV25ckXOk2D4yJEjSVjnNV7ntq9Fily6Jzg4+CTEOqf/OJFoampSFRQUjDc3Ny+QF9RqtU47hozGE3mUDIbxOtTX1ytQt5T6MQipFGu9zDPbYq0i+ey5c+dyxAvBSxrsXHXixIlmVOsOaGykp6dnYXZ2lt49BHhIWVdXN1VaWipLS0trCQ8P/xseUwrD6+HhEUJO4BFa3VMREREx4+PjCkNhunjx4iAWuI0x16KjowlVYkA7uncYczUyMpJ+3z579mzXwsLCA9fimcXHx6djvb3cGatmHrnTBxr4jSZShaYwCQnC89PQXFNUVNSvMTExv6C/XYqLi6sg0DMISRISEq7h+QY81dHY2DgpDq9CoWCYm8Fbl8FmLaxLROoA8OGpU6dKL1++LCMdGdIPEkF569atIYlE0oNNdGFsNz03NDTI0QOVhrRG31GpVCR4JcrEV1jnFWOZaMVrBx07vIDDQBiQil3XQENDMplseWlpiW3WBOLXovWoy8vLBxA+CTT6NdZ5gR9vtooFvis1NfWTioqKn6uqqv6ihius4NCYZn5+Xuf2zRAi4OSgQQIsT05OrnA71qrmR6BtQlL0wwVpL1nPIqQzCgFpzlB50HuFxlF2TkxMUKiXxBKgb4Dooqen5zHeX63FWUfl/22k/aix+qM3IkEeS05Obs7Pz6+vqakZgAcUY2Njur8T2cHBwSXobbSwsPCPgICAAny7QJgstAaVjry8vEquKwexpiz5WccrJCTkDO1yLWIILcP474DPgQ8oMahpA9+C0FxJSUk7nr/h2vwMSAfhJWFJQAKN8Xku4tCJveWP3d8gb6zWToh0aGjoJYz/FHgToGYbTMmBUM0RnJyccvE7GkiEVlv1cylhpqenGbI7l4v8UWNVfRsn5efs7Jxx/vz5fr0+VvGWuqysrMbNzS0R88KDgoLyEMo+/XvyDI4tcmHC6GsUSkgL5rxFCWbsxGDFY/oSdn+mt7d3gj5w/fp15VrENmokbvRANTbyBdbbz8/tBgsn1agD/v7+cUh7lfAj2KmGmdAoI9PT0//kOnQ01vesedF8t7+/X27oQ0hbrSmJoXBKucD3GAsd3VS8cDIoY2YykgM6RS4/Zj8kckt+sfTDeaeHmdFwHxzj98Y94qKpOz+5u7ufZGY28haOyOX89rzCW9SZ3YuLi39g/4Mhy4ex/kHejFeQ2tvS0vI79ShqE+YEmjxLSkoK5aQsheGjW6snv8EeBT42Az4C3uP/l3DhyWYhvuPZ84PWbt6tzQFH7pCdvCzoSP0LtBi6oflBr2wAAAAASUVORK5CYII=') no-repeat 533px bottom; -} - -form { - transition: transform 0.25s ease; - width: 563px; -} - -form.offscreen { - transform: translateX(-600px); -} - -fieldset { - border: 0; - margin: 0; - padding: 0; - position: relative; -} - -legend { - position: absolute; - left: -999em; -} - -form > fieldset { - border-radius: 5px; - border: 1px solid transparent; - padding: 10px 10px 10px 30px; - margin: 5px 0; - transition: all 0.5s ease; -} - -form > fieldset:hover { - background: rgba(255,255,255,0.1); - border-color: rgba(0,0,0,0.1); -} - -form > fieldset.active { - background: rgba(255,255,255,0.25); - border-color: rgba(0,0,0,0.25); -} - -form > fieldset > input { - margin-left: -20px; -} - -section { - margin: 5px 0 0; -} - -section fieldset:not(:first-child):not(:last-child) { - max-height: 1.6em; - overflow: hidden; - transition: all 0.5s ease; -} - -section.single fieldset:not(:first-child):not(:last-child) { - max-height: 0px; -} - -section fieldset:last-child { - margin-top: 5px; -} - -section fieldset:last-child label { - display: block; -} - -section fieldset:last-child textarea { - width: 412px; -} - -section > fieldset { - position: relative; - padding-left: 60px; -} - -section > fieldset > legend { - left: 0; - top: 4px; - width: 53px; - text-align: right; -} - -input[type='url']:invalid:not(:active):not(:focus) { - border-color: rgba(255,0,0,0.5); - background: rgba(255,0,0,0.25); -} - -input:invalid:not(:active):not(:focus):after { - content: "This isn't a valid URL!"; - display:block; -} - -input[type="checkbox"] { - margin: 5px 0 5px 35px; -} - -input[type="text"] { - width: 200px; - margin: 0 10px 0 0; -} - -input.port { - width: 50px; - margin: 2px 10px 0 5px; -} - -section label, -section legend { - color: #999; - transition: color 0.5s ease; -} - -.incognito section label, -.incognito section legend { - color: #BBB; -} - -.active section label, -.active section legend, -form > fieldset > label { - color: #000; - transition: color 0.5s ease; -} - -.incognito .active section label, -.incognito .active section legend, -.incognito form > fieldset > label { - color: #FFF; -} - -input[type="submit"], -button { - border-radius: 2px; - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.1); - -webkit-user-select: none; - background: -webkit-linear-gradient(#FAFAFA, #F4F4F4 40%, #E5E5E5); - border: 1px solid #AAA; - color: #444; - margin-bottom: 0; - min-width: 4em; - padding: 3px 12px; - margin-top: 0; - font-size: 1.1em; -} - -.overlay { - display: block; - text-align: center; - position: absolute; - left: 50%; - top: 50%; - width: 500px; - padding: 20px; - margin: -80px 0 0 -270px; - opacity: 0; - background: rgba(0, 0, 0, 0.75); - border-radius: 5px; - color: #FFF; - font: 1.5em/1.2 Helvetica Neue, sans-serif; - transform: scale(0); - transition: all 1.0s ease; -} - -.overlay a { - color: #FFF; -} - -.overlay.visible { - opacity: 1; - transform: scale(1); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.html b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.html deleted file mode 100644 index 595283cf..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.html +++ /dev/null
@@ -1,109 +0,0 @@ -<!doctype html> -<html> -<head> - <title>Popup for Proxy API Test</title> - <link href="./popup.css" type="text/css" rel="stylesheet"> -</head> -<body> - <h1>Proxy Configuration</h1> - <div role="main"> - <form id="proxyForm"> - <fieldset id="system"> - <legend>System Settings</legend> - <input type="radio" name="proxyType" id="proxyTypeSystem" value="system"> - <label for="proxyTypeSystem">Use the <em>system's proxy settings</em>.</label> - </fieldset> - <fieldset id="direct"> - <legend>Direct Connection</legend> - <input type="radio" name="proxyType" id="proxyTypeDirect" value="direct"> - <label for="proxyTypeDirect">Your computer is <em>directly connected</em> to the internet; no need for a proxy.</label> - </fieldset> - <fieldset id="pac_script"> - <legend>Automatic Configuration</legend> - <input type="radio" name="proxyType" id="proxyTypeAutoconfig" value="autoconfig"> - <label for="proxyTypeAutoconfig">Your proxy supports <em>automatic configuration</em>.</label> - - <section> - <label for="autoconfigURL">Autoconfiguration URL (PAC file)</label> - <input type="url" name="autoconfigURL" id="autoconfigURL"> - <input type="hidden" name="autoconfigData" id="autoconfigData"> - </section> - </fieldset> - <fieldset id="fixed_servers"> - <legend>Manual Proxy</legend> - <input type="radio" name="proxyType" id="proxyTypeManual" value="manual"> - <label for="proxyTypeManual">Configure your proxy settings <em>manually</em>.</label> - <section> - <fieldset> - <legend>HTTP</legend> - <label for="proxyHostHttp">Host</label> - <select id="proxySchemeHttp" name="proxySchemeHttp"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostHttp" id="proxyHostHttp"> - - <label for="proxyPortHttp">Port</label> - <input type="text" name="proxyPortHttp" id="proxyPortHttp" class="port"> - - <input type="checkbox" name="singleProxyForEverything" id="singleProxyForEverything"> - <label for="singleProxyForEverything">Use the same proxy server for all protocols</label> - </fieldset> - <fieldset> - <legend>HTTPS</legend> - <label for="proxyHostHttps">Host</label> - <select id="proxySchemeHttps" name="proxySchemeHttps"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostHttps" id="proxyHostHttps"> - - <label for="proxyPortHttps">Port</label> - <input type="text" name="proxyPortHttps" id="proxyPortHttps" class="port"> - </fieldset> - <fieldset> - <legend>FTP</legend> - <label for="proxyHostFtp">Host</label> - <select id="proxySchemeFtp" name="proxySchemeFtp"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostFtp" id="proxyHostFtp"> - - <label for="proxyPortFtp">Port</label> - <input type="text" name="proxyPortFtp" id="proxyPortFtp" class="port"> - </fieldset> - <fieldset> - <legend>Fallback</legend> - <label for="proxyHostFallback">Host</label> - <select id="proxySchemeFallback" name="proxySchemeFallback"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostFallback" id="proxyHostFallback"> - - <label for="proxyPortFallback">Port</label> - <input type="text" name="proxyPortFallback" id="proxyPortFallback" class="port"> - </fieldset> - <fieldset> - <label for="bypassList">Bypass proxy for these hosts:</label> - <textarea id="bypassList" name="bypassList" placeholder="<local>,192.168.1.1/16, .example.com"></textarea> - </fieldset> - </section> - </fieldset> - <input type="submit" value="Save proxy settings"> - <button value="incognito">Configure incognito window settings.</button> - </form> - </div> - <script src="./proxy_form_controller.js"></script> - <script src="./popup.js"></script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.js b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.js deleted file mode 100644 index 1c1f36d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/popup.js +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * @fileoverview This file initializes the extension's popup by creating a - * ProxyFormController object. - * - * @author Mike West <mkwst@google.com> - */ - -document.addEventListener('DOMContentLoaded', function () { - var c = new ProxyFormController( 'proxyForm' ); -});
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_error_handler.js b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_error_handler.js deleted file mode 100644 index 7d2cd223..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_error_handler.js +++ /dev/null
@@ -1,104 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * @fileoverview This file implements the ProxyErrorHandler class, which will - * flag proxy errors in a visual way for the extension's user. - * - * @author Mike West <mkwst@google.com> - */ - - -/** - * The proxy error handling object. Binds to the 'onProxyError' event, and - * changes the extensions badge to reflect the error state (yellow for - * non-fatal errors, red for fatal). - * - * @constructor - */ -function ProxyErrorHandler() { - // Handle proxy error events. - chrome.proxy.onProxyError.addListener(this.handleError_.bind(this)); - - // Handle message events from popup. - chrome.extension.onRequest.addListener(this.handleOnRequest_.bind(this)); -}; - -/////////////////////////////////////////////////////////////////////////////// - -/** - * @typedef {{fatal: boolean, error: string, details: string}} - */ -ProxyErrorHandler.ErrorDetails; - -/////////////////////////////////////////////////////////////////////////////// - -ProxyErrorHandler.prototype = { - /** - * Details of the most recent error. - * @type {?ProxyErrorHandler.ErrorDetails} - * @private - */ - lastError_: null, - - /** - * Handle request messages from the popup. - * - * @param {!{type:string}} request The external request to answer. - * @param {!MessageSender} sender Info about the script context that sent - * the request. - * @param {!function} sendResponse Function to call to send a response. - * @private - */ - handleOnRequest_: function(request, sender, sendResponse) { - if (request.type === 'getError') { - sendResponse({result: this.getErrorDetails()}); - } else if (request.type === 'clearError') { - this.clearErrorDetails(); - sendResponse({result: true}); - } - }, - - /** - * Handles the error event, storing the error details for later use, and - * badges the browser action icon. - * - * @param {!ProxyErrorHandler.ErrorDetails} details The error details. - * @private - */ - handleError_: function(details) { - var RED = [255, 0, 0, 255]; - var YELLOW = [255, 205, 0, 255]; - - // Badge the popup icon. - var color = details.fatal ? RED : YELLOW; - chrome.browserAction.setBadgeBackgroundColor({color: color}); - chrome.browserAction.setBadgeText({text: 'X'}); - chrome.browserAction.setTitle({ - title: chrome.i18n.getMessage('errorPopupTitle', details.error) - }); - - // Store the error for display in the popup. - this.lastError_ = JSON.stringify(details); - }, - - - /** - * Returns details of the last error handled. - * - * @return {?ProxyErrorHandler.ErrorDetails} - */ - getErrorDetails: function() { - return this.lastError_; - }, - - - /** - * Clears last handled error. - */ - clearErrorDetails: function() { - chrome.browserAction.setBadgeText({text: ''}); - this.lastError_ = null; - } -}
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js deleted file mode 100644 index 0157bbea..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js +++ /dev/null
@@ -1,793 +0,0 @@ -// Copyright (c) 2011 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. - -/** - * @fileoverview This file implements the ProxyFormController class, which - * wraps a form element with logic that enables implementation of proxy - * settings. - * - * @author mkwst@google.com (Mike West) - */ - -/** - * Wraps the proxy configuration form, binding proper handlers to its various - * `change`, `click`, etc. events in order to take appropriate action in - * response to user events. - * - * @param {string} id The form's DOM ID. - * @constructor - */ -var ProxyFormController = function(id) { - /** - * The wrapped form element - * @type {Node} - * @private - */ - this.form_ = document.getElementById(id); - - // Throw an error if the element either doesn't exist, or isn't a form. - if (!this.form_) - throw chrome.i18n.getMessage('errorIdNotFound', id); - else if (this.form_.nodeName !== 'FORM') - throw chrome.i18n.getMessage('errorIdNotForm', id); - - /** - * Cached references to the `fieldset` groups that define the configuration - * options presented to the user. - * - * @type {NodeList} - * @private - */ - this.configGroups_ = document.querySelectorAll('#' + id + ' > fieldset'); - - this.bindEventHandlers_(); - this.readCurrentState_(); - - // Handle errors - this.handleProxyErrors_(); -}; - -/////////////////////////////////////////////////////////////////////////////// - -/** - * The proxy types we're capable of handling. - * @enum {string} - */ -ProxyFormController.ProxyTypes = { - AUTO: 'auto_detect', - PAC: 'pac_script', - DIRECT: 'direct', - FIXED: 'fixed_servers', - SYSTEM: 'system' -}; - -/** - * The window types we're capable of handling. - * @enum {int} - */ -ProxyFormController.WindowTypes = { - REGULAR: 1, - INCOGNITO: 2 -}; - -/** - * The extension's level of control of Chrome's roxy setting - * @enum {string} - */ -ProxyFormController.LevelOfControl = { - NOT_CONTROLLABLE: 'not_controllable', - OTHER_EXTENSION: 'controlled_by_other_extension', - AVAILABLE: 'controllable_by_this_extension', - CONTROLLING: 'controlled_by_this_extension' -}; - -/** - * The response type from 'proxy.settings.get' - * - * @typedef {{value: ProxyConfig, - * levelOfControl: ProxyFormController.LevelOfControl}} - */ -ProxyFormController.WrappedProxyConfig; - -/////////////////////////////////////////////////////////////////////////////// - -/** - * Retrieves proxy settings that have been persisted across restarts. - * - * @return {?ProxyConfig} The persisted proxy configuration, or null if no - * value has been persisted. - * @static - */ -ProxyFormController.getPersistedSettings = function() { - var result = null; - if (window.localStorage['proxyConfig'] !== undefined) - result = JSON.parse(window.localStorage['proxyConfig']); - return result ? result : null; -}; - - -/** - * Persists proxy settings across restarts. - * - * @param {!ProxyConfig} config The proxy config to persist. - * @static - */ -ProxyFormController.setPersistedSettings = function(config) { - window.localStorage['proxyConfig'] = JSON.stringify(config); -}; - -/////////////////////////////////////////////////////////////////////////////// - -ProxyFormController.prototype = { - /** - * The form's current state. - * @type {regular: ?ProxyConfig, incognito: ?ProxyConfig} - * @private - */ - config_: {regular: null, incognito: null}, - - /** - * Do we have access to incognito mode? - * @type {boolean} - * @private - */ - isAllowedIncognitoAccess_: false, - - /** - * @return {string} The PAC file URL (or an empty string). - */ - get pacURL() { - return document.getElementById('autoconfigURL').value; - }, - - - /** - * @param {!string} value The PAC file URL. - */ - set pacURL(value) { - document.getElementById('autoconfigURL').value = value; - }, - - - /** - * @return {string} The PAC file data (or an empty string). - */ - get manualPac() { - return document.getElementById('autoconfigData').value; - }, - - - /** - * @param {!string} value The PAC file data. - */ - set manualPac(value) { - document.getElementById('autoconfigData').value = value; - }, - - - /** - * @return {Array<string>} A list of hostnames that should bypass the proxy. - */ - get bypassList() { - return document.getElementById('bypassList').value.split(/\s*(?:,|^)\s*/m); - }, - - - /** - * @param {?Array<string>} data A list of hostnames that should bypass - * the proxy. If empty, the bypass list is emptied. - */ - set bypassList(data) { - if (!data) - data = []; - document.getElementById('bypassList').value = data.join(', '); - }, - - - /** - * @see http://code.google.com/chrome/extensions/trunk/proxy.html - * @return {?ProxyServer} An object containing the proxy server host, port, - * and scheme. If null, there is no single proxy. - */ - get singleProxy() { - var checkbox = document.getElementById('singleProxyForEverything'); - return checkbox.checked ? this.httpProxy : null; - }, - - - /** - * @see http://code.google.com/chrome/extensions/trunk/proxy.html - * @param {?ProxyServer} data An object containing the proxy server host, - * port, and scheme. If null, the single proxy checkbox will be unchecked. - */ - set singleProxy(data) { - var checkbox = document.getElementById('singleProxyForEverything'); - checkbox.checked = !!data; - - if (data) - this.httpProxy = data; - - if (checkbox.checked) - checkbox.parentNode.parentNode.classList.add('single'); - else - checkbox.parentNode.parentNode.classList.remove('single'); - }, - - /** - * @return {?ProxyServer} An object containing the proxy server host, port - * and scheme. - */ - get httpProxy() { - return this.getProxyImpl_('Http'); - }, - - - /** - * @param {?ProxyServer} data An object containing the proxy server host, - * port, and scheme. If empty, empties the proxy setting. - */ - set httpProxy(data) { - this.setProxyImpl_('Http', data); - }, - - - /** - * @return {?ProxyServer} An object containing the proxy server host, port - * and scheme. - */ - get httpsProxy() { - return this.getProxyImpl_('Https'); - }, - - - /** - * @param {?ProxyServer} data An object containing the proxy server host, - * port, and scheme. If empty, empties the proxy setting. - */ - set httpsProxy(data) { - this.setProxyImpl_('Https', data); - }, - - - /** - * @return {?ProxyServer} An object containing the proxy server host, port - * and scheme. - */ - get ftpProxy() { - return this.getProxyImpl_('Ftp'); - }, - - - /** - * @param {?ProxyServer} data An object containing the proxy server host, - * port, and scheme. If empty, empties the proxy setting. - */ - set ftpProxy(data) { - this.setProxyImpl_('Ftp', data); - }, - - - /** - * @return {?ProxyServer} An object containing the proxy server host, port - * and scheme. - */ - get fallbackProxy() { - return this.getProxyImpl_('Fallback'); - }, - - - /** - * @param {?ProxyServer} data An object containing the proxy server host, - * port, and scheme. If empty, empties the proxy setting. - */ - set fallbackProxy(data) { - this.setProxyImpl_('Fallback', data); - }, - - - /** - * @param {string} type The type of proxy that's being set ("Http", - * "Https", etc.). - * @return {?ProxyServer} An object containing the proxy server host, - * port, and scheme. - * @private - */ - getProxyImpl_: function(type) { - var result = { - scheme: document.getElementById('proxyScheme' + type).value, - host: document.getElementById('proxyHost' + type).value, - port: parseInt(document.getElementById('proxyPort' + type).value, 10) - }; - return (result.scheme && result.host && result.port) ? result : undefined; - }, - - - /** - * A generic mechanism for setting proxy data. - * - * @see http://code.google.com/chrome/extensions/trunk/proxy.html - * @param {string} type The type of proxy that's being set ("Http", - * "Https", etc.). - * @param {?ProxyServer} data An object containing the proxy server host, - * port, and scheme. If empty, empties the proxy setting. - * @private - */ - setProxyImpl_: function(type, data) { - if (!data) - data = {scheme: 'http', host: '', port: ''}; - - document.getElementById('proxyScheme' + type).value = data.scheme; - document.getElementById('proxyHost' + type).value = data.host; - document.getElementById('proxyPort' + type).value = data.port; - }, - -/////////////////////////////////////////////////////////////////////////////// - - /** - * Calls the proxy API to read the current settings, and populates the form - * accordingly. - * - * @private - */ - readCurrentState_: function() { - chrome.extension.isAllowedIncognitoAccess( - this.handleIncognitoAccessResponse_.bind(this)); - }, - - /** - * Handles the respnse from `chrome.extension.isAllowedIncognitoAccess` - * We can't render the form until we know what our access level is, so - * we wait until we have confirmed incognito access levels before - * asking for the proxy state. - * - * @param {boolean} state The state of incognito access. - * @private - */ - handleIncognitoAccessResponse_: function(state) { - this.isAllowedIncognitoAccess_ = state; - chrome.proxy.settings.get({incognito: false}, - this.handleRegularState_.bind(this)); - if (this.isAllowedIncognitoAccess_) { - chrome.proxy.settings.get({incognito: true}, - this.handleIncognitoState_.bind(this)); - } - }, - - /** - * Handles the response from 'proxy.settings.get' for regular - * settings. - * - * @param {ProxyFormController.WrappedProxyConfig} c The proxy data and - * extension's level of control thereof. - * @private - */ - handleRegularState_: function(c) { - if (c.levelOfControl === ProxyFormController.LevelOfControl.AVAILABLE || - c.levelOfControl === ProxyFormController.LevelOfControl.CONTROLLING) { - this.recalcFormValues_(c.value); - this.config_.regular = c.value; - } else { - this.handleLackOfControl_(c.levelOfControl); - } - }, - - /** - * Handles the response from 'proxy.settings.get' for incognito - * settings. - * - * @param {ProxyFormController.WrappedProxyConfig} c The proxy data and - * extension's level of control thereof. - * @private - */ - handleIncognitoState_: function(c) { - if (c.levelOfControl === ProxyFormController.LevelOfControl.AVAILABLE || - c.levelOfControl === ProxyFormController.LevelOfControl.CONTROLLING) { - if (this.isIncognitoMode_()) - this.recalcFormValues_(c.value); - - this.config_.incognito = c.value; - } else { - this.handleLackOfControl_(c.levelOfControl); - } - }, - - /** - * Binds event handlers for the various bits and pieces of the form that - * are interesting to the controller. - * - * @private - */ - bindEventHandlers_: function() { - this.form_.addEventListener('click', this.dispatchFormClick_.bind(this)); - }, - - - /** - * When a `click` event is triggered on the form, this function handles it by - * analyzing the context, and dispatching the click to the correct handler. - * - * @param {Event} e The event to be handled. - * @private - * @return {boolean} True if the event should bubble, false otherwise. - */ - dispatchFormClick_: function(e) { - var t = e.target; - - // Case 1: "Apply" - if (t.nodeName === 'INPUT' && t.getAttribute('type') === 'submit') { - return this.applyChanges_(e); - - // Case 2: "Use the same proxy for all protocols" in an active section - } else if (t.nodeName === 'INPUT' && - t.getAttribute('type') === 'checkbox' && - t.parentNode.parentNode.parentNode.classList.contains('active') - ) { - return this.toggleSingleProxyConfig_(e); - - // Case 3: "Flip to incognito mode." - } else if (t.nodeName === 'BUTTON') { - return this.toggleIncognitoMode_(e); - - // Case 4: Click on something random: maybe changing active config group? - } else { - // Walk up the tree until we hit `form > fieldset` or fall off the top - while (t && (t.nodeName !== 'FIELDSET' || - t.parentNode.nodeName !== 'FORM')) { - t = t.parentNode; - } - if (t) { - this.changeActive_(t); - return false; - } - } - return true; - }, - - - /** - * Sets the form's active config group. - * - * @param {DOMElement} fieldset The configuration group to activate. - * @private - */ - changeActive_: function(fieldset) { - for (var i = 0; i < this.configGroups_.length; i++) { - var el = this.configGroups_[i]; - var radio = el.querySelector("input[type='radio']"); - if (el === fieldset) { - el.classList.add('active'); - radio.checked = true; - } else { - el.classList.remove('active'); - } - } - this.recalcDisabledInputs_(); - }, - - - /** - * Recalculates the `disabled` state of the form's input elements, based - * on the currently active group, and that group's contents. - * - * @private - */ - recalcDisabledInputs_: function() { - var i, j; - for (i = 0; i < this.configGroups_.length; i++) { - var el = this.configGroups_[i]; - var inputs = el.querySelectorAll( - "input:not([type='radio']), select, textarea"); - if (el.classList.contains('active')) { - for (j = 0; j < inputs.length; j++) { - inputs[j].removeAttribute('disabled'); - } - } else { - for (j = 0; j < inputs.length; j++) { - inputs[j].setAttribute('disabled', 'disabled'); - } - } - } - }, - - - /** - * Handler called in response to click on form's submission button. Generates - * the proxy configuration and passes it to `useCustomProxySettings`, or - * handles errors in user input. - * - * Proxy errors (and the browser action's badge) are cleared upon setting new - * values. - * - * @param {Event} e DOM event generated by the user's click. - * @private - */ - applyChanges_: function(e) { - e.preventDefault(); - e.stopPropagation(); - - if (this.isIncognitoMode_()) - this.config_.incognito = this.generateProxyConfig_(); - else - this.config_.regular = this.generateProxyConfig_(); - - chrome.proxy.settings.set( - {value: this.config_.regular, scope: 'regular'}, - this.callbackForRegularSettings_.bind(this)); - chrome.extension.sendRequest({type: 'clearError'}); - }, - - /** - * Called in response to setting a regular window's proxy settings: checks - * for `lastError`, and then sets incognito settings (if they exist). - * - * @private - */ - callbackForRegularSettings_: function() { - if (chrome.runtime.lastError) { - this.generateAlert_(chrome.i18n.getMessage('errorSettingRegularProxy')); - return; - } - if (this.config_.incognito) { - chrome.proxy.settings.set( - {value: this.config_.incognito, scope: 'incognito_persistent'}, - this.callbackForIncognitoSettings_.bind(this)); - } else { - ProxyFormController.setPersistedSettings(this.config_); - this.generateAlert_(chrome.i18n.getMessage('successfullySetProxy')); - } - }, - - /** - * Called in response to setting an incognito window's proxy settings: checks - * for `lastError` and sets a success message. - * - * @private - */ - callbackForIncognitoSettings_: function() { - if (chrome.runtime.lastError) { - this.generateAlert_(chrome.i18n.getMessage('errorSettingIncognitoProxy')); - return; - } - ProxyFormController.setPersistedSettings(this.config_); - this.generateAlert_( - chrome.i18n.getMessage('successfullySetProxy')); - }, - - /** - * Generates an alert overlay inside the proxy's popup, then closes the popup - * after a short delay. - * - * @param {string} msg The message to be displayed in the overlay. - * @param {?boolean} close Should the window be closed? Defaults to true. - * @private - */ - generateAlert_: function(msg, close) { - var success = document.createElement('div'); - success.classList.add('overlay'); - success.setAttribute('role', 'alert'); - success.textContent = msg; - document.body.appendChild(success); - - setTimeout(function() { success.classList.add('visible'); }, 10); - setTimeout(function() { - if (close === false) - success.classList.remove('visible'); - else - window.close(); - }, 4000); - }, - - - /** - * Parses the proxy configuration form, and generates a ProxyConfig object - * that can be passed to `useCustomProxyConfig`. - * - * @see http://code.google.com/chrome/extensions/trunk/proxy.html - * @return {ProxyConfig} The proxy configuration represented by the form. - * @private - */ - generateProxyConfig_: function() { - var active = document.getElementsByClassName('active')[0]; - switch (active.id) { - case ProxyFormController.ProxyTypes.SYSTEM: - return {mode: 'system'}; - case ProxyFormController.ProxyTypes.DIRECT: - return {mode: 'direct'}; - case ProxyFormController.ProxyTypes.PAC: - var pacScriptURL = this.pacURL; - var pacManual = this.manualPac; - if (pacScriptURL) - return {mode: 'pac_script', - pacScript: {url: pacScriptURL, mandatory: true}}; - else if (pacManual) - return {mode: 'pac_script', - pacScript: {data: pacManual, mandatory: true}}; - else - return {mode: 'auto_detect'}; - case ProxyFormController.ProxyTypes.FIXED: - var config = {mode: 'fixed_servers'}; - if (this.singleProxy) { - config.rules = { - singleProxy: this.singleProxy, - bypassList: this.bypassList - }; - } else { - config.rules = { - proxyForHttp: this.httpProxy, - proxyForHttps: this.httpsProxy, - proxyForFtp: this.ftpProxy, - fallbackProxy: this.fallbackProxy, - bypassList: this.bypassList - }; - } - return config; - } - }, - - - /** - * Sets the proper display classes based on the "Use the same proxy server - * for all protocols" checkbox. Expects to be called as an event handler - * when that field is clicked. - * - * @param {Event} e The `click` event to respond to. - * @private - */ - toggleSingleProxyConfig_: function(e) { - var checkbox = e.target; - if (checkbox.nodeName === 'INPUT' && - checkbox.getAttribute('type') === 'checkbox') { - if (checkbox.checked) - checkbox.parentNode.parentNode.classList.add('single'); - else - checkbox.parentNode.parentNode.classList.remove('single'); - } - }, - - - /** - * Returns the form's current incognito status. - * - * @return {boolean} True if the form is in incognito mode, false otherwise. - * @private - */ - isIncognitoMode_: function(e) { - return this.form_.parentNode.classList.contains('incognito'); - }, - - - /** - * Toggles the form's incognito mode. Saves the current state to an object - * property for later use, clears the form, and toggles the appropriate state. - * - * @param {Event} e The `click` event to respond to. - * @private - */ - toggleIncognitoMode_: function(e) { - var div = this.form_.parentNode; - var button = document.getElementsByTagName('button')[0]; - - // Cancel the button click. - e.preventDefault(); - e.stopPropagation(); - - // If we can't access Incognito settings, throw a message and return. - if (!this.isAllowedIncognitoAccess_) { - var msg = "I'm sorry, Dave, I'm afraid I can't do that. Give me access " + - "to Incognito settings by checking the checkbox labeled " + - "'Allow in Incognito mode', which is visible at " + - "chrome://extensions."; - this.generateAlert_(msg, false); - return; - } - - if (this.isIncognitoMode_()) { - // In incognito mode, switching to cognito. - this.config_.incognito = this.generateProxyConfig_(); - div.classList.remove('incognito'); - this.recalcFormValues_(this.config_.regular); - button.innerText = 'Configure incognito window settings.'; - } else { - // In cognito mode, switching to incognito. - this.config_.regular = this.generateProxyConfig_(); - div.classList.add('incognito'); - this.recalcFormValues_(this.config_.incognito); - button.innerText = 'Configure regular window settings.'; - } - }, - - - /** - * Sets the form's values based on a ProxyConfig. - * - * @param {!ProxyConfig} c The ProxyConfig object. - * @private - */ - recalcFormValues_: function(c) { - // Normalize `auto_detect` - if (c.mode === 'auto_detect') - c.mode = 'pac_script'; - // Activate one of the groups, based on `mode`. - this.changeActive_(document.getElementById(c.mode)); - // Populate the PAC script - if (c.pacScript) { - if (c.pacScript.url) - this.pacURL = c.pacScript.url; - } else { - this.pacURL = ''; - } - // Evaluate the `rules` - if (c.rules) { - var rules = c.rules; - if (rules.singleProxy) { - this.singleProxy = rules.singleProxy; - } else { - this.singleProxy = null; - this.httpProxy = rules.proxyForHttp; - this.httpsProxy = rules.proxyForHttps; - this.ftpProxy = rules.proxyForFtp; - this.fallbackProxy = rules.fallbackProxy; - } - this.bypassList = rules.bypassList; - } else { - this.singleProxy = null; - this.httpProxy = null; - this.httpsProxy = null; - this.ftpProxy = null; - this.fallbackProxy = null; - this.bypassList = ''; - } - }, - - - /** - * Handles the case in which this extension doesn't have the ability to - * control the Proxy settings, either because of an overriding policy - * or an extension with higher priority. - * - * @param {ProxyFormController.LevelOfControl} l The level of control this - * extension has over the proxy settings. - * @private - */ - handleLackOfControl_: function(l) { - var msg; - if (l === ProxyFormController.LevelOfControl.NO_ACCESS) - msg = chrome.i18n.getMessage('errorNoExtensionAccess'); - else if (l === ProxyFormController.LevelOfControl.OTHER_EXTENSION) - msg = chrome.i18n.getMessage('errorOtherExtensionControls'); - this.generateAlert_(msg); - }, - - - /** - * Handle the case in which errors have been generated outside the context - * of this popup. - * - * @private - */ - handleProxyErrors_: function() { - chrome.extension.sendRequest( - {type: 'getError'}, - this.handleProxyErrorHandlerResponse_.bind(this)); - }, - - /** - * Handles response from ProxyErrorHandler - * - * @param {{result: !string}} response The message sent in response to this - * popup's request. - */ - handleProxyErrorHandlerResponse_: function(response) { - if (response.result !== null) { - var error = JSON.parse(response.result); - console.error(error); - // TODO(mkwst): Do something more interesting - this.generateAlert_( - chrome.i18n.getMessage( - error.details ? 'errorProxyDetailedError' : 'errorProxyError', - [error.error, error.details]), - false); - } - } -};
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/jsunittest.js b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/jsunittest.js deleted file mode 100644 index 8e1eab03..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/jsunittest.js +++ /dev/null
@@ -1,964 +0,0 @@ -/* Jsunittest, version 0.6.0 - * (c) 2008 Dr Nic Williams - * - * Jsunittest is freely distributable under - * the terms of an MIT-style license. - * For details, see the web site: http://jsunittest.rubyforge.org - * - *--------------------------------------------------------------------------*/ - -var JsUnitTest = { - Version: '0.6.0', -}; - -var DrNicTest = { - Unit: {}, - inspect: function(object) { - try { - if (typeof object == "undefined") return 'undefined'; - if (object === null) return 'null'; - if (typeof object == "string") { - var useDoubleQuotes = arguments[1]; - var escapedString = this.gsub(object, /[\x00-\x1f\\]/, function(match) { - var character = String.specialChar[match[0]]; - return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); - }); - if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; - return "'" + escapedString.replace(/'/g, '\\\'') + "'"; - }; - return String(object); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - }, - $: function(element) { - if (arguments.length > 1) { - for (var i = 0, elements = [], length = arguments.length; i < length; i++) - elements.push(this.$(arguments[i])); - return elements; - } - if (typeof element == "string") - element = document.getElementById(element); - return element; - }, - gsub: function(source, pattern, replacement) { - var result = '', match; - replacement = arguments.callee.prepareReplacement(replacement); - - while (source.length > 0) { - if (match = source.match(pattern)) { - result += source.slice(0, match.index); - result += DrNicTest.String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - }, - scan: function(source, pattern, iterator) { - this.gsub(source, pattern, iterator); - return String(source); - }, - escapeHTML: function(data) { - return data.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); - }, - arrayfromargs: function(args) { - var myarray = new Array(); - var i; - - for (i=0;i<args.length;i++) - myarray[i] = args[i]; - - return myarray; - }, - hashToSortedArray: function(hash) { - var results = []; - for (key in hash) { - results.push([key, hash[key]]); - } - return results.sort(); - }, - flattenArray: function(array) { - var results = arguments[1] || []; - for (var i=0; i < array.length; i++) { - var object = array[i]; - if (object != null && typeof object == "object" && - 'splice' in object && 'join' in object) { - this.flattenArray(object, results); - } else { - results.push(object); - } - }; - return results; - }, - selectorMatch: function(expression, element) { - var tokens = []; - var patterns = { - // combinators must be listed first - // (and descendant needs to be last combinator) - laterSibling: /^\s*~\s*/, - child: /^\s*>\s*/, - adjacent: /^\s*\+\s*/, - descendant: /^\s/, - - // selectors follow - tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, - id: /^#([\w\-\*]+)(\b|$)/, - className: /^\.([\w\-\*]+)(\b|$)/, - pseudo: - /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/, - attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/, - attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ - }; - - var assertions = { - tagName: function(element, matches) { - return matches[1].toUpperCase() == element.tagName.toUpperCase(); - }, - - className: function(element, matches) { - return Element.hasClassName(element, matches[1]); - }, - - id: function(element, matches) { - return element.id === matches[1]; - }, - - attrPresence: function(element, matches) { - return Element.hasAttribute(element, matches[1]); - }, - - attr: function(element, matches) { - var nodeValue = Element.readAttribute(element, matches[1]); - return nodeValue && operators[matches[2]](nodeValue, matches[5] || matches[6]); - } - }; - var e = this.expression, ps = patterns, as = assertions; - var le, p, m; - - while (e && le !== e && (/\S/).test(e)) { - le = e; - for (var i in ps) { - p = ps[i]; - if (m = e.match(p)) { - // use the Selector.assertions methods unless the selector - // is too complex. - if (as[i]) { - tokens.push([i, Object.clone(m)]); - e = e.replace(m[0], ''); - } - } - } - } - - var match = true, name, matches; - for (var i = 0, token; token = tokens[i]; i++) { - name = token[0], matches = token[1]; - if (!assertions[name](element, matches)) { - match = false; break; - } - } - - return match; - }, - toQueryParams: function(query, separator) { - var query = query || window.location.search; - var match = query.replace(/^\s+/, '').replace(/\s+$/, '').match(/([^?#]*)(#.*)?$/); - if (!match) return { }; - - var hash = {}; - var parts = match[1].split(separator || '&'); - for (var i=0; i < parts.length; i++) { - var pair = parts[i].split('='); - if (pair[0]) { - var key = decodeURIComponent(pair.shift()); - var value = pair.length > 1 ? pair.join('=') : pair[0]; - if (value != undefined) value = decodeURIComponent(value); - - if (key in hash) { - var object = hash[key]; - var isArray = object != null && typeof object == "object" && - 'splice' in object && 'join' in object - if (!isArray) hash[key] = [hash[key]]; - hash[key].push(value); - } - else hash[key] = value; - } - }; - return hash; - }, - - String: { - interpret: function(value) { - return value == null ? '' : String(value); - } - } -}; - -DrNicTest.gsub.prepareReplacement = function(replacement) { - if (typeof replacement == "function") return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; -}; - -DrNicTest.Template = function(template, pattern) { - this.template = template; //template.toString(); - this.pattern = pattern || DrNicTest.Template.Pattern; -}; - -DrNicTest.Template.prototype.evaluate = function(object) { - if (typeof object.toTemplateReplacements == "function") - object = object.toTemplateReplacements(); - - return DrNicTest.gsub(this.template, this.pattern, function(match) { - if (object == null) return ''; - - var before = match[1] || ''; - if (before == '\\') return match[2]; - - var ctx = object, expr = match[3]; - var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; - match = pattern.exec(expr); - if (match == null) return before; - - while (match != null) { - var comp = (match[1].indexOf('[]') === 0) ? match[2].gsub('\\\\]', ']') : match[1]; - ctx = ctx[comp]; - if (null == ctx || '' == match[3]) break; - expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); - match = pattern.exec(expr); - } - - return before + DrNicTest.String.interpret(ctx); - }); -} - -DrNicTest.Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; -DrNicTest.Event = {}; -// written by Dean Edwards, 2005 -// with input from Tino Zijdel, Matthias Miller, Diego Perini -// namespaced by Dr Nic Williams 2008 - -// http://dean.edwards.name/weblog/2005/10/add-event/ -// http://dean.edwards.name/weblog/2005/10/add-event2/ -DrNicTest.Event.addEvent = function(element, type, handler) { - if (element.addEventListener) { - element.addEventListener(type, handler, false); - } else { - // assign each event handler a unique ID - if (!handler.$$guid) handler.$$guid = addEvent.guid++; - // create a hash table of event types for the element - if (!element.events) element.events = {}; - // create a hash table of event handlers for each element/event pair - var handlers = element.events[type]; - if (!handlers) { - handlers = element.events[type] = {}; - // store the existing event handler (if there is one) - if (element["on" + type]) { - handlers[0] = element["on" + type]; - } - } - // store the event handler in the hash table - handlers[handler.$$guid] = handler; - // assign a global event handler to do all the work - element["on" + type] = handleEvent; - } -}; -// a counter used to create unique IDs -DrNicTest.Event.addEvent.guid = 1; - -DrNicTest.Event.removeEvent = function(element, type, handler) { - if (element.removeEventListener) { - element.removeEventListener(type, handler, false); - } else { - // delete the event handler from the hash table - if (element.events && element.events[type]) { - delete element.events[type][handler.$$guid]; - } - } -}; - -DrNicTest.Event.handleEvent = function(event) { - var returnValue = true; - // grab the event object (IE uses a global event object) - event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); - // get a reference to the hash table of event handlers - var handlers = this.events[event.type]; - // execute each event handler - for (var i in handlers) { - this.$$handleEvent = handlers[i]; - if (this.$$handleEvent(event) === false) { - returnValue = false; - } - } - return returnValue; -}; - -DrNicTest.Event.fixEvent = function(event) { - // add W3C standard event methods - event.preventDefault = fixEvent.preventDefault; - event.stopPropagation = fixEvent.stopPropagation; - return event; -}; -DrNicTest.Event.fixEvent.preventDefault = function() { - this.returnValue = false; -}; -DrNicTest.Event.fixEvent.stopPropagation = function() { - this.cancelBubble = true; -}; - -DrNicTest.Unit.Logger = function(element) { - this.element = DrNicTest.$(element); - if (this.element) this._createLogTable(); -}; - -DrNicTest.Unit.Logger.prototype.start = function(testName) { - if (!this.element) return; - var tbody = this.element.getElementsByTagName('tbody')[0]; - tbody.innerHTML = tbody.innerHTML + '<tr><td>' + testName + '</td><td></td><td></td></tr>'; -}; - -DrNicTest.Unit.Logger.prototype.setStatus = function(status) { - var logline = this.getLastLogLine(); - logline.className = status; - var statusCell = logline.getElementsByTagName('td')[1]; - statusCell.innerHTML = status; -}; - -DrNicTest.Unit.Logger.prototype.finish = function(status, summary) { - if (!this.element) return; - this.setStatus(status); - this.message(summary); -}; - -DrNicTest.Unit.Logger.prototype.message = function(message) { - if (!this.element) return; - var cell = this.getMessageCell(); - cell.innerHTML = this._toHTML(message); -}; - -DrNicTest.Unit.Logger.prototype.summary = function(summary) { - if (!this.element) return; - var div = this.element.getElementsByTagName('div')[0]; - div.innerHTML = this._toHTML(summary); -}; - -DrNicTest.Unit.Logger.prototype.getLastLogLine = function() { - var tbody = this.element.getElementsByTagName('tbody')[0]; - var loglines = tbody.getElementsByTagName('tr'); - return loglines[loglines.length - 1]; -}; - -DrNicTest.Unit.Logger.prototype.getMessageCell = function() { - var logline = this.getLastLogLine(); - return logline.getElementsByTagName('td')[2]; -}; - -DrNicTest.Unit.Logger.prototype._createLogTable = function() { - var html = '<div class="logsummary">running...</div>' + - '<table class="logtable">' + - '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' + - '<tbody class="loglines"></tbody>' + - '</table>'; - this.element.innerHTML = html; -}; - -DrNicTest.Unit.Logger.prototype.appendActionButtons = function(actions) { - // actions = $H(actions); - // if (!actions.any()) return; - // var div = new Element("div", {className: 'action_buttons'}); - // actions.inject(div, function(container, action) { - // var button = new Element("input").setValue(action.key).observe("click", action.value); - // button.type = "button"; - // return container.insert(button); - // }); - // this.getMessageCell().insert(div); -}; - -DrNicTest.Unit.Logger.prototype._toHTML = function(txt) { - return DrNicTest.escapeHTML(txt).replace(/\n/g,"<br/>"); -}; -DrNicTest.Unit.MessageTemplate = function(string) { - var parts = []; - var str = DrNicTest.scan((string || ''), /(?=[^\\])\?|(?:\\\?|[^\?])+/, function(part) { - parts.push(part[0]); - }); - this.parts = parts; -}; - -DrNicTest.Unit.MessageTemplate.prototype.evaluate = function(params) { - var results = []; - for (var i=0; i < this.parts.length; i++) { - var part = this.parts[i]; - var result = (part == '?') ? DrNicTest.inspect(params.shift()) : part.replace(/\\\?/, '?'); - results.push(result); - }; - return results.join(''); -}; -// A generic function for performming AJAX requests -// It takes one argument, which is an object that contains a set of options -// All of which are outline in the comments, below -// From John Resig's book Pro JavaScript Techniques -// published by Apress, 2006-8 -DrNicTest.ajax = function( options ) { - - // Load the options object with defaults, if no - // values were provided by the user - options = { - // The type of HTTP Request - type: options.type || "POST", - - // The URL the request will be made to - url: options.url || "", - - // How long to wait before considering the request to be a timeout - timeout: options.timeout || 5000, - - // Functions to call when the request fails, succeeds, - // or completes (either fail or succeed) - onComplete: options.onComplete || function(){}, - onError: options.onError || function(){}, - onSuccess: options.onSuccess || function(){}, - - // The data type that'll be returned from the server - // the default is simply to determine what data was returned from the - // and act accordingly. - data: options.data || "" - }; - - // Create the request object - var xml = new XMLHttpRequest(); - - // Open the asynchronous POST request - xml.open(options.type, options.url, true); - - // We're going to wait for a request for 5 seconds, before giving up - var timeoutLength = 5000; - - // Keep track of when the request has been succesfully completed - var requestDone = false; - - // Initalize a callback which will fire 5 seconds from now, cancelling - // the request (if it has not already occurred). - setTimeout(function(){ - requestDone = true; - }, timeoutLength); - - // Watch for when the state of the document gets updated - xml.onreadystatechange = function(){ - // Wait until the data is fully loaded, - // and make sure that the request hasn't already timed out - if ( xml.readyState == 4 && !requestDone ) { - - // Check to see if the request was successful - if ( httpSuccess( xml ) ) { - - // Execute the success callback with the data returned from the server - options.onSuccess( httpData( xml, options.type ) ); - - // Otherwise, an error occurred, so execute the error callback - } else { - options.onError(); - } - - // Call the completion callback - options.onComplete(); - - // Clean up after ourselves, to avoid memory leaks - xml = null; - } - }; - - // Establish the connection to the server - xml.send(); - - // Determine the success of the HTTP response - function httpSuccess(r) { - try { - // If no server status is provided, and we're actually - // requesting a local file, then it was successful - return !r.status && location.protocol == "file:" || - - // Any status in the 200 range is good - ( r.status >= 200 && r.status < 300 ) || - - // Successful if the document has not been modified - r.status == 304 || - - // Safari returns an empty status if the file has not been modified - navigator.userAgent.indexOf("Safari") >= 0 && typeof r.status == "undefined"; - } catch(e){} - - // If checking the status failed, then assume that the request failed too - return false; - } - - // Extract the correct data from the HTTP response - function httpData(r,type) { - // Get the content-type header - var ct = r.getResponseHeader("content-type"); - - // If no default type was provided, determine if some - // form of XML was returned from the server - var data = !type && ct && ct.indexOf("xml") >= 0; - - // Get the XML Document object if XML was returned from - // the server, otherwise return the text contents returned by the server - data = type == "xml" || data ? r.responseXML : r.responseText; - - // If the specified type is "script", execute the returned text - // response as if it was JavaScript - if ( type == "script" ) - eval.call( window, data ); - - // Return the response data (either an XML Document or a text string) - return data; - } - -} -DrNicTest.Unit.Assertions = { - buildMessage: function(message, template) { - var args = DrNicTest.arrayfromargs(arguments).slice(2); - return (message ? message + '\n' : '') + - new DrNicTest.Unit.MessageTemplate(template).evaluate(args); - }, - - flunk: function(message) { - this.assertBlock(message || 'Flunked', function() { return false }); - }, - - assertBlock: function(message, block) { - try { - block.call(this) ? this.pass() : this.fail(message); - } catch(e) { this.error(e) } - }, - - assert: function(expression, message) { - message = this.buildMessage(message || 'assert', 'got <?>', expression); - this.assertBlock(message, function() { return expression }); - }, - - assertEqual: function(expected, actual, message) { - message = this.buildMessage(message || 'assertEqual', 'expected <?>, actual: <?>', expected, actual); - this.assertBlock(message, function() { return expected == actual }); - }, - - assertNotEqual: function(expected, actual, message) { - message = this.buildMessage(message || 'assertNotEqual', 'expected <?>, actual: <?>', expected, actual); - this.assertBlock(message, function() { return expected != actual }); - }, - - assertEnumEqual: function(expected, actual, message) { - message = this.buildMessage(message || 'assertEnumEqual', 'expected <?>, actual: <?>', expected, actual); - var expected_array = DrNicTest.flattenArray(expected); - var actual_array = DrNicTest.flattenArray(actual); - this.assertBlock(message, function() { - if (expected_array.length == actual_array.length) { - for (var i=0; i < expected_array.length; i++) { - if (expected_array[i] != actual_array[i]) return false; - }; - return true; - } - return false; - }); - }, - - assertEnumNotEqual: function(expected, actual, message) { - message = this.buildMessage(message || 'assertEnumNotEqual', '<?> was the same as <?>', expected, actual); - var expected_array = DrNicTest.flattenArray(expected); - var actual_array = DrNicTest.flattenArray(actual); - this.assertBlock(message, function() { - if (expected_array.length == actual_array.length) { - for (var i=0; i < expected_array.length; i++) { - if (expected_array[i] != actual_array[i]) return true; - }; - return false; - } - return true; - }); - }, - - assertHashEqual: function(expected, actual, message) { - message = this.buildMessage(message || 'assertHashEqual', 'expected <?>, actual: <?>', expected, actual); - var expected_array = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(expected)); - var actual_array = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(actual)); - var block = function() { - if (expected_array.length == actual_array.length) { - for (var i=0; i < expected_array.length; i++) { - if (expected_array[i] != actual_array[i]) return false; - }; - return true; - } - return false; - }; - this.assertBlock(message, block); - }, - - assertHashNotEqual: function(expected, actual, message) { - message = this.buildMessage(message || 'assertHashNotEqual', '<?> was the same as <?>', expected, actual); - var expected_array = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(expected)); - var actual_array = DrNicTest.flattenArray(DrNicTest.hashToSortedArray(actual)); - // from now we recursively zip & compare nested arrays - var block = function() { - if (expected_array.length == actual_array.length) { - for (var i=0; i < expected_array.length; i++) { - if (expected_array[i] != actual_array[i]) return true; - }; - return false; - } - return true; - }; - this.assertBlock(message, block); - }, - - assertIdentical: function(expected, actual, message) { - message = this.buildMessage(message || 'assertIdentical', 'expected <?>, actual: <?>', expected, actual); - this.assertBlock(message, function() { return expected === actual }); - }, - - assertNotIdentical: function(expected, actual, message) { - message = this.buildMessage(message || 'assertNotIdentical', 'expected <?>, actual: <?>', expected, actual); - this.assertBlock(message, function() { return expected !== actual }); - }, - - assertNull: function(obj, message) { - message = this.buildMessage(message || 'assertNull', 'got <?>', obj); - this.assertBlock(message, function() { return obj === null }); - }, - - assertNotNull: function(obj, message) { - message = this.buildMessage(message || 'assertNotNull', 'got <?>', obj); - this.assertBlock(message, function() { return obj !== null }); - }, - - assertUndefined: function(obj, message) { - message = this.buildMessage(message || 'assertUndefined', 'got <?>', obj); - this.assertBlock(message, function() { return typeof obj == "undefined" }); - }, - - assertNotUndefined: function(obj, message) { - message = this.buildMessage(message || 'assertNotUndefined', 'got <?>', obj); - this.assertBlock(message, function() { return typeof obj != "undefined" }); - }, - - assertNullOrUndefined: function(obj, message) { - message = this.buildMessage(message || 'assertNullOrUndefined', 'got <?>', obj); - this.assertBlock(message, function() { return obj == null }); - }, - - assertNotNullOrUndefined: function(obj, message) { - message = this.buildMessage(message || 'assertNotNullOrUndefined', 'got <?>', obj); - this.assertBlock(message, function() { return obj != null }); - }, - - assertMatch: function(expected, actual, message) { - message = this.buildMessage(message || 'assertMatch', 'regex <?> did not match <?>', expected, actual); - this.assertBlock(message, function() { return new RegExp(expected).exec(actual) }); - }, - - assertNoMatch: function(expected, actual, message) { - message = this.buildMessage(message || 'assertNoMatch', 'regex <?> matched <?>', expected, actual); - this.assertBlock(message, function() { return !(new RegExp(expected).exec(actual)) }); - }, - - assertHidden: function(element, message) { - message = this.buildMessage(message || 'assertHidden', '? isn\'t hidden.', element); - this.assertBlock(message, function() { return element.style.display == 'none' }); - }, - - assertInstanceOf: function(expected, actual, message) { - message = this.buildMessage(message || 'assertInstanceOf', '<?> was not an instance of the expected type', actual); - this.assertBlock(message, function() { return actual instanceof expected }); - }, - - assertNotInstanceOf: function(expected, actual, message) { - message = this.buildMessage(message || 'assertNotInstanceOf', '<?> was an instance of the expected type', actual); - this.assertBlock(message, function() { return !(actual instanceof expected) }); - }, - - assertRespondsTo: function(method, obj, message) { - message = this.buildMessage(message || 'assertRespondsTo', 'object doesn\'t respond to <?>', method); - this.assertBlock(message, function() { return (method in obj && typeof obj[method] == 'function') }); - }, - - assertRaise: function(exceptionName, method, message) { - message = this.buildMessage(message || 'assertRaise', '<?> exception expected but none was raised', exceptionName); - var block = function() { - try { - method(); - return false; - } catch(e) { - if (e.name == exceptionName) return true; - else throw e; - } - }; - this.assertBlock(message, block); - }, - - assertNothingRaised: function(method, message) { - try { - method(); - this.assert(true, "Expected nothing to be thrown"); - } catch(e) { - message = this.buildMessage(message || 'assertNothingRaised', '<?> was thrown when nothing was expected.', e); - this.flunk(message); - } - }, - - _isVisible: function(element) { - element = DrNicTest.$(element); - if(!element.parentNode) return true; - this.assertNotNull(element); - if(element.style && element.style.display == 'none') - return false; - - return arguments.callee.call(this, element.parentNode); - }, - - assertVisible: function(element, message) { - message = this.buildMessage(message, '? was not visible.', element); - this.assertBlock(message, function() { return this._isVisible(element) }); - }, - - assertNotVisible: function(element, message) { - message = this.buildMessage(message, '? was not hidden and didn\'t have a hidden parent either.', element); - this.assertBlock(message, function() { return !this._isVisible(element) }); - }, - - assertElementsMatch: function() { - var pass = true, expressions = DrNicTest.arrayfromargs(arguments); - var elements = expressions.shift(); - if (elements.length != expressions.length) { - message = this.buildMessage('assertElementsMatch', 'size mismatch: ? elements, ? expressions (?).', elements.length, expressions.length, expressions); - this.flunk(message); - pass = false; - } - for (var i=0; i < expressions.length; i++) { - var expression = expressions[i]; - var element = DrNicTest.$(elements[i]); - if (DrNicTest.selectorMatch(expression, element)) { - pass = true; - break; - } - message = this.buildMessage('assertElementsMatch', 'In index <?>: expected <?> but got ?', index, expression, element); - this.flunk(message); - pass = false; - }; - this.assert(pass, "Expected all elements to match."); - }, - - assertElementMatches: function(element, expression, message) { - this.assertElementsMatch([element], expression); - } -}; -DrNicTest.Unit.Runner = function(testcases) { - var argumentOptions = arguments[1] || {}; - var options = this.options = {}; - options.testLog = ('testLog' in argumentOptions) ? argumentOptions.testLog : 'testlog'; - options.resultsURL = this.queryParams.resultsURL; - options.testLog = DrNicTest.$(options.testLog); - - this.tests = this.getTests(testcases); - this.currentTest = 0; - this.logger = new DrNicTest.Unit.Logger(options.testLog); - - var self = this; - DrNicTest.Event.addEvent(window, "load", function() { - setTimeout(function() { - self.runTests(); - }, 0.1); - }); -}; - -DrNicTest.Unit.Runner.prototype.queryParams = DrNicTest.toQueryParams(); - -DrNicTest.Unit.Runner.prototype.portNumber = function() { - if (window.location.search.length > 0) { - var matches = window.location.search.match(/\:(\d{3,5})\//); - if (matches) { - return parseInt(matches[1]); - } - } - return null; -}; - -DrNicTest.Unit.Runner.prototype.getTests = function(testcases) { - var tests = [], options = this.options; - if (this.queryParams.tests) tests = this.queryParams.tests.split(','); - else if (options.tests) tests = options.tests; - else if (options.test) tests = [option.test]; - else { - for (testname in testcases) { - if (testname.match(/^test/)) tests.push(testname); - } - } - var results = []; - for (var i=0; i < tests.length; i++) { - var test = tests[i]; - if (testcases[test]) - results.push( - new DrNicTest.Unit.Testcase(test, testcases[test], testcases.setup, testcases.teardown) - ); - }; - return results; -}; - -DrNicTest.Unit.Runner.prototype.getResult = function() { - var results = { - tests: this.tests.length, - assertions: 0, - failures: 0, - errors: 0 - }; - - for (var i=0; i < this.tests.length; i++) { - var test = this.tests[i]; - results.assertions += test.assertions; - results.failures += test.failures; - results.errors += test.errors; - }; - return results; -}; - -DrNicTest.Unit.Runner.prototype.postResults = function() { - if (this.options.resultsURL) { - // new Ajax.Request(this.options.resultsURL, - // { method: 'get', parameters: this.getResult(), asynchronous: false }); - var results = this.getResult(); - var url = this.options.resultsURL + "?"; - url += "assertions="+ results.assertions + "&"; - url += "failures=" + results.failures + "&"; - url += "errors=" + results.errors; - DrNicTest.ajax({ - url: url, - type: 'GET' - }) - } -}; - -DrNicTest.Unit.Runner.prototype.runTests = function() { - var test = this.tests[this.currentTest], actions; - - if (!test) return this.finish(); - if (!test.isWaiting) this.logger.start(test.name); - test.run(); - var self = this; - if(test.isWaiting) { - this.logger.message("Waiting for " + test.timeToWait + "ms"); - // setTimeout(this.runTests.bind(this), test.timeToWait || 1000); - setTimeout(function() { - self.runTests(); - }, test.timeToWait || 1000); - return; - } - - this.logger.finish(test.status(), test.summary()); - if (actions = test.actions) this.logger.appendActionButtons(actions); - this.currentTest++; - // tail recursive, hopefully the browser will skip the stackframe - this.runTests(); -}; - -DrNicTest.Unit.Runner.prototype.finish = function() { - this.postResults(); - this.logger.summary(this.summary()); -}; - -DrNicTest.Unit.Runner.prototype.summary = function() { - return new DrNicTest.Template('#{tests} tests, #{assertions} assertions, #{failures} failures, #{errors} errors').evaluate(this.getResult()); -}; -DrNicTest.Unit.Testcase = function(name, test, setup, teardown) { - this.name = name; - this.test = test || function() {}; - this.setup = setup || function() {}; - this.teardown = teardown || function() {}; - this.messages = []; - this.actions = {}; -}; -// import DrNicTest.Unit.Assertions - -for (method in DrNicTest.Unit.Assertions) { - DrNicTest.Unit.Testcase.prototype[method] = DrNicTest.Unit.Assertions[method]; -} - -DrNicTest.Unit.Testcase.prototype.isWaiting = false; -DrNicTest.Unit.Testcase.prototype.timeToWait = 1000; -DrNicTest.Unit.Testcase.prototype.assertions = 0; -DrNicTest.Unit.Testcase.prototype.failures = 0; -DrNicTest.Unit.Testcase.prototype.errors = 0; -// DrNicTest.Unit.Testcase.prototype.isRunningFromRake = window.location.port == 4711; -DrNicTest.Unit.Testcase.prototype.isRunningFromRake = window.location.port; - -DrNicTest.Unit.Testcase.prototype.wait = function(time, nextPart) { - this.isWaiting = true; - this.test = nextPart; - this.timeToWait = time; -}; - -DrNicTest.Unit.Testcase.prototype.run = function(rethrow) { - try { - try { - if (!this.isWaiting) this.setup(); - this.isWaiting = false; - this.test(); - } finally { - if(!this.isWaiting) { - this.teardown(); - } - } - } - catch(e) { - if (rethrow) throw e; - this.error(e, this); - } -}; - -DrNicTest.Unit.Testcase.prototype.summary = function() { - var msg = '#{assertions} assertions, #{failures} failures, #{errors} errors\n'; - return new DrNicTest.Template(msg).evaluate(this) + - this.messages.join("\n"); -}; - -DrNicTest.Unit.Testcase.prototype.pass = function() { - this.assertions++; -}; - -DrNicTest.Unit.Testcase.prototype.fail = function(message) { - this.failures++; - var line = ""; - try { - throw new Error("stack"); - } catch(e){ - line = (/\.html:(\d+)/.exec(e.stack || '') || ['',''])[1]; - } - this.messages.push("Failure: " + message + (line ? " Line #" + line : "")); -}; - -DrNicTest.Unit.Testcase.prototype.info = function(message) { - this.messages.push("Info: " + message); -}; - -DrNicTest.Unit.Testcase.prototype.error = function(error, test) { - this.errors++; - this.actions['retry with throw'] = function() { test.run(true) }; - this.messages.push(error.name + ": "+ error.message + "(" + DrNicTest.inspect(error) + ")"); -}; - -DrNicTest.Unit.Testcase.prototype.status = function() { - if (this.failures > 0) return 'failed'; - if (this.errors > 0) return 'error'; - return 'passed'; -}; - -DrNicTest.Unit.Testcase.prototype.benchmark = function(operation, iterations) { - var startAt = new Date(); - (iterations || 1).times(operation); - var timeTaken = ((new Date())-startAt); - this.info((arguments[2] || 'Operation') + ' finished ' + - iterations + ' iterations in ' + (timeTaken/1000)+'s' ); - return timeTaken; -}; - -Test = DrNicTest
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/proxy_form_controller_test.html b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/proxy_form_controller_test.html deleted file mode 100644 index 096e709..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/proxy_form_controller_test.html +++ /dev/null
@@ -1,113 +0,0 @@ -<!doctype html> -<html> -<head> - <title>Popup for Proxy API Test</title> - <link rel="stylesheet" type="text/css" href="./unittest.css"> - <script src="./jsunittest.js"></script> - <script src="../proxy_form_controller.js"></script> -</head> -<body> - <h1>Proxy Configuration Unit Tests</h1> - - <h2>ProxyFormController</h2> - <div id="proxyformcontrollerlog"></div> - - <div id="fixture"> - <form id="proxyForm"> - <fieldset id="system"> - <legend>System Settings</legend> - <input type="radio" name="proxyType" id="proxyTypeSystem" value="system"> - <label for="proxyTypeSystem">Use the <em>system's proxy settings</em>.</label> - </fieldset> - <fieldset id="direct"> - <legend>Direct Connection</legend> - <input type="radio" name="proxyType" id="proxyTypeDirect" value="direct"> - <label for="proxyTypeDirect">Your computer is <em>directly connected</em> to the internet; no need for a proxy.</label> - </fieldset> - <fieldset id="pac_script"> - <legend>Automatic Configuration</legend> - <input type="radio" name="proxyType" id="proxyTypeAutoconfig" value="autoconfig"> - <label for="proxyTypeAutoconfig">Your proxy supports <em>automatic configuration</em>.</label> - - <section> - <label for="autoconfigURL">Autoconfiguration URL (PAC file)</label> - <input type="url" name="autoconfigURL" id="autoconfigURL"> - <input type="hidden" name="autoconfigData" id="autoconfigData"> - </section> - </fieldset> - <fieldset id="fixed_servers"> - <legend>Manual Proxy</legend> - <input type="radio" name="proxyType" id="proxyTypeManual" value="manual"> - <label for="proxyTypeManual">Configure your proxy settings <em>manually</em>.</label> - <section> - <fieldset> - <legend>HTTP</legend> - <label for="proxyHostHttp">Host</label> - <select id="proxySchemeHttp" name="proxySchemeHttp"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostHttp" id="proxyHostHttp"> - - <label for="proxyPortHttp">Port</label> - <input type="number" min="1" step="1" name="proxyPortHttp" id="proxyPortHttp"> - - <input type="checkbox" name="singleProxyForEverything" id="singleProxyForEverything"> - <label for="singleProxyForEverything">Use the same proxy server for all protocols</label> - </fieldset> - <fieldset> - <legend>HTTPS</legend> - <label for="proxyHostHttps">Host</label> - <select id="proxySchemeHttps" name="proxySchemeHttps"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostHttps" id="proxyHostHttps"> - - <label for="proxyPortHttps">Port</label> - <input type="number" min="1" step="1" name="proxyPortHttps" id="proxyPortHttps"> - </fieldset> - <fieldset> - <legend>FTP</legend> - <label for="proxyHostFtp">Host</label> - <select id="proxySchemeFtp" name="proxySchemeFtp"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostFtp" id="proxyHostFtp"> - - <label for="proxyPortFtp">Port</label> - <input type="number" min="1" step="1" name="proxyPortFtp" id="proxyPortFtp"> - </fieldset> - <fieldset> - <legend>Fallback</legend> - <label for="proxyHostFallback">Host</label> - <select id="proxySchemeFallback" name="proxySchemeFallback"> - <option selected value="http">http://</option> - <option value="https">https://</option> - <option value="socks4">socks4://</option> - <option value="socks5">socks5://</option> - </select> - <input type="text" name="proxyHostFallback" id="proxyHostFallback"> - - <label for="proxyPortFallback">Port</label> - <input type="number" min="1" step="1" name="proxyPortFallback" id="proxyPortFallback"> - </fieldset> - <fieldset> - <label for="bypassList">Bypass proxy for these hosts:</label> - <textarea id="bypassList" name="bypassList" placeholder="localhost,192.168.1.1/16, .example.com"></textarea> - </fieldset> - </section> - </fieldset> - <input type="submit" value="Save proxy settings"> - </form> - </div> - <script src="./proxy_form_controller_test.js"></script> -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/proxy_form_controller_test.js b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/proxy_form_controller_test.js deleted file mode 100644 index f778ec9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/proxy_form_controller_test.js +++ /dev/null
@@ -1,513 +0,0 @@ -// Copyright (c) 2011 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. - -// Stub out the `chrome.proxy`, `chrome.i18n`, and `chrome.extension` APIs -chrome = chrome || { - proxy: { - settings: { - get: function() {}, - clear: function() {}, - set: function() {} - } - }, - i18n: { - getMessage: function(x) { return x; } - }, - extension: { - sendRequest: function() {}, - isAllowedIncognitoAccess: function(funk) { - funk(true); - } - } -}; - -var fixture = document.getElementById('fixture'); -var baselineHTML = fixture.innerHTML; -var groupIDs = [ProxyFormController.ProxyTypes.DIRECT, - ProxyFormController.ProxyTypes.SYSTEM, - ProxyFormController.ProxyTypes.PAC, - ProxyFormController.ProxyTypes.FIXED]; - -var mockFunctionFactory = function(returnValue, logging) { - var called = []; - returnValue = returnValue || null; - - var funky = function() { - called.push(arguments); - if (arguments[1] && typeof(arguments[1]) === 'function') { - var funk = arguments[1]; - funk(returnValue); - } - return returnValue; - }; - funky.getCallList = function() { return called; }; - funky.getValue = function() { return returnValue; }; - return funky; -}; - -var proxyform = new Test.Unit.Runner({ - setup: function() { - fixture.innerHTML = baselineHTML; - this.controller_ = new ProxyFormController('proxyForm'); - this.clickEvent_ = document.createEvent('MouseEvents'); - this.clickEvent_.initMouseEvent('click', true, true, window, - 0, 0, 0, 0, 0, false, false, false, false, 0, null); - // Reset mock functions. - chrome.proxy = { - settings: { - get: mockFunctionFactory({ - value: {mode: 'system' }, - levelOfControl: 'controllable_by_this_extension' }), - clear: mockFunctionFactory({ - value: {mode: 'system' }, - levelOfControl: 'controllable_by_this_extension' }), - set: mockFunctionFactory({ - value: {mode: 'system' }, - levelOfControl: 'controllable_by_this_extension' }) - } - }; - }, - - teardown: function() { - fixture.removeChild(fixture.childNodes[0]); - delete(this.controller_); - }, - - // Clicking on various bits of the interface should set correct classes, - // and select correct radio buttons. - testActivationClicks: function() { - var self = this; - var i; - groupIDs.forEach(function(id) { - var group = document.getElementById(id); - var all = group.querySelectorAll('*'); - for (i = 0; i < all.length; i++) { - group.classList.remove('active'); - all[i].dispatchEvent(self.clickEvent_); - self.assert(group.classList.contains('active')); - } - }); - }, - - // Elements inside an active group should not be disabled, and vice versa - testDisabledElements: function() { - var self = this; - var i, j; - groupIDs.forEach(function(id) { - var group = document.getElementById(id); - var all = group.querySelectorAll('*'); - // First, check that activating a group enables its form elements - for (i = 0; i < all.length; i++) { - group.classList.remove('active'); - var inputs = group.querySelectorAll('input:not([type="radio"]),select'); - for (j = 0; j < inputs.length; j++) { - inputs[j].setAttribute('disabled', 'disabled'); - } - all[i].dispatchEvent(self.clickEvent_); - for (j = 0; j < inputs.length; j++) { - self.assert(!inputs[j].hasAttribute('disabled')); - } - } - }); - }, - - // Clicking the "Use single proxy" checkbox should set the correct - // classes on the form. - testSingleProxyToggle: function() { - var group = document.getElementById( - ProxyFormController.ProxyTypes.FIXED); - var checkbox = document.getElementById('singleProxyForEverything'); - var section = checkbox.parentNode.parentNode; - // Checkbox only works in active group, `testActivationClicks` tests - // the inactive click behavior. - group.classList.add('active'); - - checkbox.checked = false; - checkbox.dispatchEvent(this.clickEvent_); - this.assert(section.classList.contains('single')); - checkbox.dispatchEvent(this.clickEvent_); - this.assert(!section.classList.contains('single')); - }, - - // On instantiation, ProxyFormController should read the current state - // from `chrome.proxy.settings.get`, and react accordingly. - // Let's see if that happens with the next four sets of assertions. - testSetupFormSystem: function() { - chrome.proxy.settings.get = mockFunctionFactory({ - value: {mode: 'system'}, - levelOfControl: 'controllable_by_this_extension' - }); - - fixture.innerHTML = baselineHTML; - this.controller_ = new ProxyFormController('proxyForm'); - // Wait for async calls to fire - this.wait(100, function() { - this.assertEqual( - 6, - chrome.proxy.settings.get.getCallList().length); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.SYSTEM) - .classList.contains('active')); - }); - }, - - testSetupFormDirect: function() { - chrome.proxy.settings.get = - mockFunctionFactory({value: {mode: 'direct'}, - levelOfControl: 'controllable_by_this_extension'}, true); - - fixture.innerHTML = baselineHTML; - this.controller_ = new ProxyFormController('proxyForm'); - // Wait for async calls to fire - this.wait(100, function() { - this.assertEqual( - 2, - chrome.proxy.settings.get.getCallList().length); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.DIRECT) - .classList.contains('active')); - }); - }, - - testSetupFormPac: function() { - chrome.proxy.settings.get = - mockFunctionFactory({value: {mode: 'pac_script' }, - levelOfControl: 'controllable_by_this_extension'}); - - fixture.innerHTML = baselineHTML; - this.controller_ = new ProxyFormController('proxyForm'); - // Wait for async calls to fire - this.wait(100, function() { - this.assertEqual( - 2, - chrome.proxy.settings.get.getCallList().length); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.PAC) - .classList.contains('active')); - }); - }, - - testSetupFormFixed: function() { - chrome.proxy.settings.get = - mockFunctionFactory({value: {mode: 'fixed_servers' }, - levelOfControl: 'controllable_by_this_extension'}); - - fixture.innerHTML = baselineHTML; - this.controller_ = new ProxyFormController('proxyForm'); - // Wait for async calls to fire - this.wait(100, function() { - this.assertEqual( - 2, - chrome.proxy.settings.get.getCallList().length); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.FIXED) - .classList.contains('active')); - }); - }, - - // Test that `recalcFormValues_` correctly sets DOM field values when - // given a `ProxyConfig` structure - testRecalcFormValuesGroups: function() { - // Test `AUTO` normalization to `PAC` - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.AUTO, - rules: {}, - pacScript: '' - }); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.PAC) - .classList.contains('active')); - - // DIRECT - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.DIRECT, - rules: {}, - pacScript: '' - }); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.DIRECT) - .classList.contains('active')); - - // FIXED - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.FIXED, - rules: {}, - pacScript: '' - }); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.FIXED) - .classList.contains('active')); - - // PAC - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.PAC, - rules: {}, - pacScript: '' - }); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.PAC) - .classList.contains('active')); - - // SYSTEM - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.SYSTEM, - rules: {}, - pacScript: '' - }); - this.assert( - document.getElementById(ProxyFormController.ProxyTypes.SYSTEM) - .classList.contains('active')); - }, - - testRecalcFormValuesFixedSingle: function() { - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.FIXED, - rules: { - singleProxy: { - scheme: 'socks5', - host: 'singleproxy.example.com', - port: '1234' - } - } - }); - var single = this.controller_.singleProxy; - this.assertEqual('socks5', single.scheme); - this.assertEqual('singleproxy.example.com', single.host); - this.assertEqual(1234, single.port); - }, - - testRecalcFormValuesPacScript: function() { - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.PAC, - rules: {}, - pacScript: {url: 'http://example.com/this/is/a/pac.script'} - }); - this.assertEqual( - 'http://example.com/this/is/a/pac.script', - document.getElementById('autoconfigURL').value); - }, - - testRecalcFormValuesSingle: function() { - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.FIXED, - rules: { - singleProxy: { - scheme: 'https', - host: 'example.com', - port: 80 - } - } - }); - // Single! - this.assert( - document.querySelector('#' + ProxyFormController.ProxyTypes.FIXED + - ' > section').classList.contains('single')); - - var single = this.controller_.singleProxy; - this.assertEqual('https', single.scheme); - this.assertEqual('example.com', single.host); - this.assertEqual(80, single.port); - }, - - testRecalcFormValuesMultiple: function() { - this.controller_.recalcFormValues_({ - mode: ProxyFormController.ProxyTypes.FIXED, - rules: { - proxyForHttp: { - scheme: 'http', - host: 'http.example.com', - port: 1 - }, - proxyForHttps: { - scheme: 'https', - host: 'https.example.com', - port: 2 - }, - proxyForFtp: { - scheme: 'socks4', - host: 'socks4.example.com', - port: 3 - }, - fallbackProxy: { - scheme: 'socks5', - host: 'socks5.example.com', - port: 4 - } - } - }); - // Not Single! - this.assert( - !document.querySelector('#' + ProxyFormController.ProxyTypes.FIXED - + ' > section').classList.contains('single')); - var server = this.controller_.singleProxy; - this.assertNull(server); - - server = this.controller_.httpProxy; - this.assertEqual('http', server.scheme); - this.assertEqual('http.example.com', server.host); - this.assertEqual(1, server.port); - - server = this.controller_.httpsProxy; - this.assertEqual('https', server.scheme); - this.assertEqual('https.example.com', server.host); - this.assertEqual(2, server.port); - - server = this.controller_.ftpProxy; - this.assertEqual('socks4', server.scheme); - this.assertEqual('socks4.example.com', server.host); - this.assertEqual(3, server.port); - - server = this.controller_.fallbackProxy; - this.assertEqual('socks5', server.scheme); - this.assertEqual('socks5.example.com', server.host); - this.assertEqual(4, server.port); - }, - - testBypassList: function() { - this.controller_.bypassList = ['1.example.com', - '2.example.com', - '3.example.com']; - this.assertEnumEqual( - document.getElementById('bypassList').value, - '1.example.com, 2.example.com, 3.example.com'); - this.assertEnumEqual( - this.controller_.bypassList, - ['1.example.com', '2.example.com', '3.example.com']); - }, - - // Test that "system" rules are correctly generated - testProxyRulesGenerationSystem: function() { - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.SYSTEM)); - - this.assertHashEqual( - {mode: 'system'}, - this.controller_.generateProxyConfig_()); - }, - - // Test that "direct" rules are correctly generated - testProxyRulesGenerationDirect: function() { - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.DIRECT)); - - this.assertHashEqual( - {mode: 'direct'}, - this.controller_.generateProxyConfig_()); - }, - - // Test that auto detection rules are correctly generated when "automatic" - // is selected, and no PAC file URL is given - testProxyRulesGenerationAuto: function() { - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.PAC)); - - this.assertHashEqual( - {mode: 'auto_detect'}, - this.controller_.generateProxyConfig_()); - }, - - // Test that PAC URL rules are correctly generated when "automatic" - // is selected, and a PAC file URL is given - testProxyRulesGenerationPacURL: function() { - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.PAC)); - this.controller_.pacURL = 'http://example.com/pac.pac'; - var result = this.controller_.generateProxyConfig_(); - this.assertEqual('pac_script', result.mode); - this.assertEqual('http://example.com/pac.pac', result.pacScript.url); - }, - - // Manual PAC definitions - testProxyRulesGenerationPacData: function() { - var pacData = 'function FindProxyForURL(url,host) { return "DIRECT"; }'; - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.PAC)); - this.controller_.manualPac = pacData; - var result = this.controller_.generateProxyConfig_(); - this.assertEqual('pac_script', result.mode); - this.assertEqual(pacData, result.pacScript.data); - }, - - // PAC URLs override manual PAC definitions - testProxyRulesGenerationPacURLOverridesData: function() { - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.PAC)); - this.controller_.pacURL = 'http://example.com/pac.pac'; - this.controller_.manualPac = - 'function FindProxyForURL(url,host) { return "DIRECT"; }'; - var result = this.controller_.generateProxyConfig_(); - this.assertEqual('pac_script', result.mode); - this.assertEqual('http://example.com/pac.pac', result.pacScript.url); - }, - - // Test that fixed, manual servers are correctly transformed into a - // `ProxyRules` structure. - testProxyRulesGenerationSingle: function() { - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.FIXED)); - - this.controller_.singleProxy = { - scheme: 'http', - host: 'example.com', - port: '80' - }; - - var result = this.controller_.generateProxyConfig_(); - this.assertEqual('fixed_servers', result.mode); - this.assertEqual('http', result.rules.singleProxy.scheme); - this.assertEqual('example.com', result.rules.singleProxy.host); - this.assertEqual(80, result.rules.singleProxy.port); - this.assertEqual(undefined, result.rules.proxyForHttp); - this.assertEqual(undefined, result.rules.proxyForHttps); - this.assertEqual(undefined, result.rules.proxyForFtp); - this.assertEqual(undefined, result.rules.fallbackProxy); - }, - - // Test that proxy configuration rules are correctly generated - // for separate manually entered servers. - testProxyRulesGenerationSeparate: function() { - this.controller_.changeActive_( - document.getElementById(ProxyFormController.ProxyTypes.FIXED)); - - this.controller_.singleProxy = false; - this.controller_.httpProxy = { - scheme: 'http', - host: 'http.example.com', - port: 80 - }; - this.controller_.httpsProxy = { - scheme: 'https', - host: 'https.example.com', - port: 443 - }; - this.controller_.ftpProxy = { - scheme: 'socks4', - host: 'ftp.example.com', - port: 80 - }; - this.controller_.fallbackProxy = { - scheme: 'socks5', - host: 'fallback.example.com', - port: 80 - }; - - var result = this.controller_.generateProxyConfig_(); - this.assertEqual('fixed_servers', result.mode); - this.assertEqual(undefined, result.rules.singleProxy); - this.assertEqual('http', result.rules.proxyForHttp.scheme); - this.assertEqual('http.example.com', result.rules.proxyForHttp.host); - this.assertEqual('80', result.rules.proxyForHttp.port); - this.assertEqual('https', result.rules.proxyForHttps.scheme); - this.assertEqual('https.example.com', result.rules.proxyForHttps.host); - this.assertEqual('443', result.rules.proxyForHttps.port); - this.assertEqual('socks4', result.rules.proxyForFtp.scheme); - this.assertEqual('ftp.example.com', result.rules.proxyForFtp.host); - this.assertEqual('80', result.rules.proxyForFtp.port); - this.assertEqual('socks5', result.rules.fallbackProxy.scheme); - this.assertEqual('fallback.example.com', result.rules.fallbackProxy.host); - this.assertEqual('80', result.rules.fallbackProxy.port); - } -}, { testLog: 'proxyformcontrollerlog' }); - -var c = new ProxyFormController('proxyForm');
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/unittest.css b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/unittest.css deleted file mode 100644 index d62b1c58..0000000 --- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/test/unittest.css +++ /dev/null
@@ -1,58 +0,0 @@ -body, div, p, h1, h2, h3, ul, ol, span, a, table, td, form, img, li { - font-family: sans-serif; -} - -body { - font-size:0.8em; -} - -#log { - padding-bottom: 1em; - border-bottom: 2px solid #000; - margin-bottom: 2em; -} - -.logsummary { - margin-top: 1em; - margin-bottom: 1em; - padding: 1ex; - border: 1px solid #000; - font-weight: bold; -} - -.logtable { - width:100%; - border-collapse: collapse; - border: 1px dotted #666; -} - -.logtable td, .logtable th { - text-align: left; - padding: 3px 8px; - border: 1px dotted #666; -} - -.logtable .passed { - background-color: #cfc; -} - -.logtable .failed, .logtable .error { - background-color: #fcc; -} - -.logtable .warning { - background-color: #FC6; -} - -.logtable td div.action_buttons { - display: inline; -} - -.logtable td div.action_buttons input { - margin: 0 5px; - font-size: 10px; -} - -#fixture { - display: none; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel128.png b/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel128.png deleted file mode 100644 index 8ec46c1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel16.png b/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel16.png deleted file mode 100644 index 5dad8df3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel19-active.png b/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel19-active.png deleted file mode 100644 index 35e6df2..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel19-active.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel19.png b/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel19.png deleted file mode 100644 index 201831f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel256.png b/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel256.png deleted file mode 100644 index 7270b1f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel256.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel48.png b/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel48.png deleted file mode 100644 index e35886a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/SpeakSel48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/background.js b/chrome/common/extensions/docs/examples/extensions/speak_selection/background.js deleted file mode 100644 index a67629a..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/background.js +++ /dev/null
@@ -1,83 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -var lastUtterance = ''; -var speaking = false; -var globalUtteranceIndex = 0; - -if (localStorage['lastVersionUsed'] != '1') { - localStorage['lastVersionUsed'] = '1'; - chrome.tabs.create({ - url: chrome.extension.getURL('options.html') - }); -} - -function speak(utterance) { - if (speaking && utterance == lastUtterance) { - chrome.tts.stop(); - return; - } - - speaking = true; - lastUtterance = utterance; - globalUtteranceIndex++; - var utteranceIndex = globalUtteranceIndex; - - chrome.browserAction.setIcon({path: 'SpeakSel19-active.png'}); - - var rate = localStorage['rate'] || 1.0; - var pitch = localStorage['pitch'] || 1.0; - var volume = localStorage['volume'] || 1.0; - var voice = localStorage['voice']; - chrome.tts.speak( - utterance, - {voiceName: voice, - rate: parseFloat(rate), - pitch: parseFloat(pitch), - volume: parseFloat(volume), - onEvent: function(evt) { - if (evt.type == 'end' || - evt.type == 'interrupted' || - evt.type == 'cancelled' || - evt.type == 'error') { - if (utteranceIndex == globalUtteranceIndex) { - speaking = false; - chrome.browserAction.setIcon({path: 'SpeakSel19.png'}); - } - } - } - }); -} - -function initBackground() { - loadContentScriptInAllTabs(); - - var defaultKeyString = getDefaultKeyString(); - var keyString = localStorage['speakKey']; - if (keyString == undefined) { - keyString = defaultKeyString; - localStorage['speakKey'] = keyString; - } - sendKeyToAllTabs(keyString); - - chrome.extension.onRequest.addListener( - function(request, sender, sendResponse) { - if (request['init']) { - sendResponse({'key': localStorage['speakKey']}); - } else if (request['speak']) { - speak(request['speak']); - } - }); - - chrome.browserAction.onClicked.addListener( - function(tab) { - chrome.tabs.sendRequest( - tab.id, - {'speakSelection': true}); - }); -} - -initBackground();
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/content_script.js b/chrome/common/extensions/docs/examples/extensions/speak_selection/content_script.js deleted file mode 100644 index 69f8879..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/content_script.js +++ /dev/null
@@ -1,56 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -var speakKeyStr; - -function speakSelection() { - var focused = document.activeElement; - var selectedText; - if (focused) { - try { - selectedText = focused.value.substring( - focused.selectionStart, focused.selectionEnd); - } catch (err) { - } - } - if (selectedText == undefined) { - var sel = window.getSelection(); - var selectedText = sel.toString(); - } - chrome.extension.sendRequest({'speak': selectedText}); -} - -function onExtensionMessage(request) { - if (request['speakSelection'] != undefined) { - if (!document.hasFocus()) { - return; - } - speakSelection(); - } else if (request['key'] != undefined) { - speakKeyStr = request['key']; - } -} - -function initContentScript() { - chrome.extension.onRequest.addListener(onExtensionMessage); - chrome.extension.sendRequest({'init': true}, onExtensionMessage); - - document.addEventListener('keydown', function(evt) { - if (!document.hasFocus()) { - return true; - } - var keyStr = keyEventToString(evt); - if (keyStr == speakKeyStr && speakKeyStr.length > 0) { - speakSelection(); - evt.stopPropagation(); - evt.preventDefault(); - return false; - } - return true; - }, false); -} - -initContentScript();
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/keycodes.js b/chrome/common/extensions/docs/examples/extensions/speak_selection/keycodes.js deleted file mode 100644 index edea93e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/keycodes.js +++ /dev/null
@@ -1,94 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -var KEY_MAP = { - 12: 'Clear', - 14: 'Enter', - 33: 'PgUp', - 34: 'PgDown', - 35: 'End', - 36: 'Home', - 37: 'Left', - 38: 'Up', - 39: 'Right', - 40: 'Down', - 45: 'Insert', - 46: 'Delete', - 96: 'Numpad0', - 97: 'Numpad1', - 98: 'Numpad2', - 99: 'Numpad3', - 100: 'Numpad4', - 101: 'Numpad5', - 102: 'Numpad6', - 103: 'Numpad7', - 104: 'Numpad8', - 105: 'Numpad9', - 106: '*', - 107: 'Plus', - 108: '_', - 109: '-', - 111: '/', - 112: 'F1', - 113: 'F2', - 114: 'F3', - 115: 'F4', - 116: 'F5', - 117: 'F6', - 118: 'F7', - 119: 'F8', - 120: 'F9', - 121: 'F10', - 122: 'F11', - 123: 'F12', - 124: 'F13', - 125: 'F14', - 126: 'F15', - 186: ';', - 187: '=', - 188: ',', - 189: '-', - 190: '.', - 191: '/', - 192: '`', - 219: '[', - 221: ']' -}; - -var isMac = (navigator.appVersion.indexOf("Mac") != -1); - -function keyEventToString(evt) { - var tokens = []; - if (evt.ctrlKey) { - tokens.push('Control'); - } - if (evt.altKey) { - tokens.push(isMac ? 'Option' : 'Alt'); - } - if (evt.metaKey) { - tokens.push(isMac ? 'Command' : 'Meta'); - } - if (evt.shiftKey) { - tokens.push('Shift'); - } - if (evt.keyCode >= 48 && evt.keyCode <= 90) { - tokens.push(String.fromCharCode(evt.keyCode)); - } else if (KEY_MAP[evt.keyCode]) { - tokens.push(KEY_MAP[evt.keyCode]); - } else { - return ''; - } - return tokens.join('+'); -} - -function getDefaultKeyString() { - return keyEventToString({ - keyCode: 83, // 's' - shiftKey: true, - altKey: true, - ctrlKey: true, - metaKey: false}); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/manifest.json b/chrome/common/extensions/docs/examples/extensions/speak_selection/manifest.json deleted file mode 100644 index fed3608..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/manifest.json +++ /dev/null
@@ -1,49 +0,0 @@ -{ - "name": "Speak Selection", - "version": "1.1", - "description": "Speaks the current selection out loud.", - "permissions": [ - "<all_urls>", - "tts", - "tabs" - ], - - "background": { - "scripts": [ - "keycodes.js", - "tabs.js", - "background.js" - ] - }, - - "browser_action": { - "default_icon": "SpeakSel19.png", - "default_title": "Speak Selection" - }, - - "options_page": "options.html", - - "minimum_chrome_version": "14", - - "content_scripts": [ - { - "matches": [ - "<all_urls>" - ], - "all_frames": true, - "js": [ - "keycodes.js", - "content_script.js" - ] - } - ], - - "icons": { - "16": "SpeakSel16.png", - "48": "SpeakSel48.png", - "128": "SpeakSel128.png", - "256": "SpeakSel256.png" - }, - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/options.html b/chrome/common/extensions/docs/examples/extensions/speak_selection/options.html deleted file mode 100644 index f52ce7e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/options.html +++ /dev/null
@@ -1,152 +0,0 @@ -<html> -<head> - <title>Speak Selection Options</title> - <style> - body { - font-family: arial, helvetica, sans-serif; - } - .banner { - width: 100%; - float: left; - } - .banner_left { - padding: 8px; - float: left; - } - .banner_right { - padding: 8px; - } - .body_wrapper { - width: 100%; - float: left; - } - .body_left { - border: 0; - padding: 0; - margin: 0; - width: 50%; - float: left; - } - .body_right { - border: 0; - padding: 0; - margin: 0; - width: 46%; - float: left; - } - .body_inner { - padding: 0 32px; - } - .browser_action { - vertical-align: middle; - margin: 0 2px 3px 2px; - } - .ctrl_label { - width: 100px; - float: left; - } - .ctrl_wrap { - margin: 18px 8px; - } - .ctrl { - width: 200px; - } - #hotkey { - font-size: 16px; - width: 15em; - margin-left: 12px; - } - #test { - } - #defaults { - margin-left: 24px; - } - </style> - <script src="keycodes.js"></script> - <script src="tabs.js"></script> - <script src="options.js"></script> - <script src="content_script.js"></script> -</head> -<body> - -<div class="banner"> - <div class="banner_left"> - <img src="SpeakSel128.png" class="logo" alt=""> - </div> - <div class="banner_right"> - <h1>Speak Selection</h1> - <p> - This extension lets you use Chrome's text-to-speech (TTS) capabilities - to speak any text you find on the web. - </p> - </div> -</div> - -<div class="body_wrapper"> - <div class="body_left"> - <div class="body_inner"> - <h2>Speech Settings</h2> - - <div class="ctrl_label"> - <label for="voice">Voice:</label> - </div> - <div class="ctrl_wrap"> - <select id="voice" class="ctrl"></select> - </div> - - <div class="ctrl_label"> - <label for="rate">Rate:</label> - </div> - <div class="ctrl_wrap"> - <input id="rate" type="range" class="ctrl" - min=0.5 max=2.0 step=0.1 value=1.0></input> - </div> - - <div class="ctrl_label"> - <label for="pitch">Pitch:</label> - </div> - <div class="ctrl_wrap"> - <input id="pitch" type="range" class="ctrl" - min=0.5 max=1.5 step=0.1 value=1.0></input> - </div> - - <div class="ctrl_label"> - <label for="volume">Volume:</label> - </div> - <div class="ctrl_wrap"> - <input id="volume" type="range" class="ctrl" - min=0.0 max=1.0 step=0.1 value=1.0></input> - </div> - - <div class="ctrl_label"> - - </div> - <div class="ctrl_wrap"> - <button id="test">Test Speech</button> - <button id="defaults">Defaults</button> - </div> - - </div> - </div> - <div class="body_right"> - <div class="body_inner"> - <h2>When to speak</h2> - <p> - <span id="selected">Select some text</span> - anywhere on a webpage, then either: - </p> - - <p>1. Click on the - <img class="browser_action" src="SpeakSel19.png" alt="Speak Selection"> - button in the toolbar ↗, or - </p> - - <p>2. Use this hot key: <input type="text" id="hotkey"></input> - </p> - <p>Click the button or press the key again to stop speech.</p> - </div> - </div> -</div> - -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/options.js b/chrome/common/extensions/docs/examples/extensions/speak_selection/options.js deleted file mode 100644 index f77e739..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/options.js +++ /dev/null
@@ -1,130 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -function load() { - var selectedElement = document.getElementById('selected'); - var sel = window.getSelection(); - sel.removeAllRanges(); - var range = document.createRange(); - range.selectNode(selectedElement); - sel.addRange(range); - - var rateElement = document.getElementById('rate'); - var pitchElement = document.getElementById('pitch'); - var volumeElement = document.getElementById('volume'); - var rate = localStorage['rate'] || 1.0; - var pitch = localStorage['pitch'] || 1.0; - var volume = localStorage['volume'] || 1.0; - rateElement.value = rate; - pitchElement.value = pitch; - volumeElement.value = volume; - function listener(evt) { - rate = rateElement.value; - localStorage['rate'] = rate; - pitch = pitchElement.value; - localStorage['pitch'] = pitch; - volume = volumeElement.value; - localStorage['volume'] = volume; - } - rateElement.addEventListener('keyup', listener, false); - pitchElement.addEventListener('keyup', listener, false); - volumeElement.addEventListener('keyup', listener, false); - rateElement.addEventListener('mouseup', listener, false); - pitchElement.addEventListener('mouseup', listener, false); - volumeElement.addEventListener('mouseup', listener, false); - - var defaultsButton = document.getElementById('defaults'); - defaultsButton.addEventListener('click', function(evt) { - rate = 1.0; - pitch = 1.0; - volume = 1.0; - localStorage['rate'] = rate; - localStorage['pitch'] = pitch; - localStorage['volume'] = volume; - rateElement.value = rate; - pitchElement.value = pitch; - volumeElement.value = volume; - }, false); - - var voice = document.getElementById('voice'); - var voiceArray = []; - chrome.tts.getVoices(function(va) { - voiceArray = va; - for (var i = 0; i < voiceArray.length; i++) { - var opt = document.createElement('option'); - var name = voiceArray[i].voiceName; - if (name == localStorage['voice']) { - opt.setAttribute('selected', ''); - } - opt.setAttribute('value', name); - opt.innerText = voiceArray[i].voiceName; - voice.appendChild(opt); - } - }); - voice.addEventListener('change', function() { - var i = voice.selectedIndex; - localStorage['voice'] = voiceArray[i].voiceName; - }, false); - - var defaultKeyString = getDefaultKeyString(); - - var keyString = localStorage['speakKey']; - if (keyString == undefined) { - keyString = defaultKeyString; - } - - var testButton = document.getElementById('test'); - testButton.addEventListener('click', function(evt) { - chrome.tts.speak( - 'Testing speech synthesis', - {voiceName: localStorage['voice'], - rate: parseFloat(rate), - pitch: parseFloat(pitch), - volume: parseFloat(volume)}); - }); - - var hotKeyElement = document.getElementById('hotkey'); - hotKeyElement.value = keyString; - hotKeyElement.addEventListener('keydown', function(evt) { - switch (evt.keyCode) { - case 27: // Escape - evt.stopPropagation(); - evt.preventDefault(); - hotKeyElement.blur(); - return false; - case 8: // Backspace - case 46: // Delete - evt.stopPropagation(); - evt.preventDefault(); - hotKeyElement.value = ''; - localStorage['speakKey'] = ''; - sendKeyToAllTabs(''); - window.speakKeyStr = ''; - return false; - case 9: // Tab - return false; - case 16: // Shift - case 17: // Control - case 18: // Alt/Option - case 91: // Meta/Command - evt.stopPropagation(); - evt.preventDefault(); - return false; - } - var keyStr = keyEventToString(evt); - if (keyStr) { - hotKeyElement.value = keyStr; - localStorage['speakKey'] = keyStr; - sendKeyToAllTabs(keyStr); - - // Set the key used by the content script running in the options page. - window.speakKeyStr = keyStr; - } - evt.stopPropagation(); - evt.preventDefault(); - return false; - }, true); -} - -document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/common/extensions/docs/examples/extensions/speak_selection/tabs.js b/chrome/common/extensions/docs/examples/extensions/speak_selection/tabs.js deleted file mode 100644 index 4edac9cf..0000000 --- a/chrome/common/extensions/docs/examples/extensions/speak_selection/tabs.js +++ /dev/null
@@ -1,34 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -function sendKeyToAllTabs(keyStr) { - chrome.windows.getAll({'populate': true}, function(windows) { - for (var i = 0; i < windows.length; i++) { - var tabs = windows[i].tabs; - for (var j = 0; j < tabs.length; j++) { - chrome.tabs.sendRequest( - tabs[j].id, - {'key': keyStr}); - } - } - }); -} - -function loadContentScriptInAllTabs() { - chrome.windows.getAll({'populate': true}, function(windows) { - for (var i = 0; i < windows.length; i++) { - var tabs = windows[i].tabs; - for (var j = 0; j < tabs.length; j++) { - chrome.tabs.executeScript( - tabs[j].id, - {file: 'keycodes.js', allFrames: true}); - chrome.tabs.executeScript( - tabs[j].id, - {file: 'content_script.js', allFrames: true}); - } - } - }); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/cuckoo.ogg b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/cuckoo.ogg deleted file mode 100644 index 7a5cd56..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/cuckoo.ogg +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/digital.ogg b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/digital.ogg deleted file mode 100644 index 0c9cf42f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/digital.ogg +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/metal.ogg b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/metal.ogg deleted file mode 100644 index 22fbceb..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/metal.ogg +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/ringing.ogg b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/ringing.ogg deleted file mode 100644 index 04ee778..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/ringing.ogg +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/rooster.ogg b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/rooster.ogg deleted file mode 100644 index 5ef6a0bd..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/audio/rooster.ogg +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/background.js b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/background.js deleted file mode 100644 index 38c5917..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/background.js +++ /dev/null
@@ -1,126 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -var a1Timer = null; -var a2Timer = null; -var port = null; -var iconFlashTimer = null; - -var HOUR_MS = 1000 * 60 * 60; - -// Override from common.js -window.stopFlashingIcon = function() { - window.clearTimeout(iconFlashTimer); - chrome.browserAction.setIcon({'path': 'clock-19.png'}); -}; - -// Override from common.js -window.flashIcon = function() { - var flashes = 10; - function flash() { - if (flashes == 0) { - stopFlashingIcon(); - return; - } - - if (flashes % 2 == 0) { - chrome.browserAction.setIcon({'path': 'clock-highlighted-19.png'}); - } else { - chrome.browserAction.setIcon({'path': 'clock-19.png'}); - } - flashes--; - iconFlashTimer = window.setTimeout(flash, 500); - } - flash(); -}; - -function setTimer(alarmHours, alarmMinutes) { - var alarmTime = (alarmHours * 60 + alarmMinutes) * 60 * 1000; - var d = new Date(); - var now = d.getHours() * HOUR_MS + - d.getMinutes() * 60 * 1000 + - d.getSeconds() * 1000; - var delta = (alarmTime - now); - - if (delta >= -5000 && delta < 1000) { - ringAlarm(alarmHours, alarmMinutes); - if (port) { - port.postMessage({'cmd': 'anim'}); - } - return null; - } - - if (delta < 0) { - delta += HOUR_MS * 24; - } - if (delta >= 1000) { - if (delta > HOUR_MS) { - delta = HOUR_MS; - } - console.log('Timer set for ' + delta + ' ms'); - return window.setTimeout(resetTimers, delta); - } - - return null; -}; - -function resetTimers() { - if (a1Timer) { - window.clearTimeout(a1Timer); - } - - try { - var a1_on = (localStorage['a1_on'] == 'true'); - var a1_tt = localStorage['a1_tt'] || DEFAULT_A1_TT; - var a1_ampm = localStorage['a1_ampm'] || DEFAULT_A1_AMPM; - if (a1_on) { - var alarmHoursMinutes = parseTime(a1_tt, a1_ampm); - var alarmHours = alarmHoursMinutes[0]; - var alarmMinutes = alarmHoursMinutes[1]; - a1Timer = setTimer(alarmHours, alarmMinutes); - } - } catch (e) { - console.log(e); - } - - try { - var a2_on = (localStorage['a2_on'] == 'true'); - var a2_tt = localStorage['a2_tt'] || DEFAULT_A2_TT; - var a2_ampm = localStorage['a2_ampm'] || DEFAULT_A2_AMPM; - if (a2_on) { - var alarmHoursMinutes = parseTime(a2_tt, a2_ampm); - var alarmHours = alarmHoursMinutes[0]; - var alarmMinutes = alarmHoursMinutes[1]; - a2Timer = setTimer(alarmHours, alarmMinutes); - } - } catch (e) { - console.log(e); - } - - if (a1_on || a2_on) { - chrome.browserAction.setIcon({'path': 'clock-19.png'}); - } else { - chrome.browserAction.setIcon({'path': 'clock-disabled-19.png'}); - } -} - -function onLocalStorageChange() { - resetTimers(); -} - -function initBackground() { - window.addEventListener('storage', onLocalStorageChange, false); - - chrome.runtime.onConnect.addListener(function(popupPort) { - port = popupPort; - port.onDisconnect.addListener(function() { - port = null; - }); - }); -} - -initBackground(); -resetTimers();
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-150.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-150.png deleted file mode 100644 index af850fc7..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-150.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-ring1-150.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-ring1-150.png deleted file mode 100644 index b0631b40..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-ring1-150.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-ring2-150.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-ring2-150.png deleted file mode 100644 index b02437a1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/blank-clock-ring2-150.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-128.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-128.png deleted file mode 100644 index 290e3f25f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-16.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-16.png deleted file mode 100644 index 32e570f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-19.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-19.png deleted file mode 100644 index 59685e9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-256.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-256.png deleted file mode 100644 index d576bea..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-256.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-48.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-48.png deleted file mode 100644 index 1dbb771..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-disabled-19.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-disabled-19.png deleted file mode 100644 index 69cf5a66..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-disabled-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-highlighted-19.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-highlighted-19.png deleted file mode 100644 index 5729f292..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/clock-highlighted-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/common.js b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/common.js deleted file mode 100644 index 037aa39e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/common.js +++ /dev/null
@@ -1,179 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -var DEFAULT_A1_TT = '09:30'; -var DEFAULT_A1_AMPM = 0; -var DEFAULT_A2_TT = '03:30'; -var DEFAULT_A2_AMPM = 1; -var DEFAULT_RATE = 1.0; -var DEFAULT_VOLUME = 1.0; -var DEFAULT_PHRASE = 'It\'s $TIME, so get up!'; -var DEFAULT_SOUND = 'ringing'; - -var audio = null; - -var isPlaying = false; -var isSpeaking = false; -var isAnimating = false; - -// Overridden in popup.js but not in background.js. -window.displayAlarmAnimation = function() { -}; - -// Overridden in popup.js but not in background.js. -window.stopAlarmAnimation = function() { -}; - -// Overridden in background.js but not in popup.js. -window.flashIcon = function() { -}; - -// Overridden in background.js but not in popup.js. -window.stopFlashingIcon = function() { -}; - -function $(id) { - return document.getElementById(id); -} - -function parseTime(timeString, ampm) { - var time = timeString.match(/^(\d\d):(\d\d)$/); - if (!time) { - throw 'Cannot parse: ' + timeString; - } - - var hours = parseInt(time[1], 10); - if (hours == 12 && ampm == 0) { - hours = 0; - } else { - hours += (hours < 12 && ampm == 1)? 12 : 0; - } - var minutes = parseInt(time[2], 10) || 0; - - return [hours, minutes]; -} - -function stopAll() { - if (audio) { - audio.pause(); - isPlaying = false; - } - try { - chrome.tts.stop(); - isSpeaking = false; - } catch (e) { - } - window.stopAlarmAnimation(); - window.stopFlashingIcon(); -} - -function playSound(duckAudio) { - if (audio) { - audio.pause(); - document.body.removeChild(audio); - audio = null; - } - - var currentSound = localStorage['sound'] || DEFAULT_SOUND; - if (currentSound == 'none') { - return; - } - - audio = document.createElement('audio'); - audio.addEventListener('ended', function(evt) { - isPlaying = false; - }); - document.body.appendChild(audio); - audio.autoplay = true; - - var src = 'audio/' + currentSound + '.ogg'; - var volume = parseFloat(localStorage['volume']) || DEFAULT_VOLUME; - audio.volume = volume; - audio.src = src; - isPlaying = true; - - if (duckAudio) { - for (var i = 0; i < 10; i++) { - (function(i) { - window.setTimeout(function() { - var duckedVolume = volume * (1.0 - 0.07 * (i + 1)); - audio.volume = duckedVolume; - }, 1800 + 50 * i); - })(i); - } - } -} - -function getTimeString(hh, mm) { - var ampm = hh >= 12 ? 'P M' : 'A M'; - hh = (hh % 12); - if (hh == 0) - hh = 12; - if (mm == 0) - mm = 'o\'clock'; - else if (mm < 10) - mm = 'O ' + mm; - - return hh + ' ' + mm + ' ' + ampm; -} - -function speak(text) { - var rate = parseFloat(localStorage['rate']) || DEFAULT_RATE; - var pitch = 1.0; - var volume = parseFloat(localStorage['volume']) || DEFAULT_VOLUME; - var voice = localStorage['voice']; - chrome.tts.speak( - text, - {voiceName: voice, - rate: rate, - pitch: pitch, - volume: volume, - onEvent: function(evt) { - if (evt.type == 'end') { - isSpeaking = false; - } - } - }); -} - -function speakPhraseWithTimeString(timeString) { - var phraseTemplate = localStorage['phrase'] || DEFAULT_PHRASE; - var utterance = phraseTemplate.replace(/\$TIME/g, timeString); - speak(utterance); -} - -function speakPhraseWithCurrentTime() { - var d = new Date(); - speakPhraseWithTimeString(getTimeString(d.getHours(), d.getMinutes())); -} - -function ringAlarm(alarmHours, alarmMinutes) { - window.displayAlarmAnimation(); - window.flashIcon(); - - var phraseTemplate = localStorage['phrase'] || DEFAULT_PHRASE; - var currentSound = localStorage['sound'] || DEFAULT_SOUND; - - if (phraseTemplate == '') { - playSound(false); - } else if (currentSound == 'none') { - speakPhraseWithTimeString(getTimeString(alarmHours, alarmMinutes)); - } else { - chrome.tts.stop(); - playSound(true); - isSpeaking = true; - window.setTimeout(function() { - if (isSpeaking) { - speakPhraseWithTimeString(getTimeString(alarmHours, alarmMinutes)); - } - }, 2000); - } -} - -function ringAlarmWithCurrentTime() { - var d = new Date(); - ringAlarm(d.getHours(), d.getMinutes()); -}
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/credits.html b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/credits.html deleted file mode 100644 index 303b916..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/credits.html +++ /dev/null
@@ -1,39 +0,0 @@ -<html> -<head> - <title>Talking Alarm Clock</title> - <style> - body { - font-family: arial, helvetica, sans-serif; - font-size: 13; - } - </style> -</head> -<body> - -<img src="clock-128.png" style="float: left; margin: 0 20px 200px 0;"> - -<p> -<b>Talking Alarm Clock for Google Chrome</b> -</p> - -<p> -by Dominic Mazzoni -</p> - -<p> -Talking Alarm Clock uses the following sound files from Freesound -(<a href="http://www.freesound.org">http://www.freesound.org</a>): -</p> - -<ul style="margin-left: 150px;"> -<li>alarmclockbeeps from tedthetrumpet -<li>alarm_clock_ringing from joedeshon -<li>CuckooClock6DP from acclivity -<li>ClockStrikes12 from acclivity -<li>Maxines from TexasMusicForge -<li>fat_beat_1 from -zin- -<li>20070812.rooster from dobroide -</ul> - -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/manifest.json b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/manifest.json deleted file mode 100644 index 79f5b50..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/manifest.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "name": "Talking Alarm Clock", - "version": "1.3", - "description": "A clock with two configurable alarms that will play a sound and speak a phrase of your choice.", - "permissions": [ "background", "tts" ], - - "background": { "scripts": ["common.js", "background.js"] }, - - "browser_action": { - "default_icon": "clock-19.png", - "default_title": "Talking Alarm Clock", - "default_popup": "popup.html" - }, - - "icons": { - "16": "clock-16.png", - "48": "clock-48.png", - "128": "clock-128.png", - "256": "clock-256.png" - }, - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/play.png b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/play.png deleted file mode 100644 index 08e8b3e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/play.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/popup.html b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/popup.html deleted file mode 100644 index cb82ed3..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/popup.html +++ /dev/null
@@ -1,205 +0,0 @@ -<html> -<head> - <title>Talking Alarm Clock</title> - <link href='http://fonts.googleapis.com/css?family=Nova%20Mono' rel='stylesheet' type='text/css'> - <style> - body { - overflow: hidden; - margin-top: 0px; - } - #main { - width: 200px; - font-family: arial, helvetica, sans-serif; - font-size: 13; - } - #clock { - cursor: pointer; - } - .alarm_wrap { - margin-top: 6px; - padding: 6px; - background-color: #dfd; - border: 1px solid #aaa; - border-radius: 4px; - } - .alarm_wrap.disabled { - background-color: #eee; - } - .alarm_wrap[aria-invalid] { - background-color: #f99; - } - .alarm_wrap[aria-invalid] input { - color: #900; - } - .alarm_wrap input { - font-size: 20; - } - .alarm_wrap input[type=time] { - font-size: 20; - width: 85px; - } - .alarm_wrap.disabled input { - color: #999; - } - .ctrl_label { - float: left; - width: 100%; - margin-top: 6px; - } - .ctrl_wrap { - width: 200px; - float: left; - } - .ctrl_wrap input[type=range] { - width: 180px; - height: 16px; - } - .buttons { - margin-top: 10px; - } - .voice_options { - } - #sound { - float: left; - width: 160px; - margin: 8px 0px; - } - #playsound { - padding: 5px; - margin: 5px; - } - #phrase { - float: left; - width: 160px; - } - #playspeech { - padding: 5px; - margin: 5px; - } - #a1_tt { - font-family: Nova Mono; - height: 34px; - } - #a2_tt { - font-family: Nova Mono; - height: 34px; - } - #a1_ampm { - font-family: Nova Mono; - } - #a2_ampm { - font-family: Nova Mono; - } - #current_time { - font-family: Nova Mono; - font-size: 24; - height: 32px; - } - body.nooutline * { - outline: none; - } - .footer { - clear:left; - } - </style> - <script src="common.js"></script> - <script src="popup.js"></script> -</head> -<body> - -<div id="main"> - - <center> - <canvas id="clock" width="150" height="150" - role="button" tabindex="0"></canvas> - <div id="current_time">00:00:00</div> - </center> - - <div id="a1_wrap" class="alarm_wrap"> - <label for="a1_on">Alarm 1</label> - <br> - <input id="a1_on" type="checkbox"> - <input id="a1_tt" type="time" step="300" size="5"> - <select id="a1_ampm"> - <option>AM</option> - <option selected>PM</option> - </select> - </div> - <div id="a2_wrap" class="alarm_wrap"> - <label for="a2_on">Alarm 2</label> - <br> - <input id="a2_on" type="checkbox"> - <input id="a2_tt" type="time" step="300" size="5"> - <select id="a2_ampm"> - <option>AM</option> - <option selected>PM</option> - </select> - </div> - - <div class="voice_options"> - <div> - <div class="ctrl_label"> - <label for="sound">Sound:</label> - </div> - <div class="ctrl_wrap"> - <select id="sound" class="ctrl"> - <option value="none">None</option> - <option selected value="cuckoo">Cuckoo Clock</option> - <option value="digital">Digital Alarm Clock</option> - <option value="metal">Metal</option> - <option value="ringing">Ringing Alarm Clock</option> - <option value="rooster">Rooster</option> - </select> - - <button id="playsound" title="Play Sound"> - <img src="play.png"> - </button> - </div> - - <div class="ctrl_label"> - <label for="sound">Phrase (use $TIME to say time):</label> - </div> - <div class="ctrl_wrap"> - <textarea id="phrase"></textarea> - - <button id="playspeech" title="Play Speech"> - <img src="play.png"> - </button> - </div> - - <div class="ctrl_label"> - <label for="voice">Voice:</label> - </div> - <div class="ctrl_wrap"> - <select id="voice" class="ctrl"></select> - </div> - - <div class="ctrl_label"> - <label for="rate">Speech rate:</label> - </div> - <div class="ctrl_wrap"> - <input id="rate" type="range" class="ctrl" - min=0.5 max=1.5 step=0.1 value=1.0></input> - </div> - - <div class="ctrl_label"> - <label for="volume">Speech and sound volume:</label> - </div> - <div class="ctrl_wrap"> - <input id="volume" type="range" class="ctrl" - min=0.0 max=1.0 step=0.1 value=1.0></input> - </div> - </div> - </div> - - <div class="footer"> - <a href="credits.html" target="_blank">Credits</a> - | - <a href="https://chrome.google.com/webstore/search?q=tts" - target="_blank">Get more voices</a> - </div> - -</div> - -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/popup.js b/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/popup.js deleted file mode 100644 index 30b80853..0000000 --- a/chrome/common/extensions/docs/examples/extensions/talking_alarm_clock/popup.js +++ /dev/null
@@ -1,403 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -var blankClockImage; -var blankClockAnim1Image; -var blankClockAnim2Image; -var animationTimer; -var currentClockImage; -var port; - -function updateEnabledStatus(alarm) { - var enabled = $('a' + alarm + '_on').checked; - $('a' + alarm + '_tt').disabled = !enabled; - $('a' + alarm + '_ampm').disabled = !enabled; - var valid = true; - try { - var tt = $('a' + alarm + '_tt').value; - var ampm = $('a' + alarm + '_ampm').selectedIndex; - parseTime(tt, ampm); - } catch (x) { - valid = false; - } - if (valid) { - $('a' + alarm + '_wrap').removeAttribute('aria-invalid'); - } else { - $('a' + alarm + '_wrap').setAttribute('aria-invalid', 'true'); - } - if (enabled) { - $('a' + alarm + '_wrap').classList.remove('disabled'); - } else { - $('a' + alarm + '_wrap').classList.add('disabled'); - } -} - -function loadAllImages() { - var loadCount = 0; - var img = new Image(); - img.onload = function() { - blankClockImage = img; - currentClockImage = blankClockImage; - drawClock(); - }; - img.src = 'blank-clock-150.png'; - - // These will finish loading before they're needed, no need - // for an onload handler. - blankClockAnim1Image = new Image(); - blankClockAnim1Image.src = 'blank-clock-ring1-150.png'; - blankClockAnim2Image = new Image(); - blankClockAnim2Image.src = 'blank-clock-ring2-150.png'; -} - -function drawClock(hh, mm, ss) { - if (hh == undefined || mm == undefined) { - var d = new Date(); - hh = d.getHours(); - mm = d.getMinutes(); - ss = d.getSeconds() + 0.001 * d.getMilliseconds(); - } - - if (!currentClockImage) { - loadAllImages(); - return; - } - - var ctx = $('clock').getContext('2d'); - ctx.drawImage(currentClockImage, 0, 0); - - // Move the hour by the fraction of the minute - hh = (hh % 12) + (mm / 60); - - // Move the minute by the fraction of the second - mm += (ss / 60); - - var hourAngle = Math.PI * hh / 6; - var hourX = Math.sin(hourAngle); - var hourY = -Math.cos(hourAngle); - var minAngle = Math.PI * mm / 30; - var minX = Math.sin(minAngle); - var minY = -Math.cos(minAngle); - var secAngle = Math.PI * ss / 30; - var secX = Math.sin(secAngle); - var secY = -Math.cos(secAngle); - - var cx = 75; - var cy = 77; - - ctx.lineWidth = 5; - ctx.strokeStyle = '#ffffff'; - ctx.globalAlpha = 0.5; - ctx.beginPath(); - ctx.moveTo(cx - 4 * hourX, cy - 4 * hourY); - ctx.lineTo(cx + 20 * hourX, cy + 20 * hourY); - ctx.stroke(); - ctx.beginPath(); - ctx.moveTo(cx - 8 * minX, cy - 8 * minY); - ctx.lineTo(cx + 35 * minX, cy + 33 * minY); - ctx.stroke(); - - ctx.lineWidth = 3; - ctx.strokeStyle = '#696969'; - ctx.globalAlpha = 1.0; - ctx.beginPath(); - ctx.moveTo(cx - 4 * hourX, cy - 4 * hourY); - ctx.lineTo(cx + 20 * hourX, cy + 20 * hourY); - ctx.stroke(); - ctx.beginPath(); - ctx.moveTo(cx - 8 * minX, cy - 8 * minY); - ctx.lineTo(cx + 35 * minX, cy + 33 * minY); - ctx.stroke(); - - ctx.lineWidth = 1; - ctx.strokeStyle = '#990000'; - ctx.globalAlpha = 1.0; - ctx.beginPath(); - ctx.moveTo(cx - 4 * secX, cy - 4 * secY); - ctx.lineTo(cx + 40 * secX, cy + 40 * secY); - ctx.stroke(); -} - -function updateCurrentTime() { - var now = new Date(); - var hh = now.getHours(); - var mm = now.getMinutes(); - var ss = now.getSeconds(); - var str = ''; - if (hh % 12 == 0) { - str += '12'; - } else { - str += (hh % 12); - } - str += ':'; - if (mm >= 10) { - str += mm; - } else { - str += '0' + mm; - } - str += ':'; - if (ss >= 10) { - str += ss; - } else { - str += '0' + ss; - } - if (hh >= 12) { - str += " PM"; - } else { - str += " AM"; - } - $('current_time').innerText = str; -} - -// Override from common.js -window.stopAlarmAnimation = function() { - window.clearTimeout(animationTimer); - currentClockImage = blankClockImage; - drawClock(); - isAnimating = false; -}; - -// Override from common.js -window.displayAlarmAnimation = function() { - isAnimating = true; - var rings = 100; - function ring() { - if (rings == 0) { - stopAlarmAnimation(); - return; - } - currentClockImage = (rings % 2 == 0)? - blankClockAnim1Image: - blankClockAnim2Image; - drawClock(); - rings--; - animationTimer = window.setTimeout(ring, 50); - } - ring(); -}; - -function addOutlineStyleListeners() { - document.addEventListener('click', function(evt) { - document.body.classList.add('nooutline'); - return true; - }, true); - document.addEventListener('keydown', function(evt) { - document.body.classList.remove('nooutline'); - return true; - }, true); -} - -function load() { - try { - port = chrome.runtime.connect(); - port.onMessage.addListener(function(msg) { - if (msg.cmd == 'anim') { - displayAlarmAnimation(); - } - }); - } catch (e) { - } - - addOutlineStyleListeners(); - - stopAll(); - drawClock(); - setInterval(drawClock, 100); - - updateCurrentTime(); - setInterval(updateCurrentTime, 250); - - function updateTime(timeElement) { - if (!parseTime(timeElement.value)) { - return false; - } - - timeElement.valueAsNumber = - timeElement.valueAsNumber % (12 * 60 * 60 * 1000); - if (timeElement.valueAsNumber < (1 * 60 * 60 * 1000)) - timeElement.valueAsNumber += (12 * 60 * 60 * 1000); - return true; - } - - $('clock').addEventListener('click', function(evt) { - if (isPlaying || isSpeaking || isAnimating) { - stopAll(); - } else { - ringAlarmWithCurrentTime(); - } - }, false); - $('clock').addEventListener('keydown', function(evt) { - if (evt.keyCode == 13 || evt.keyCode == 32) { - if (isPlaying || isSpeaking || isAnimating) { - stopAll(); - } else { - ringAlarmWithCurrentTime(); - } - } - }, false); - - // Alarm 1 - - var a1_tt = localStorage['a1_tt'] || DEFAULT_A1_TT; - $('a1_tt').value = a1_tt; - $('a1_tt').addEventListener('input', function(evt) { - updateEnabledStatus(1); - if (!updateTime($('a1_tt'))) { - evt.stopPropagation(); - return false; - } - localStorage['a1_tt'] = $('a1_tt').value; - updateEnabledStatus(1); - return true; - }, false); - $('a1_tt').addEventListener('change', function(evt) { - if ($('a1_tt').value.length == 4 && - parseTime('0' + $('a1_tt').value)) { - $('a1_tt').value = '0' + $('a1_tt').value; - } - if (!updateTime($('a1_tt'))) { - evt.stopPropagation(); - return false; - } - localStorage['a1_tt'] = $('a1_tt').value; - updateEnabledStatus(1); - return true; - }, false); - - var a1_on = (localStorage['a1_on'] == 'true'); - $('a1_on').checked = a1_on; - $('a1_on').addEventListener('change', function(evt) { - window.setTimeout(function() { - localStorage['a1_on'] = $('a1_on').checked; - updateEnabledStatus(1); - }, 0); - }, false); - - var a1_ampm = localStorage['a1_ampm'] || DEFAULT_A1_AMPM; - $('a1_ampm').selectedIndex = a1_ampm; - $('a1_ampm').addEventListener('change', function(evt) { - localStorage['a1_ampm'] = $('a1_ampm').selectedIndex; - }, false); - - updateEnabledStatus(1); - - // Alarm 2 - - var a2_tt = localStorage['a2_tt'] || DEFAULT_A2_TT; - $('a2_tt').value = a2_tt; - $('a2_tt').addEventListener('input', function(evt) { - updateEnabledStatus(2); - if (!updateTime($('a2_tt'))) { - evt.stopPropagation(); - return false; - } - localStorage['a2_tt'] = $('a2_tt').value; - updateEnabledStatus(2); - return true; - }, false); - $('a2_tt').addEventListener('change', function(evt) { - if ($('a2_tt').value.length == 4 && - parseTime('0' + $('a2_tt').value)) { - $('a2_tt').value = '0' + $('a2_tt').value; - } - if (!updateTime($('a2_tt'))) { - evt.stopPropagation(); - return false; - } - localStorage['a2_tt'] = $('a2_tt').value; - updateEnabledStatus(2); - return true; - }, false); - - var a2_on = (localStorage['a2_on'] == 'true'); - $('a2_on').checked = a2_on; - $('a2_on').addEventListener('change', function(evt) { - window.setTimeout(function() { - localStorage['a2_on'] = $('a2_on').checked; - updateEnabledStatus(2); - }, 0); - }, false); - - var a2_ampm = localStorage['a2_ampm'] || DEFAULT_A2_AMPM; - $('a2_ampm').selectedIndex = a2_ampm; - $('a2_ampm').addEventListener('change', function(evt) { - localStorage['a2_ampm'] = $('a2_ampm').selectedIndex; - }, false); - - updateEnabledStatus(2); - - // Phrase - - var phrase = localStorage['phrase'] || DEFAULT_PHRASE; - $('phrase').value = phrase; - $('phrase').addEventListener('change', function(evt) { - localStorage['phrase'] = $('phrase').value; - }, false); - - // Speech parameters - - var rateElement = $('rate'); - var volumeElement = $('volume'); - var rate = localStorage['rate'] || DEFAULT_RATE; - var volume = localStorage['volume'] || DEFAULT_VOLUME; - rateElement.value = rate; - volumeElement.value = volume; - function listener(evt) { - rate = rateElement.value; - localStorage['rate'] = rate; - volume = volumeElement.value; - localStorage['volume'] = volume; - } - rateElement.addEventListener('keyup', listener, false); - volumeElement.addEventListener('keyup', listener, false); - rateElement.addEventListener('mouseup', listener, false); - volumeElement.addEventListener('mouseup', listener, false); - - var sound = $('sound'); - var currentSound = localStorage['sound'] || DEFAULT_SOUND; - for (var i = 0; i < sound.options.length; i++) { - if (sound.options[i].value == currentSound) { - sound.selectedIndex = i; - break; - } - } - localStorage['sound'] = sound.options[sound.selectedIndex].value; - sound.addEventListener('change', function() { - localStorage['sound'] = sound.options[sound.selectedIndex].value; - }, false); - - var playSoundButton = $('playsound'); - playSoundButton.addEventListener('click', function(evt) { - playSound(false); - }); - - var playSpeechButton = $('playspeech'); - playSpeechButton.addEventListener('click', function(evt) { - speakPhraseWithCurrentTime(); - }); - - var voice = $('voice'); - var voiceArray = []; - if (chrome && chrome.tts) { - chrome.tts.getVoices(function(va) { - voiceArray = va; - for (var i = 0; i < voiceArray.length; i++) { - var opt = document.createElement('option'); - var name = voiceArray[i].voiceName; - if (name == localStorage['voice']) { - opt.setAttribute('selected', ''); - } - opt.setAttribute('value', name); - opt.innerText = voiceArray[i].voiceName; - voice.appendChild(opt); - } - }); - } - voice.addEventListener('change', function() { - var i = voice.selectedIndex; - localStorage['voice'] = voiceArray[i].voiceName; - }, false); -} - -document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/128.png b/chrome/common/extensions/docs/examples/extensions/ttsdebug/128.png deleted file mode 100644 index 6411dc9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/16.png b/chrome/common/extensions/docs/examples/extensions/ttsdebug/16.png deleted file mode 100644 index 9e55a982..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/256.png b/chrome/common/extensions/docs/examples/extensions/ttsdebug/256.png deleted file mode 100644 index 986d3ae8..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/256.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/manifest.json b/chrome/common/extensions/docs/examples/extensions/ttsdebug/manifest.json deleted file mode 100644 index 0a856f92..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/manifest.json +++ /dev/null
@@ -1,18 +0,0 @@ -{ - "app": { - "launch": { - "local_path": "ttsdebug.html" - } - }, - "description": "Tool for developers of Chrome TTS engine extensions to help them test their engines are implementing the API correctly.", - "icons": { - "16": "16.png", - "128": "128.png", - "256": "256.png" - }, - "minimum_chrome_version": "14", - "name": "TTS Debug", - "permissions": [ "tts" ], - "version": "1.0", - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/pacman.gif b/chrome/common/extensions/docs/examples/extensions/ttsdebug/pacman.gif deleted file mode 100644 index d43fcb5..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/pacman.gif +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.css b/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.css deleted file mode 100644 index 86f603e..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.css +++ /dev/null
@@ -1,64 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -#main { - font-family: arial,helvetica; - font-size: 10pt; - text-align: center; - margin-left: auto; - margin-right: auto; - padding: 10px 30px 20px 30px; - width: 800px; - border-left: solid 1px #ccc; - border-right: solid 1px #ccc; -} -#stop { - margin-left: 100px; -} -#container { - text-align: left; -} -#instructions { - text-align: left; -} -.outer { - margin: 12px 6px 6px 6px; - padding: 6px; - border: 1px solid #000; -} -.outer.disabled { - border: 1px solid #696969; -} -.runTestButton { - margin: 12px; -} -.description { - margin: 6px 12px; -} -.results { - margin: 12px; -} -.messages { - margin: 12px; -} -.error { - color: #900; -} -.result { - margin: 6px; - padding: 6px; -} -.success { - font-weight: bold; - color: #090; -} -.failure { - font-weight: bold; - color: #900; -} -.disabled { - color: #696969 !important; -}
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.html b/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.html deleted file mode 100644 index 745fb2f..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.html +++ /dev/null
@@ -1,35 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Chrome TTS Debug</title> - <link href="ttsdebug.css" rel="stylesheet" type="text/css"> - <script src="ttsdebug.js"></script> - </head> - <body> - <div id="main"> - <h2>Chrome Text-to-Speech Debug</h2> - - <div id="instructions"> - <p> - This app is for developers of Chrome TTS engines, to help validate that - an engine is properly implementing the API. Click on a button to run a - test. A lot of errors can be detected automatically, but some tests - require manually listening to the speech, and it's important to listen to - all tests running to identify other potential glitches.</p> - <p>For more diagnostic information, open the JavaScript console.</p> - </div> - - <div> - <label for="voices">Voice:</label> - - <select id="voices"> - <option value="">Unspecified</option> - </select> - - <button id="stop">Emergency Stop!</button> - </div> - - <div id="container"></div> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.js b/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.js deleted file mode 100644 index 61b71c9..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdebug/ttsdebug.js +++ /dev/null
@@ -1,694 +0,0 @@ -/** - * Copyright (c) 2011 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. - */ - -var voiceArray; -var trials = 3; -var resultMap = {}; -var updateDependencyFunctions = []; -var testRunIndex = 0; -var emergencyStop = false; - -function $(id) { - return document.getElementById(id); -} - -function isErrorEvent(evt) { - return (evt.type == 'error' || - evt.type == 'interrupted' || - evt.type == 'cancelled'); -} - -function logEvent(callTime, testRunName, evt) { - var elapsed = ((new Date() - callTime) / 1000).toFixed(3); - while (elapsed.length < 7) { - elapsed = ' ' + elapsed; - } - console.log(elapsed + ' ' + testRunName + ': ' + JSON.stringify(evt)); -} - -function logSpeakCall(utterance, options, callback) { - var optionsCopy = {}; - for (var key in options) { - if (key != 'onEvent') { - optionsCopy[key] = options[key]; - } - } - console.log('Calling chrome.tts.speak(\'' + - utterance + '\', ' + - JSON.stringify(optionsCopy) + ')'); - if (callback) - chrome.tts.speak(utterance, options, callback); - else - chrome.tts.speak(utterance, options); -} - -var tests = [ - { - name: 'Baseline', - description: 'Ensures that the speech engine sends both start and ' + - 'end events, and establishes a baseline time to speak a ' + - 'key phrase, to compare other tests against.', - dependencies: [], - trials: 3, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - var startTime; - var warnings = []; - var errors = []; - logSpeakCall('Alpha Bravo Charlie Delta Echo', { - voiceName: voiceName, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'start') { - startTime = new Date(); - if (evt.charIndex != 0) { - errors.push('Error: start event should have a charIndex of 0.'); - } - } else if (evt.type == 'end') { - if (startTime == undefined) { - errors.push('Error: no "start" event received!'); - startTime = callTime; - } - if (evt.charIndex != 30) { - errors.push('Error: end event should have a charIndex of 30.'); - } - var endTime = new Date(); - if (startTime - callTime > 1000) { - var delta = ((startTime - callTime) / 1000).toFixed(3); - warnings.push('Note: Delay of ' + delta + - ' before speech started. ' + - 'Less than 1.0 s latency is recommended.'); - } - var delta = (endTime - startTime) / 1000; - if (delta < 1.0) { - warnings.push('Warning: Default speech rate seems too fast.'); - } else if (delta > 3.0) { - warnings.push('Warning: Default speech rate seems too slow.'); - } - callback(errors.length == 0, delta, warnings.concat(errors)); - } - } - }); - } - }, - { - name: 'Fast', - description: 'Speaks twice as fast and compares the time to the baseline.', - dependencies: ['Baseline'], - trials: 3, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - var startTime; - var errors = []; - logSpeakCall('Alpha Bravo Charlie Delta Echo', { - voiceName: voiceName, - rate: 2.0, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'start') { - startTime = new Date(); - } else if (evt.type == 'end') { - if (startTime == undefined) - startTime = callTime; - var endTime = new Date(); - var delta = (endTime - startTime) / 1000; - var relative = delta / resultMap['Baseline']; - if (relative < 0.35) { - errors.push('2x speech rate seems too fast.'); - } else if (relative > 0.65) { - errors.push('2x speech rate seems too slow.'); - } - callback(errors.length == 0, delta, errors); - } - } - }); - } - }, - { - name: 'Slow', - description: 'Speaks twice as slow and compares the time to the baseline.', - dependencies: ['Baseline'], - trials: 3, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - var startTime; - var errors = []; - logSpeakCall('Alpha Bravo Charlie Delta Echo', { - voiceName: voiceName, - rate: 0.5, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'start') { - startTime = new Date(); - } else if (evt.type == 'end') { - if (startTime == undefined) - startTime = callTime; - var endTime = new Date(); - var delta = (endTime - startTime) / 1000; - var relative = delta / resultMap['Baseline']; - if (relative < 1.6) { - errors.push('Half-speed speech rate seems too fast.'); - } else if (relative > 2.4) { - errors.push('Half-speed speech rate seems too slow.'); - } - callback(errors.length == 0, delta, errors); - } - } - }); - } - }, - { - name: 'Interrupt and restart', - description: 'Interrupts partway through a long sentence and then ' + - 'the baseline utterance, to make sure that speech after ' + - 'an interruption works correctly.', - dependencies: ['Baseline'], - trials: 1, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - var startTime; - var errors = []; - logSpeakCall('When in the course of human events it becomes ' + - 'necessary for one people to dissolve the political ' + - 'bands which have connected them ', { - voiceName: voiceName, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - } - }); - window.setTimeout(function() { - logSpeakCall('Alpha Bravo Charlie Delta Echo', { - voiceName: voiceName, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'start') { - startTime = new Date(); - } else if (evt.type == 'end') { - if (startTime == undefined) - startTime = callTime; - var endTime = new Date(); - var delta = (endTime - startTime) / 1000; - var relative = delta / resultMap['Baseline']; - if (relative < 0.9) { - errors.push('Interrupting speech seems too short.'); - } else if (relative > 1.1) { - errors.push('Interrupting speech seems too long.'); - } - callback(errors.length == 0, delta, errors); - } - } - }); - }, 4000); - } - }, - { - name: 'Low volume', - description: '<b>Manual</b> test - verify that the volume is lower.', - dependencies: [], - trials: 1, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - logSpeakCall('Alpha Bravo Charlie Delta Echo', { - voiceName: voiceName, - volume: 0.5, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'end') { - callback(true, null, []); - } - } - }); - } - }, - { - name: 'High pitch', - description: '<b>Manual</b> test - verify that the pitch is ' + - 'moderately higher, but quite understandable.', - dependencies: [], - trials: 1, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - logSpeakCall('Alpha Bravo Charlie Delta Echo', { - voiceName: voiceName, - pitch: 1.2, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'end') { - callback(true, null, []); - } - } - }); - } - }, - { - name: 'Low pitch', - description: '<b>Manual</b> test - verify that the pitch is ' + - 'moderately lower, but quite understandable.', - dependencies: [], - trials: 1, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - logSpeakCall('Alpha Bravo Charlie Delta Echo', { - voiceName: voiceName, - pitch: 0.8, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'end') { - callback(true, null, []); - } - } - }); - } - }, - { - name: 'Word and sentence callbacks', - description: 'Checks to see if proper word and sentence callbacks ' + - 'are received.', - dependencies: ['Baseline'], - trials: 1, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - var startTime; - var errors = []; - var wordExpected = [{min: 5, max: 6}, - {min: 11, max: 12}, - {min: 19, max: 20}, - {min: 25, max: 26}, - {min: 30, max: 32}, - {min: 37, max: 38}, - {min: 43, max: 44}, - {min: 51, max: 52}, - {min: 57, max: 58}]; - var sentenceExpected = [{min: 30, max: 32}] - var wordCount = 0; - var sentenceCount = 0; - var lastWordTime = callTime; - var lastSentenceTime = callTime; - var avgWordTime = resultMap['Baseline'] / 5; - logSpeakCall('Alpha Bravo Charlie Delta Echo. ' + - 'Alpha Bravo Charlie Delta Echo.', { - voiceName: voiceName, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'start') { - startTime = new Date(); - lastWordTime = startTime; - lastSentenceTime = startTime; - } else if (evt.type == 'word') { - if (evt.charIndex > 0 && evt.charIndex < 62) { - var min = wordExpected[wordCount].min; - var max = wordExpected[wordCount].max; - if (evt.charIndex < min || evt.charIndex > max) { - errors.push('Got word at charIndex ' + evt.charIndex + ', ' + - 'was expecting next word callback charIndex ' + - 'in the range ' + min + ':' + max + '.'); - } - if (wordCount != 4) { - var delta = (new Date() - lastWordTime) / 1000; - if (delta < 0.6 * avgWordTime) { - errors.push('Word at charIndex ' + evt.charIndex + - ' came after only ' + delta.toFixed(3) + - ' s, which seems too short.'); - } else if (delta > 1.3 * avgWordTime) { - errors.push('Word at charIndex ' + evt.charIndex + - ' came after ' + delta.toFixed(3) + - ' s, which seems too long.'); - } - } - wordCount++; - } - lastWordTime = new Date(); - } else if (evt.type == 'sentence') { - if (evt.charIndex > 0 && evt.charIndex < 62) { - var min = sentenceExpected[sentenceCount].min; - var max = sentenceExpected[sentenceCount].max; - if (evt.charIndex < min || evt.charIndex > max) { - errors.push('Got sentence at charIndex ' + evt.charIndex + - ', was expecting next callback charIndex ' + - 'in the range ' + min + ':' + max + '.'); - } - var delta = (new Date() - lastSentenceTime) / 1000; - if (delta < 0.75 * resultMap['Baseline']) { - errors.push('Sentence at charIndex ' + evt.charIndex + - ' came after only ' + delta.toFixed(3) + - ' s, which seems too short.'); - } else if (delta > 1.25 * resultMap['Baseline']) { - errors.push('Sentence at charIndex ' + evt.charIndex + - ' came after ' + delta.toFixed(3) + - ' s, which seems too long.'); - } - sentenceCount++; - } - lastSentenceTime = new Date(); - } else if (evt.type == 'end') { - if (wordCount == 0) { - errors.push('Didn\'t get any word callbacks.'); - } else if (wordCount < wordExpected.length) { - errors.push('Not enough word callbacks.'); - } else if (wordCount > wordExpected.length) { - errors.push('Too many word callbacks.'); - } - if (sentenceCount == 0) { - errors.push('Didn\'t get any sentence callbacks.'); - } else if (sentenceCount < sentenceExpected.length) { - errors.push('Not enough sentence callbacks.'); - } else if (sentenceCount > sentenceExpected.length) { - errors.push('Too many sentence callbacks.'); - } - if (startTime == undefined) { - errors.push('Error: no "start" event received!'); - startTime = callTime; - } - var endTime = new Date(); - var delta = (endTime - startTime) / 1000; - if (delta < 2.5) { - errors.push('Default speech rate seems too fast.'); - } else if (delta > 7.0) { - errors.push('Default speech rate seems too slow.'); - } - callback(errors.length == 0, delta, errors); - } - } - }); - } - }, - { - name: 'Baseline Queueing Test', - description: 'Establishes a baseline time to speak a ' + - 'sequence of three enqueued phrases, to compare ' + - 'other tests against.', - dependencies: [], - trials: 3, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - var startTime; - var errors = []; - logSpeakCall('Alpha Alpha', { - voiceName: voiceName, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'start') { - startTime = new Date(); - } - } - }); - logSpeakCall('Bravo bravo.', { - voiceName: voiceName, - enqueue: true, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } - } - }); - logSpeakCall('Charlie charlie', { - voiceName: voiceName, - enqueue: true, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'end') { - if (startTime == undefined) { - errors.push('Error: no "start" event received!'); - startTime = callTime; - } - var endTime = new Date(); - var delta = (endTime - startTime) / 1000; - callback(errors.length == 0, delta, errors); - } - } - }); - } - }, - { - name: 'Interruption with Queueing', - description: 'Queue a sequence of three utterances, then before they ' + - 'are finished, interrupt and queue a sequence of three ' + - 'more utterances. Make sure that interrupting and ' + - 'cancelling the previous utterances doesn\'t interfere ' + - 'with the interrupting utterances.', - dependencies: ['Baseline Queueing Test'], - trials: 1, - run: function(testRunName, voiceName, callback) { - var callTime = new Date(); - var startTime; - var errors = []; - - logSpeakCall('Just when I\'m about to say something interesting,', { - voiceName: voiceName - }); - logSpeakCall('it seems that I always get interrupted.', { - voiceName: voiceName, - enqueue: true, - }); - logSpeakCall('How rude! Will you ever let me finish?', { - voiceName: voiceName, - enqueue: true, - }); - - window.setTimeout(function() { - logSpeakCall('Alpha Alpha', { - voiceName: voiceName, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'start') { - startTime = new Date(); - } - } - }); - logSpeakCall('Bravo bravo.', { - voiceName: voiceName, - enqueue: true, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } - } - }); - logSpeakCall('Charlie charlie', { - voiceName: voiceName, - enqueue: true, - onEvent: function(evt) { - logEvent(callTime, testRunName, evt); - if (isErrorEvent(evt)) { - callback(false, null, []); - } else if (evt.type == 'end') { - if (startTime == undefined) { - errors.push('Error: no "start" event received!'); - startTime = callTime; - } - var endTime = new Date(); - var delta = (endTime - startTime) / 1000; - var relative = delta / resultMap['Baseline Queueing Test']; - if (relative < 0.9) { - errors.push('Interrupting speech seems too short.'); - } else if (relative > 1.1) { - errors.push('Interrupting speech seems too long.'); - } - callback(errors.length == 0, delta, errors); - } - } - }); - }, 4000); - } - } -]; - -function updateDependencies() { - for (var i = 0; i < updateDependencyFunctions.length; i++) { - updateDependencyFunctions[i](); - } -} - -function registerTest(test) { - var outer = document.createElement('div'); - outer.className = 'outer'; - $('container').appendChild(outer); - - var buttonWrap = document.createElement('div'); - buttonWrap.className = 'buttonWrap'; - outer.appendChild(buttonWrap); - - var button = document.createElement('button'); - button.className = 'runTestButton'; - button.innerText = test.name; - buttonWrap.appendChild(button); - - var busy = document.createElement('img'); - busy.src = 'pacman.gif'; - busy.alt = 'Busy indicator'; - buttonWrap.appendChild(busy); - busy.style.visibility = 'hidden'; - - var description = document.createElement('div'); - description.className = 'description'; - description.innerHTML = test.description; - outer.appendChild(description); - - var resultsWrap = document.createElement('div'); - resultsWrap.className = 'results'; - outer.appendChild(resultsWrap); - var results = []; - for (var j = 0; j < test.trials; j++) { - var result = document.createElement('span'); - resultsWrap.appendChild(result); - results.push(result); - } - var avg = document.createElement('span'); - resultsWrap.appendChild(avg); - - var messagesWrap = document.createElement('div'); - messagesWrap.className = 'messages'; - outer.appendChild(messagesWrap); - - var totalTime; - var successCount; - - function finishTrials() { - busy.style.visibility = 'hidden'; - if (successCount == test.trials) { - console.log('Test succeeded.'); - var success = document.createElement('div'); - success.className = 'success'; - success.innerText = 'Test succeeded.'; - messagesWrap.appendChild(success); - if (totalTime > 0.0) { - var avgTime = totalTime / test.trials; - avg.className = 'result'; - avg.innerText = 'Avg: ' + avgTime.toFixed(3) + ' s'; - resultMap[test.name] = avgTime; - updateDependencies(); - } - } else { - console.log('Test failed.'); - var failure = document.createElement('div'); - failure.className = 'failure'; - failure.innerText = 'Test failed.'; - messagesWrap.appendChild(failure); - } - } - - function runTest(index, voiceName) { - if (emergencyStop) { - busy.style.visibility = 'hidden'; - emergencyStop = false; - return; - } - var testRunName = 'Test run ' + testRunIndex + ', ' + - test.name + ', trial ' + (index+1) + ' of ' + - test.trials; - console.log('*** Beginning ' + testRunName + - ' with voice ' + voiceName); - test.run(testRunName, voiceName, function(success, resultTime, errors) { - if (success) { - successCount++; - } - for (var i = 0; i < errors.length; i++) { - console.log(errors[i]); - var error = document.createElement('div'); - error.className = 'error'; - error.innerText = errors[i]; - messagesWrap.appendChild(error); - } - if (resultTime != null) { - results[index].className = 'result'; - results[index].innerText = resultTime.toFixed(3) + ' s'; - totalTime += resultTime; - } - index++; - if (index < test.trials) { - runTest(index, voiceName); - } else { - finishTrials(); - } - }); - } - - button.addEventListener('click', function() { - var voiceIndex = $('voices').selectedIndex - 1; - if (voiceIndex < 0) { - alert('Please select a voice first!'); - return; - } - testRunIndex++; - busy.style.visibility = 'visible'; - totalTime = 0.0; - successCount = 0; - messagesWrap.innerHTML = ''; - var voiceName = voiceArray[voiceIndex].voiceName; - runTest(0, voiceName); - }, false); - - updateDependencyFunctions.push(function() { - for (var i = 0; i < test.dependencies.length; i++) { - if (resultMap[test.dependencies[i]] != undefined) { - button.disabled = false; - outer.className = 'outer'; - } else { - button.disabled = true; - outer.className = 'outer disabled'; - } - } - }); -} - -function load() { - var voice = localStorage['voice']; - chrome.tts.getVoices(function(va) { - voiceArray = va; - for (var i = 0; i < voiceArray.length; i++) { - var opt = document.createElement('option'); - var name = voiceArray[i].voiceName; - if (name == localStorage['voice']) { - opt.setAttribute('selected', ''); - } - opt.setAttribute('value', name); - opt.innerText = voiceArray[i].voiceName; - $('voices').appendChild(opt); - } - }); - $('voices').addEventListener('change', function() { - var i = $('voices').selectedIndex; - localStorage['voice'] = $('voices').item(i).value; - }, false); - $('stop').addEventListener('click', stop); - - for (var i = 0; i < tests.length; i++) { - registerTest(tests[i]); - } - updateDependencies(); -} - -function stop() { - console.log('*** Emergency stop!'); - emergencyStop = true; - chrome.tts.stop(); -} - -document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdemo/128.png b/chrome/common/extensions/docs/examples/extensions/ttsdemo/128.png deleted file mode 100644 index b9ba0f38..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdemo/128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdemo/16.png b/chrome/common/extensions/docs/examples/extensions/ttsdemo/16.png deleted file mode 100644 index d206ec1..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdemo/16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdemo/256.png b/chrome/common/extensions/docs/examples/extensions/ttsdemo/256.png deleted file mode 100644 index 2990023..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdemo/256.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdemo/manifest.json b/chrome/common/extensions/docs/examples/extensions/ttsdemo/manifest.json deleted file mode 100644 index ade1281d..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdemo/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "app": { - "launch": { - "local_path": "ttsdemo.html" - } - }, - "description": "Demo Chrome's synthesized text-to-speech capabilities.", - "icons": { - "16": "16.png", - "128": "128.png", - "256": "256.png" - }, - "minimum_chrome_version": "14", - "name": "TTS Demo", - "permissions": [ "tts" ], - "version": "2.1", - - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdemo/ttsdemo.html b/chrome/common/extensions/docs/examples/extensions/ttsdemo/ttsdemo.html deleted file mode 100644 index 6f916364..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdemo/ttsdemo.html +++ /dev/null
@@ -1,172 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <title>Chrome TTS Demo</title> - <style> - body { - font-family: arial, helvetica, sans-serif; - } - .banner { - width: 100%; - float: left; - } - .banner_left { - padding: 8px; - float: left; - } - .banner_right { - padding: 8px; - } - .body_wrapper { - width: 100%; - float: left; - } - .body_left { - border: 0; - padding: 0; - margin: 0; - width: 50%; - float: left; - } - .body_right { - border: 0; - padding: 0; - margin: 0; - width: 46%; - float: left; - } - .body_inner { - padding: 0 32px; - } - #srctext { - width: 100%; - font-size: 133%; - } - .large_button { - font-size: 166%; - padding: 6pt 12pt 6pt 12pt; - } - .box { - margin: 10px; - padding: 10px; - border: 1px solid #999; - } - .tabbable { - padding: 10px; - border: 1px solid #00C; - } - table { - margin-left: auto; - margin-right: auto; - } - #help { - text-align: left; - } - #voiceInfo { - text-align: left; - padding: 4px; - border: 1px solid #aaa; - width: 100%; - min-height: 100px; - overflow: auto; - } - </style> - <script src="ttsdemo.js"></script> -</head> - -<body> - -<div class="banner"> - <div class="banner_left"> - <img src="128.png" class="logo" alt=""> - </div> - <div class="banner_right"> - <h1>Chrome Text-to-Speech Demo</h1> - <p> - Use this application to try out all of the text-to-speech voices in Chrome, or - <a href="https://chrome.google.com/webstore/search?q=tts">Search the Chrome Web Store</a> - for more TTS voices. - </p> - </div> -</div> - -<div class="body_wrapper"> - <div class="body_left"> - <div class="body_inner"> - - Enter text here: - <textarea id="srctext" rows="6" cols="40">This is a demo of text-to-speech in Chrome.</textarea> - - <p> - <button class="large_button" id="speakUserTextButton">Speak</button> - <button class="large_button" id="stopButton">Stop</button> - </p> - - <div class="box" id="ttsStatusBox"> - TTS status: <b><span id="ttsStatus"></span></b> - </div> - - <p> - - Click on or tab to these boxes: - - <p> - - <span tabindex="0" class="tabbable" id="speakAlpha">Alpha</span> - <span tabindex="0" class="tabbable" id="speakBravo">Bravo</span> - <span tabindex="0" class="tabbable" id="speakCharlie">Charlie</span> - <span tabindex="0" class="tabbable" id="speakDelta">Delta</span> - <span tabindex="0" class="tabbable" id="speakEcho">Echo</span> - <span tabindex="0" class="tabbable" id="speakFoxtrot">Foxtrot</span> - - </div> - </div> - <div class="body_right"> - <div class="body_inner"> - - <table class="simple"> - <tr> - <td>Voice:</td> - <td><select id="voices"> - <option value="">Unspecified</option> - </select></td> - </td> - </tr> - <tr> - <td>Lang:</td> - <td><select id="lang"> - <option value="">Unspecified</option> - <option value="de">de (German)</option> - <option value="en-GB">en-GB (British English)</option> - <option value="en-US" selected>en-US (American English)</option> - <option value="es">es (Spanish)</option> - <option value="fr">fr (French)</option> - <option value="it">it (Italian)</option> - </select></td></tr> - <tr> - <td>Queuing mode:</td> - <td><select id="enqueue"> - <option value="">Interrupt</option> - <option value="true">Enqueue</option> - </select></td></tr> - <tr> - <td>Rate:</td> - <td><input id="rate" type="range" min="0.5" max="4.0" value="1.0" step="0.1"> - </td></tr> - <tr> - <td>Pitch:</td> - <td><input id="pitch" type="range" min="0.0" max="2.0" value="1.0" step="0.2"> - </td></tr> - <tr> - <td>Volume:</td> - <td><input id="volume" type="range" min="0.0" max="1.0" value="1.0" step="0.1"> - </td></tr> - </table> - - <pre id="voiceInfo"></pre> - </div> - </div> -</div> - -</body> -</html>
diff --git a/chrome/common/extensions/docs/examples/extensions/ttsdemo/ttsdemo.js b/chrome/common/extensions/docs/examples/extensions/ttsdemo/ttsdemo.js deleted file mode 100644 index 518dbce..0000000 --- a/chrome/common/extensions/docs/examples/extensions/ttsdemo/ttsdemo.js +++ /dev/null
@@ -1,128 +0,0 @@ -/** - * Copyright (c) 2012 The Chromium Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -var text; -var ttsStatus; -var ttsStatusBox; -var lang; -var enqueue; -var voices; -var voiceInfo; -var voiceArray; -var utteranceIndex = 0; - -function load() { - text = document.getElementById('srctext'); - ttsStatus = document.getElementById('ttsStatus'); - ttsStatusBox = document.getElementById('ttsStatusBox'); - lang = document.getElementById('lang'); - enqueue = document.getElementById('enqueue'); - voices = document.getElementById('voices'); - voiceInfo = document.getElementById('voiceInfo'); - - document.getElementById('speakUserTextButton') - .addEventListener('click', speakUserText); - document.getElementById('stopButton') - .addEventListener('click', stop); - - const speechOptions = [ - { id: 'speakAlpha', text: 'Alpha' }, - { id: 'speakBravo', text: 'Bravo' }, - { id: 'speakCharlie', text: 'Charlie' }, - { id: 'speakDelta', text: 'Delta' }, - { id: 'speakEcho', text: 'Echo' }, - { id: 'speakFoxtrot', text: 'Foxtrot' }, - ]; - - for (const option of speechOptions) { - document.getElementById(option.id) - .addEventListener('focus', function(){ speak(option.text); }); - } - - chrome.tts.getVoices(function(va) { - voiceArray = va; - for (var i = 0; i < voiceArray.length; i++) { - var opt = document.createElement('option'); - opt.setAttribute('value', voiceArray[i].voiceName); - opt.innerText = voiceArray[i].voiceName; - voices.appendChild(opt); - } - }); - voices.addEventListener('change', function() { - var i = voices.selectedIndex - 1; - if (i >= 0) { - voiceInfo.innerText = JSON.stringify(voiceArray[i], null, 2); - } else { - voiceInfo.innerText = ''; - } - }, false); -} - -function speak(str, options, highlightText) { - if (!options) { - options = {}; - } - if (enqueue.value) { - options.enqueue = Boolean(enqueue.value); - } - var voiceIndex = voices.selectedIndex - 1; - if (voiceIndex >= 0) { - options.voiceName = voiceArray[voiceIndex].voiceName; - } - var rateValue = Number(rate.value); - if (rateValue >= 0.1 && rateValue <= 10.0) { - options.rate = rateValue; - } - var pitchValue = Number(pitch.value); - if (pitchValue >= 0.0 && pitchValue <= 2.0) { - options.pitch = pitchValue; - } - var volumeValue = Number(volume.value); - if (volumeValue >= 0.0 && volumeValue <= 1.0) { - options.volume = volumeValue; - } - utteranceIndex++; - console.log(utteranceIndex + ': ' + JSON.stringify(options)); - options.onEvent = function(event) { - console.log(utteranceIndex + ': ' + JSON.stringify(event)); - if (highlightText) { - text.setSelectionRange(0, event.charIndex); - } - if (event.type == 'end' || - event.type == 'interrupted' || - event.type == 'cancelled' || - event.type == 'error') { - chrome.tts.isSpeaking(function(isSpeaking) { - if (!isSpeaking) { - ttsStatus.innerHTML = 'Idle'; - ttsStatusBox.style.background = '#fff'; - } - }); - } - }; - chrome.tts.speak( - str, options, function() { - if (chrome.runtime.lastError) { - console.log('TTS Error: ' + chrome.runtime.lastError.message); - } - }); - ttsStatus.innerHTML = 'Busy'; - ttsStatusBox.style.background = '#ffc'; -} - -function stop() { - chrome.tts.stop(); -} - -function speakUserText() { - var options = {}; - if (lang.value) { - options.lang = lang.value; - } - speak(text.value, options, true); -} - -document.addEventListener('DOMContentLoaded', load);
diff --git a/chrome/common/extensions/docs/examples/howto/sandbox/LICENSE.handlebars b/chrome/common/extensions/docs/examples/howto/sandbox/LICENSE.handlebars deleted file mode 100644 index 237cd0346..0000000 --- a/chrome/common/extensions/docs/examples/howto/sandbox/LICENSE.handlebars +++ /dev/null
@@ -1,20 +0,0 @@ -Copyright (C) 2011 by Yehuda Katz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -
diff --git a/chrome/common/extensions/docs/examples/howto/sandbox/eventpage.html b/chrome/common/extensions/docs/examples/howto/sandbox/eventpage.html deleted file mode 100644 index 8a29dbb..0000000 --- a/chrome/common/extensions/docs/examples/howto/sandbox/eventpage.html +++ /dev/null
@@ -1,14 +0,0 @@ -<!-- - - Copyright (c) 2012 The Chromium Authors. All rights reserved. - - Use of this source code is governed by a BSD-style license that can be - - found in the LICENSE file. - --> -<!doctype html> -<html> - <head> - <script src="eventpage.js"></script> - </head> - <body> - <iframe id="theFrame" src="sandbox.html"></iframe> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/howto/sandbox/eventpage.js b/chrome/common/extensions/docs/examples/howto/sandbox/eventpage.js deleted file mode 100644 index feb07385..0000000 --- a/chrome/common/extensions/docs/examples/howto/sandbox/eventpage.js +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -chrome.browserAction.onClicked.addListener(function() { - var iframe = document.getElementById('theFrame'); - var message = { - command: 'render', - context: {thing: 'world'} - }; - iframe.contentWindow.postMessage(message, '*'); -}); - - -window.addEventListener('message', function(event) { - if (event.data.html) { - new Notification('Templated!', { - icon: 'icon.png', - body: 'HTML Received for "' + event.data.name + '": `' + - event.data.html + '`' - }); - } -});
diff --git a/chrome/common/extensions/docs/examples/howto/sandbox/handlebars-1.0.0.beta.6.js b/chrome/common/extensions/docs/examples/howto/sandbox/handlebars-1.0.0.beta.6.js deleted file mode 100644 index 4f9e2c5..0000000 --- a/chrome/common/extensions/docs/examples/howto/sandbox/handlebars-1.0.0.beta.6.js +++ /dev/null
@@ -1,1553 +0,0 @@ -// Copyright (C) 2011 by Yehuda Katz -// Licensing details in LICENSE.handlebars - -// lib/handlebars/base.js -var Handlebars = {}; - -Handlebars.VERSION = "1.0.beta.6"; - -Handlebars.helpers = {}; -Handlebars.partials = {}; - -Handlebars.registerHelper = function(name, fn, inverse) { - if(inverse) { fn.not = inverse; } - this.helpers[name] = fn; -}; - -Handlebars.registerPartial = function(name, str) { - this.partials[name] = str; -}; - -Handlebars.registerHelper('helperMissing', function(arg) { - if(arguments.length === 2) { - return undefined; - } else { - throw new Error("Could not find property '" + arg + "'"); - } -}); - -var toString = Object.prototype.toString, functionType = "[object Function]"; - -Handlebars.registerHelper('blockHelperMissing', function(context, options) { - var inverse = options.inverse || function() {}, fn = options.fn; - - - var ret = ""; - var type = toString.call(context); - - if(type === functionType) { context = context.call(this); } - - if(context === true) { - return fn(this); - } else if(context === false || context == null) { - return inverse(this); - } else if(type === "[object Array]") { - if(context.length > 0) { - for(var i=0, j=context.length; i<j; i++) { - ret = ret + fn(context[i]); - } - } else { - ret = inverse(this); - } - return ret; - } else { - return fn(context); - } -}); - -Handlebars.registerHelper('each', function(context, options) { - var fn = options.fn, inverse = options.inverse; - var ret = ""; - - if(context && context.length > 0) { - for(var i=0, j=context.length; i<j; i++) { - ret = ret + fn(context[i]); - } - } else { - ret = inverse(this); - } - return ret; -}); - -Handlebars.registerHelper('if', function(context, options) { - var type = toString.call(context); - if(type === functionType) { context = context.call(this); } - - if(!context || Handlebars.Utils.isEmpty(context)) { - return options.inverse(this); - } else { - return options.fn(this); - } -}); - -Handlebars.registerHelper('unless', function(context, options) { - var fn = options.fn, inverse = options.inverse; - options.fn = inverse; - options.inverse = fn; - - return Handlebars.helpers['if'].call(this, context, options); -}); - -Handlebars.registerHelper('with', function(context, options) { - return options.fn(context); -}); - -Handlebars.registerHelper('log', function(context) { - Handlebars.log(context); -}); -; -// lib/handlebars/compiler/parser.js -/* Jison generated parser */ -var handlebars = (function(){ - -var parser = {trace: function trace() { }, -yy: {}, -symbols_: {"error":2,"root":3,"program":4,"EOF":5,"statements":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"params":25,"hash":26,"param":27,"STRING":28,"INTEGER":29,"BOOLEAN":30,"hashSegments":31,"hashSegment":32,"ID":33,"EQUALS":34,"pathSegments":35,"SEP":36,"$accept":0,"$end":1}, -terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"STRING",29:"INTEGER",30:"BOOLEAN",33:"ID",34:"EQUALS",36:"SEP"}, -productions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[25,2],[25,1],[27,1],[27,1],[27,1],[27,1],[26,1],[31,2],[31,1],[32,3],[32,3],[32,3],[32,3],[21,1],[35,3],[35,1]], -performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { - -var $0 = $$.length - 1; -switch (yystate) { -case 1: return $$[$0-1] -break; -case 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]) -break; -case 3: this.$ = new yy.ProgramNode($$[$0]) -break; -case 4: this.$ = new yy.ProgramNode([]) -break; -case 5: this.$ = [$$[$0]] -break; -case 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] -break; -case 7: this.$ = new yy.InverseNode($$[$0-2], $$[$0-1], $$[$0]) -break; -case 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0]) -break; -case 9: this.$ = $$[$0] -break; -case 10: this.$ = $$[$0] -break; -case 11: this.$ = new yy.ContentNode($$[$0]) -break; -case 12: this.$ = new yy.CommentNode($$[$0]) -break; -case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) -break; -case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) -break; -case 15: this.$ = $$[$0-1] -break; -case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]) -break; -case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true) -break; -case 18: this.$ = new yy.PartialNode($$[$0-1]) -break; -case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]) -break; -case 20: -break; -case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]] -break; -case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null] -break; -case 23: this.$ = [[$$[$0-1]], $$[$0]] -break; -case 24: this.$ = [[$$[$0]], null] -break; -case 25: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; -break; -case 26: this.$ = [$$[$0]] -break; -case 27: this.$ = $$[$0] -break; -case 28: this.$ = new yy.StringNode($$[$0]) -break; -case 29: this.$ = new yy.IntegerNode($$[$0]) -break; -case 30: this.$ = new yy.BooleanNode($$[$0]) -break; -case 31: this.$ = new yy.HashNode($$[$0]) -break; -case 32: $$[$0-1].push($$[$0]); this.$ = $$[$0-1] -break; -case 33: this.$ = [$$[$0]] -break; -case 34: this.$ = [$$[$0-2], $$[$0]] -break; -case 35: this.$ = [$$[$0-2], new yy.StringNode($$[$0])] -break; -case 36: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])] -break; -case 37: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])] -break; -case 38: this.$ = new yy.IdNode($$[$0]) -break; -case 39: $$[$0-2].push($$[$0]); this.$ = $$[$0-2]; -break; -case 40: this.$ = [$$[$0]] -break; -} -}, -table: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,33:[1,25],35:24},{17:26,21:23,33:[1,25],35:24},{17:27,21:23,33:[1,25],35:24},{17:28,21:23,33:[1,25],35:24},{21:29,33:[1,25],35:24},{1:[2,1]},{6:30,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,31],21:23,33:[1,25],35:24},{10:32,20:[1,33]},{10:34,20:[1,33]},{18:[1,35]},{18:[2,24],21:40,25:36,26:37,27:38,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,38],28:[2,38],29:[2,38],30:[2,38],33:[2,38],36:[1,46]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],36:[2,40]},{18:[1,47]},{18:[1,48]},{18:[1,49]},{18:[1,50],21:51,33:[1,25],35:24},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:52,33:[1,25],35:24},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:40,26:53,27:54,28:[1,41],29:[1,42],30:[1,43],31:39,32:44,33:[1,45],35:24},{18:[2,23]},{18:[2,26],28:[2,26],29:[2,26],30:[2,26],33:[2,26]},{18:[2,31],32:55,33:[1,56]},{18:[2,27],28:[2,27],29:[2,27],30:[2,27],33:[2,27]},{18:[2,28],28:[2,28],29:[2,28],30:[2,28],33:[2,28]},{18:[2,29],28:[2,29],29:[2,29],30:[2,29],33:[2,29]},{18:[2,30],28:[2,30],29:[2,30],30:[2,30],33:[2,30]},{18:[2,33],33:[2,33]},{18:[2,40],28:[2,40],29:[2,40],30:[2,40],33:[2,40],34:[1,57],36:[2,40]},{33:[1,58]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,59]},{18:[1,60]},{18:[2,21]},{18:[2,25],28:[2,25],29:[2,25],30:[2,25],33:[2,25]},{18:[2,32],33:[2,32]},{34:[1,57]},{21:61,28:[1,62],29:[1,63],30:[1,64],33:[1,25],35:24},{18:[2,39],28:[2,39],29:[2,39],30:[2,39],33:[2,39],36:[2,39]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,34],33:[2,34]},{18:[2,35],33:[2,35]},{18:[2,36],33:[2,36]},{18:[2,37],33:[2,37]}], -defaultActions: {16:[2,1],37:[2,23],53:[2,21]}, -parseError: function parseError(str, hash) { - throw new Error(str); -}, -parse: function parse(input) { - var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; - this.lexer.setInput(input); - this.lexer.yy = this.yy; - this.yy.lexer = this.lexer; - if (typeof this.lexer.yylloc == "undefined") - this.lexer.yylloc = {}; - var yyloc = this.lexer.yylloc; - lstack.push(yyloc); - if (typeof this.yy.parseError === "function") - this.parseError = this.yy.parseError; - function popStack(n) { - stack.length = stack.length - 2 * n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - function lex() { - var token; - token = self.lexer.lex() || 1; - if (typeof token !== "number") { - token = self.symbols_[token] || token; - } - return token; - } - var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; - while (true) { - state = stack[stack.length - 1]; - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol == null) - symbol = lex(); - action = table[state] && table[state][symbol]; - } - if (typeof action === "undefined" || !action.length || !action[0]) { - if (!recovering) { - expected = []; - for (p in table[state]) - if (this.terminals_[p] && p > 2) { - expected.push("'" + this.terminals_[p] + "'"); - } - var errStr = ""; - if (this.lexer.showPosition) { - errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + this.terminals_[symbol] + "'"; - } else { - errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); - } - this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); - } - } - if (action[0] instanceof Array && action.length > 1) { - throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); - } - switch (action[0]) { - case 1: - stack.push(symbol); - vstack.push(this.lexer.yytext); - lstack.push(this.lexer.yylloc); - stack.push(action[1]); - symbol = null; - if (!preErrorSymbol) { - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - if (recovering > 0) - recovering--; - } else { - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - case 2: - len = this.productions_[action[1]][1]; - yyval.$ = vstack[vstack.length - len]; - yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; - r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); - if (typeof r !== "undefined") { - return r; - } - if (len) { - stack = stack.slice(0, -1 * len * 2); - vstack = vstack.slice(0, -1 * len); - lstack = lstack.slice(0, -1 * len); - } - stack.push(this.productions_[action[1]][0]); - vstack.push(yyval.$); - lstack.push(yyval._$); - newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; - stack.push(newState); - break; - case 3: - return true; - } - } - return true; -} -};/* Jison generated lexer */ -var lexer = (function(){ - -var lexer = ({EOF:1, -parseError:function parseError(str, hash) { - if (this.yy.parseError) { - this.yy.parseError(str, hash); - } else { - throw new Error(str); - } - }, -setInput:function (input) { - this._input = input; - this._more = this._less = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; - return this; - }, -input:function () { - var ch = this._input[0]; - this.yytext+=ch; - this.yyleng++; - this.match+=ch; - this.matched+=ch; - var lines = ch.match(/\n/); - if (lines) this.yylineno++; - this._input = this._input.slice(1); - return ch; - }, -unput:function (ch) { - this._input = ch + this._input; - return this; - }, -more:function () { - this._more = true; - return this; - }, -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); - }, -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c+"^"; - }, -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) this.done = true; - - var token, - match, - col, - lines; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i=0;i < rules.length; i++) { - match = this._input.match(this.rules[rules[i]]); - if (match) { - lines = match[0].match(/\n.*/g); - if (lines) this.yylineno += lines.length; - this.yylloc = {first_line: this.yylloc.last_line, - last_line: this.yylineno+1, - first_column: this.yylloc.last_column, - last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - this._more = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]); - if (token) return token; - else return; - } - } - if (this._input === "") { - return this.EOF; - } else { - this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), - {text: "", token: null, line: this.yylineno}); - } - }, -lex:function lex() { - var r = this.next(); - if (typeof r !== 'undefined') { - return r; - } else { - return this.lex(); - } - }, -begin:function begin(condition) { - this.conditionStack.push(condition); - }, -popState:function popState() { - return this.conditionStack.pop(); - }, -_currentRules:function _currentRules() { - return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; - }, -topState:function () { - return this.conditionStack[this.conditionStack.length-2]; - }, -pushState:function begin(condition) { - this.begin(condition); - }}); -lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { - -var YYSTATE=YY_START -switch($avoiding_name_collisions) { -case 0: - if(yy_.yytext.slice(-1) !== "\\") this.begin("mu"); - if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu"); - if(yy_.yytext) return 14; - -break; -case 1: return 14; -break; -case 2: this.popState(); return 14; -break; -case 3: return 24; -break; -case 4: return 16; -break; -case 5: return 20; -break; -case 6: return 19; -break; -case 7: return 19; -break; -case 8: return 23; -break; -case 9: return 23; -break; -case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; -break; -case 11: return 22; -break; -case 12: return 34; -break; -case 13: return 33; -break; -case 14: return 33; -break; -case 15: return 36; -break; -case 16: /*ignore whitespace*/ -break; -case 17: this.popState(); return 18; -break; -case 18: this.popState(); return 18; -break; -case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 28; -break; -case 20: return 30; -break; -case 21: return 30; -break; -case 22: return 29; -break; -case 23: return 33; -break; -case 24: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 33; -break; -case 25: return 'INVALID'; -break; -case 26: return 5; -break; -} -}; -lexer.rules = [/^[^\x00]*?(?=(\{\{))/,/^[^\x00]+/,/^[^\x00]{2,}?(?=(\{\{))/,/^\{\{>/,/^\{\{#/,/^\{\{\//,/^\{\{\^/,/^\{\{\s*else\b/,/^\{\{\{/,/^\{\{&/,/^\{\{![\s\S]*?\}\}/,/^\{\{/,/^=/,/^\.(?=[} ])/,/^\.\./,/^[\/.]/,/^\s+/,/^\}\}\}/,/^\}\}/,/^"(\\["]|[^"])*"/,/^true(?=[}\s])/,/^false(?=[}\s])/,/^[0-9]+(?=[}\s])/,/^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/,/^\[[^\]]*\]/,/^./,/^$/]; -lexer.conditions = {"mu":{"rules":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"INITIAL":{"rules":[0,1,26],"inclusive":true}};return lexer;})() -parser.lexer = lexer; -return parser; -})(); -if (typeof require !== 'undefined' && typeof exports !== 'undefined') { -exports.parser = handlebars; -exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); } -exports.main = function commonjsMain(args) { - if (!args[1]) - throw new Error('Usage: '+args[0]+' FILE'); - if (typeof process !== 'undefined') { - var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); - } else { - var cwd = require("file").path(require("file").cwd()); - var source = cwd.join(args[1]).read({charset: "utf-8"}); - } - return exports.parser.parse(source); -} -if (typeof module !== 'undefined' && require.main === module) { - exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); -} -}; -; -// lib/handlebars/compiler/base.js -Handlebars.Parser = handlebars; - -Handlebars.parse = function(string) { - Handlebars.Parser.yy = Handlebars.AST; - return Handlebars.Parser.parse(string); -}; - -Handlebars.print = function(ast) { - return new Handlebars.PrintVisitor().accept(ast); -}; - -Handlebars.logger = { - DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3, - - // override in the host environment - log: function(level, str) {} -}; - -Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); }; -; -// lib/handlebars/compiler/ast.js -(function() { - - Handlebars.AST = {}; - - Handlebars.AST.ProgramNode = function(statements, inverse) { - this.type = "program"; - this.statements = statements; - if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); } - }; - - Handlebars.AST.MustacheNode = function(params, hash, unescaped) { - this.type = "mustache"; - this.id = params[0]; - this.params = params.slice(1); - this.hash = hash; - this.escaped = !unescaped; - }; - - Handlebars.AST.PartialNode = function(id, context) { - this.type = "partial"; - - // TODO: disallow complex IDs - - this.id = id; - this.context = context; - }; - - var verifyMatch = function(open, close) { - if(open.original !== close.original) { - throw new Handlebars.Exception(open.original + " doesn't match " + close.original); - } - }; - - Handlebars.AST.BlockNode = function(mustache, program, close) { - verifyMatch(mustache.id, close); - this.type = "block"; - this.mustache = mustache; - this.program = program; - }; - - Handlebars.AST.InverseNode = function(mustache, program, close) { - verifyMatch(mustache.id, close); - this.type = "inverse"; - this.mustache = mustache; - this.program = program; - }; - - Handlebars.AST.ContentNode = function(string) { - this.type = "content"; - this.string = string; - }; - - Handlebars.AST.HashNode = function(pairs) { - this.type = "hash"; - this.pairs = pairs; - }; - - Handlebars.AST.IdNode = function(parts) { - this.type = "ID"; - this.original = parts.join("."); - - var dig = [], depth = 0; - - for(var i=0,l=parts.length; i<l; i++) { - var part = parts[i]; - - if(part === "..") { depth++; } - else if(part === "." || part === "this") { this.isScoped = true; } - else { dig.push(part); } - } - - this.parts = dig; - this.string = dig.join('.'); - this.depth = depth; - this.isSimple = (dig.length === 1) && (depth === 0); - }; - - Handlebars.AST.StringNode = function(string) { - this.type = "STRING"; - this.string = string; - }; - - Handlebars.AST.IntegerNode = function(integer) { - this.type = "INTEGER"; - this.integer = integer; - }; - - Handlebars.AST.BooleanNode = function(bool) { - this.type = "BOOLEAN"; - this.bool = bool; - }; - - Handlebars.AST.CommentNode = function(comment) { - this.type = "comment"; - this.comment = comment; - }; - -})();; -// lib/handlebars/utils.js -Handlebars.Exception = function(message) { - var tmp = Error.prototype.constructor.apply(this, arguments); - - for (var p in tmp) { - if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; } - } - - this.message = tmp.message; -}; -Handlebars.Exception.prototype = new Error; - -// Build out our basic SafeString type -Handlebars.SafeString = function(string) { - this.string = string; -}; -Handlebars.SafeString.prototype.toString = function() { - return this.string.toString(); -}; - -(function() { - var escape = { - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - - var badChars = /&(?!\w+;)|[<>"'`]/g; - var possible = /[&<>"'`]/; - - var escapeChar = function(chr) { - return escape[chr] || "&"; - }; - - Handlebars.Utils = { - escapeExpression: function(string) { - // don't escape SafeStrings, since they're already safe - if (string instanceof Handlebars.SafeString) { - return string.toString(); - } else if (string == null || string === false) { - return ""; - } - - if(!possible.test(string)) { return string; } - return string.replace(badChars, escapeChar); - }, - - isEmpty: function(value) { - if (typeof value === "undefined") { - return true; - } else if (value === null) { - return true; - } else if (value === false) { - return true; - } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { - return true; - } else { - return false; - } - } - }; -})();; -// lib/handlebars/compiler/compiler.js -Handlebars.Compiler = function() {}; -Handlebars.JavaScriptCompiler = function() {}; - -(function(Compiler, JavaScriptCompiler) { - Compiler.OPCODE_MAP = { - appendContent: 1, - getContext: 2, - lookupWithHelpers: 3, - lookup: 4, - append: 5, - invokeMustache: 6, - appendEscaped: 7, - pushString: 8, - truthyOrFallback: 9, - functionOrFallback: 10, - invokeProgram: 11, - invokePartial: 12, - push: 13, - assignToHash: 15, - pushStringParam: 16 - }; - - Compiler.MULTI_PARAM_OPCODES = { - appendContent: 1, - getContext: 1, - lookupWithHelpers: 2, - lookup: 1, - invokeMustache: 3, - pushString: 1, - truthyOrFallback: 1, - functionOrFallback: 1, - invokeProgram: 3, - invokePartial: 1, - push: 1, - assignToHash: 1, - pushStringParam: 1 - }; - - Compiler.DISASSEMBLE_MAP = {}; - - for(var prop in Compiler.OPCODE_MAP) { - var value = Compiler.OPCODE_MAP[prop]; - Compiler.DISASSEMBLE_MAP[value] = prop; - } - - Compiler.multiParamSize = function(code) { - return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]]; - }; - - Compiler.prototype = { - compiler: Compiler, - - disassemble: function() { - var opcodes = this.opcodes, opcode, nextCode; - var out = [], str, name, value; - - for(var i=0, l=opcodes.length; i<l; i++) { - opcode = opcodes[i]; - - if(opcode === 'DECLARE') { - name = opcodes[++i]; - value = opcodes[++i]; - out.push("DECLARE " + name + " = " + value); - } else { - str = Compiler.DISASSEMBLE_MAP[opcode]; - - var extraParams = Compiler.multiParamSize(opcode); - var codes = []; - - for(var j=0; j<extraParams; j++) { - nextCode = opcodes[++i]; - - if(typeof nextCode === "string") { - nextCode = "\"" + nextCode.replace("\n", "\\n") + "\""; - } - - codes.push(nextCode); - } - - str = str + " " + codes.join(" "); - - out.push(str); - } - } - - return out.join("\n"); - }, - - guid: 0, - - compile: function(program, options) { - this.children = []; - this.depths = {list: []}; - this.options = options; - - // These changes will propagate to the other compiler components - var knownHelpers = this.options.knownHelpers; - this.options.knownHelpers = { - 'helperMissing': true, - 'blockHelperMissing': true, - 'each': true, - 'if': true, - 'unless': true, - 'with': true, - 'log': true - }; - if (knownHelpers) { - for (var name in knownHelpers) { - this.options.knownHelpers[name] = knownHelpers[name]; - } - } - - return this.program(program); - }, - - accept: function(node) { - return this[node.type](node); - }, - - program: function(program) { - var statements = program.statements, statement; - this.opcodes = []; - - for(var i=0, l=statements.length; i<l; i++) { - statement = statements[i]; - this[statement.type](statement); - } - this.isSimple = l === 1; - - this.depths.list = this.depths.list.sort(function(a, b) { - return a - b; - }); - - return this; - }, - - compileProgram: function(program) { - var result = new this.compiler().compile(program, this.options); - var guid = this.guid++; - - this.usePartial = this.usePartial || result.usePartial; - - this.children[guid] = result; - - for(var i=0, l=result.depths.list.length; i<l; i++) { - depth = result.depths.list[i]; - - if(depth < 2) { continue; } - else { this.addDepth(depth - 1); } - } - - return guid; - }, - - block: function(block) { - var mustache = block.mustache; - var depth, child, inverse, inverseGuid; - - var params = this.setupStackForMustache(mustache); - - var programGuid = this.compileProgram(block.program); - - if(block.program.inverse) { - inverseGuid = this.compileProgram(block.program.inverse); - this.declare('inverse', inverseGuid); - } - - this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash); - this.declare('inverse', null); - this.opcode('append'); - }, - - inverse: function(block) { - var params = this.setupStackForMustache(block.mustache); - - var programGuid = this.compileProgram(block.program); - - this.declare('inverse', programGuid); - - this.opcode('invokeProgram', null, params.length, !!block.mustache.hash); - this.declare('inverse', null); - this.opcode('append'); - }, - - hash: function(hash) { - var pairs = hash.pairs, pair, val; - - this.opcode('push', '{}'); - - for(var i=0, l=pairs.length; i<l; i++) { - pair = pairs[i]; - val = pair[1]; - - this.accept(val); - this.opcode('assignToHash', pair[0]); - } - }, - - partial: function(partial) { - var id = partial.id; - this.usePartial = true; - - if(partial.context) { - this.ID(partial.context); - } else { - this.opcode('push', 'depth0'); - } - - this.opcode('invokePartial', id.original); - this.opcode('append'); - }, - - content: function(content) { - this.opcode('appendContent', content.string); - }, - - mustache: function(mustache) { - var params = this.setupStackForMustache(mustache); - - this.opcode('invokeMustache', params.length, mustache.id.original, !!mustache.hash); - - if(mustache.escaped && !this.options.noEscape) { - this.opcode('appendEscaped'); - } else { - this.opcode('append'); - } - }, - - ID: function(id) { - this.addDepth(id.depth); - - this.opcode('getContext', id.depth); - - this.opcode('lookupWithHelpers', id.parts[0] || null, id.isScoped || false); - - for(var i=1, l=id.parts.length; i<l; i++) { - this.opcode('lookup', id.parts[i]); - } - }, - - STRING: function(string) { - this.opcode('pushString', string.string); - }, - - INTEGER: function(integer) { - this.opcode('push', integer.integer); - }, - - BOOLEAN: function(bool) { - this.opcode('push', bool.bool); - }, - - comment: function() {}, - - // HELPERS - pushParams: function(params) { - var i = params.length, param; - - while(i--) { - param = params[i]; - - if(this.options.stringParams) { - if(param.depth) { - this.addDepth(param.depth); - } - - this.opcode('getContext', param.depth || 0); - this.opcode('pushStringParam', param.string); - } else { - this[param.type](param); - } - } - }, - - opcode: function(name, val1, val2, val3) { - this.opcodes.push(Compiler.OPCODE_MAP[name]); - if(val1 !== undefined) { this.opcodes.push(val1); } - if(val2 !== undefined) { this.opcodes.push(val2); } - if(val3 !== undefined) { this.opcodes.push(val3); } - }, - - declare: function(name, value) { - this.opcodes.push('DECLARE'); - this.opcodes.push(name); - this.opcodes.push(value); - }, - - addDepth: function(depth) { - if(depth === 0) { return; } - - if(!this.depths[depth]) { - this.depths[depth] = true; - this.depths.list.push(depth); - } - }, - - setupStackForMustache: function(mustache) { - var params = mustache.params; - - this.pushParams(params); - - if(mustache.hash) { - this.hash(mustache.hash); - } - - this.ID(mustache.id); - - return params; - } - }; - - JavaScriptCompiler.prototype = { - // PUBLIC API: You can override these methods in a subclass to provide - // alternative compiled forms for name lookup and buffering semantics - nameLookup: function(parent, name, type) { - if (/^[0-9]+$/.test(name)) { - return parent + "[" + name + "]"; - } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { - return parent + "." + name; - } - else { - return parent + "['" + name + "']"; - } - }, - - appendToBuffer: function(string) { - if (this.environment.isSimple) { - return "return " + string + ";"; - } else { - return "buffer += " + string + ";"; - } - }, - - initializeBuffer: function() { - return this.quotedString(""); - }, - - namespace: "Handlebars", - // END PUBLIC API - - compile: function(environment, options, context, asObject) { - this.environment = environment; - this.options = options || {}; - - this.name = this.environment.name; - this.isChild = !!context; - this.context = context || { - programs: [], - aliases: { self: 'this' }, - registers: {list: []} - }; - - this.preamble(); - - this.stackSlot = 0; - this.stackVars = []; - - this.compileChildren(environment, options); - - var opcodes = environment.opcodes, opcode; - - this.i = 0; - - for(l=opcodes.length; this.i<l; this.i++) { - opcode = this.nextOpcode(0); - - if(opcode[0] === 'DECLARE') { - this.i = this.i + 2; - this[opcode[1]] = opcode[2]; - } else { - this.i = this.i + opcode[1].length; - this[opcode[0]].apply(this, opcode[1]); - } - } - - return this.createFunctionContext(asObject); - }, - - nextOpcode: function(n) { - var opcodes = this.environment.opcodes, opcode = opcodes[this.i + n], name, val; - var extraParams, codes; - - if(opcode === 'DECLARE') { - name = opcodes[this.i + 1]; - val = opcodes[this.i + 2]; - return ['DECLARE', name, val]; - } else { - name = Compiler.DISASSEMBLE_MAP[opcode]; - - extraParams = Compiler.multiParamSize(opcode); - codes = []; - - for(var j=0; j<extraParams; j++) { - codes.push(opcodes[this.i + j + 1 + n]); - } - - return [name, codes]; - } - }, - - eat: function(opcode) { - this.i = this.i + opcode.length; - }, - - preamble: function() { - var out = []; - - // this register will disambiguate helper lookup from finding a function in - // a context. This is necessary for mustache compatibility, which requires - // that context functions in blocks are evaluated by blockHelperMissing, and - // then proceed as if the resulting value was provided to blockHelperMissing. - this.useRegister('foundHelper'); - - if (!this.isChild) { - var namespace = this.namespace; - var copies = "helpers = helpers || " + namespace + ".helpers;"; - if(this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; } - out.push(copies); - } else { - out.push(''); - } - - if (!this.environment.isSimple) { - out.push(", buffer = " + this.initializeBuffer()); - } else { - out.push(""); - } - - // track the last context pushed into place to allow skipping the - // getContext opcode when it would be a noop - this.lastContext = 0; - this.source = out; - }, - - createFunctionContext: function(asObject) { - var locals = this.stackVars; - if (!this.isChild) { - locals = locals.concat(this.context.registers.list); - } - - if(locals.length > 0) { - this.source[1] = this.source[1] + ", " + locals.join(", "); - } - - // Generate minimizer alias mappings - if (!this.isChild) { - var aliases = [] - for (var alias in this.context.aliases) { - this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; - } - } - - if (this.source[1]) { - this.source[1] = "var " + this.source[1].substring(2) + ";"; - } - - // Merge children - if (!this.isChild) { - this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; - } - - if (!this.environment.isSimple) { - this.source.push("return buffer;"); - } - - var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; - - for(var i=0, l=this.environment.depths.list.length; i<l; i++) { - params.push("depth" + this.environment.depths.list[i]); - } - - if (asObject) { - params.push(this.source.join("\n ")); - - return Function.apply(this, params); - } else { - var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + this.source.join("\n ") + '}'; - Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n"); - return functionSource; - } - }, - - appendContent: function(content) { - this.source.push(this.appendToBuffer(this.quotedString(content))); - }, - - append: function() { - var local = this.popStack(); - this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }"); - if (this.environment.isSimple) { - this.source.push("else { " + this.appendToBuffer("''") + " }"); - } - }, - - appendEscaped: function() { - var opcode = this.nextOpcode(1), extra = ""; - this.context.aliases.escapeExpression = 'this.escapeExpression'; - - if(opcode[0] === 'appendContent') { - extra = " + " + this.quotedString(opcode[1][0]); - this.eat(opcode); - } - - this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra)); - }, - - getContext: function(depth) { - if(this.lastContext !== depth) { - this.lastContext = depth; - } - }, - - lookupWithHelpers: function(name, isScoped) { - if(name) { - var topStack = this.nextStack(); - - this.usingKnownHelper = false; - - var toPush; - if (!isScoped && this.options.knownHelpers[name]) { - toPush = topStack + " = " + this.nameLookup('helpers', name, 'helper'); - this.usingKnownHelper = true; - } else if (isScoped || this.options.knownHelpersOnly) { - toPush = topStack + " = " + this.nameLookup('depth' + this.lastContext, name, 'context'); - } else { - this.register('foundHelper', this.nameLookup('helpers', name, 'helper')); - toPush = topStack + " = foundHelper || " + this.nameLookup('depth' + this.lastContext, name, 'context'); - } - - toPush += ';'; - this.source.push(toPush); - } else { - this.pushStack('depth' + this.lastContext); - } - }, - - lookup: function(name) { - var topStack = this.topStack(); - this.source.push(topStack + " = (" + topStack + " === null || " + topStack + " === undefined || " + topStack + " === false ? " + - topStack + " : " + this.nameLookup(topStack, name, 'context') + ");"); - }, - - pushStringParam: function(string) { - this.pushStack('depth' + this.lastContext); - this.pushString(string); - }, - - pushString: function(string) { - this.pushStack(this.quotedString(string)); - }, - - push: function(name) { - this.pushStack(name); - }, - - invokeMustache: function(paramSize, original, hasHash) { - this.populateParams(paramSize, this.quotedString(original), "{}", null, hasHash, function(nextStack, helperMissingString, id) { - if (!this.usingKnownHelper) { - this.context.aliases.helperMissing = 'helpers.helperMissing'; - this.context.aliases.undef = 'void 0'; - this.source.push("else if(" + id + "=== undef) { " + nextStack + " = helperMissing.call(" + helperMissingString + "); }"); - if (nextStack !== id) { - this.source.push("else { " + nextStack + " = " + id + "; }"); - } - } - }); - }, - - invokeProgram: function(guid, paramSize, hasHash) { - var inverse = this.programExpression(this.inverse); - var mainProgram = this.programExpression(guid); - - this.populateParams(paramSize, null, mainProgram, inverse, hasHash, function(nextStack, helperMissingString, id) { - if (!this.usingKnownHelper) { - this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; - this.source.push("else { " + nextStack + " = blockHelperMissing.call(" + helperMissingString + "); }"); - } - }); - }, - - populateParams: function(paramSize, helperId, program, inverse, hasHash, fn) { - var needsRegister = hasHash || this.options.stringParams || inverse || this.options.data; - var id = this.popStack(), nextStack; - var params = [], param, stringParam, stringOptions; - - if (needsRegister) { - this.register('tmp1', program); - stringOptions = 'tmp1'; - } else { - stringOptions = '{ hash: {} }'; - } - - if (needsRegister) { - var hash = (hasHash ? this.popStack() : '{}'); - this.source.push('tmp1.hash = ' + hash + ';'); - } - - if(this.options.stringParams) { - this.source.push('tmp1.contexts = [];'); - } - - for(var i=0; i<paramSize; i++) { - param = this.popStack(); - params.push(param); - - if(this.options.stringParams) { - this.source.push('tmp1.contexts.push(' + this.popStack() + ');'); - } - } - - if(inverse) { - this.source.push('tmp1.fn = tmp1;'); - this.source.push('tmp1.inverse = ' + inverse + ';'); - } - - if(this.options.data) { - this.source.push('tmp1.data = data;'); - } - - params.push(stringOptions); - - this.populateCall(params, id, helperId || id, fn, program !== '{}'); - }, - - populateCall: function(params, id, helperId, fn, program) { - var paramString = ["depth0"].concat(params).join(", "); - var helperMissingString = ["depth0"].concat(helperId).concat(params).join(", "); - - var nextStack = this.nextStack(); - - if (this.usingKnownHelper) { - this.source.push(nextStack + " = " + id + ".call(" + paramString + ");"); - } else { - this.context.aliases.functionType = '"function"'; - var condition = program ? "foundHelper && " : "" - this.source.push("if(" + condition + "typeof " + id + " === functionType) { " + nextStack + " = " + id + ".call(" + paramString + "); }"); - } - fn.call(this, nextStack, helperMissingString, id); - this.usingKnownHelper = false; - }, - - invokePartial: function(context) { - params = [this.nameLookup('partials', context, 'partial'), "'" + context + "'", this.popStack(), "helpers", "partials"]; - - if (this.options.data) { - params.push("data"); - } - - this.pushStack("self.invokePartial(" + params.join(", ") + ");"); - }, - - assignToHash: function(key) { - var value = this.popStack(); - var hash = this.topStack(); - - this.source.push(hash + "['" + key + "'] = " + value + ";"); - }, - - // HELPERS - - compiler: JavaScriptCompiler, - - compileChildren: function(environment, options) { - var children = environment.children, child, compiler; - - for(var i=0, l=children.length; i<l; i++) { - child = children[i]; - compiler = new this.compiler(); - - this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children - var index = this.context.programs.length; - child.index = index; - child.name = 'program' + index; - this.context.programs[index] = compiler.compile(child, options, this.context); - } - }, - - programExpression: function(guid) { - if(guid == null) { return "self.noop"; } - - var child = this.environment.children[guid], - depths = child.depths.list; - var programParams = [child.index, child.name, "data"]; - - for(var i=0, l = depths.length; i<l; i++) { - depth = depths[i]; - - if(depth === 1) { programParams.push("depth0"); } - else { programParams.push("depth" + (depth - 1)); } - } - - if(depths.length === 0) { - return "self.program(" + programParams.join(", ") + ")"; - } else { - programParams.shift(); - return "self.programWithDepth(" + programParams.join(", ") + ")"; - } - }, - - register: function(name, val) { - this.useRegister(name); - this.source.push(name + " = " + val + ";"); - }, - - useRegister: function(name) { - if(!this.context.registers[name]) { - this.context.registers[name] = true; - this.context.registers.list.push(name); - } - }, - - pushStack: function(item) { - this.source.push(this.nextStack() + " = " + item + ";"); - return "stack" + this.stackSlot; - }, - - nextStack: function() { - this.stackSlot++; - if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } - return "stack" + this.stackSlot; - }, - - popStack: function() { - return "stack" + this.stackSlot--; - }, - - topStack: function() { - return "stack" + this.stackSlot; - }, - - quotedString: function(str) { - return '"' + str - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') + '"'; - } - }; - - var reservedWords = ( - "break else new var" + - " case finally return void" + - " catch for switch while" + - " continue function this with" + - " default if throw" + - " delete in try" + - " do instanceof typeof" + - " abstract enum int short" + - " boolean export interface static" + - " byte extends long super" + - " char final native synchronized" + - " class float package throws" + - " const goto private transient" + - " debugger implements protected volatile" + - " double import public let yield" - ).split(" "); - - var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; - - for(var i=0, l=reservedWords.length; i<l; i++) { - compilerWords[reservedWords[i]] = true; - } - - JavaScriptCompiler.isValidJavaScriptVariableName = function(name) { - if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) { - return true; - } - return false; - } - -})(Handlebars.Compiler, Handlebars.JavaScriptCompiler); - -Handlebars.precompile = function(string, options) { - options = options || {}; - - var ast = Handlebars.parse(string); - var environment = new Handlebars.Compiler().compile(ast, options); - return new Handlebars.JavaScriptCompiler().compile(environment, options); -}; - -Handlebars.compile = function(string, options) { - options = options || {}; - - var compiled; - function compile() { - var ast = Handlebars.parse(string); - var environment = new Handlebars.Compiler().compile(ast, options); - var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true); - return Handlebars.template(templateSpec); - } - - // Template is only compiled on first use and cached after that point. - return function(context, options) { - if (!compiled) { - compiled = compile(); - } - return compiled.call(this, context, options); - }; -}; -; -// lib/handlebars/runtime.js -Handlebars.VM = { - template: function(templateSpec) { - // Just add water - var container = { - escapeExpression: Handlebars.Utils.escapeExpression, - invokePartial: Handlebars.VM.invokePartial, - programs: [], - program: function(i, fn, data) { - var programWrapper = this.programs[i]; - if(data) { - return Handlebars.VM.program(fn, data); - } else if(programWrapper) { - return programWrapper; - } else { - programWrapper = this.programs[i] = Handlebars.VM.program(fn); - return programWrapper; - } - }, - programWithDepth: Handlebars.VM.programWithDepth, - noop: Handlebars.VM.noop - }; - - return function(context, options) { - options = options || {}; - return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); - }; - }, - - programWithDepth: function(fn, data, $depth) { - var args = Array.prototype.slice.call(arguments, 2); - - return function(context, options) { - options = options || {}; - - return fn.apply(this, [context, options.data || data].concat(args)); - }; - }, - program: function(fn, data) { - return function(context, options) { - options = options || {}; - - return fn(context, options.data || data); - }; - }, - noop: function() { return ""; }, - invokePartial: function(partial, name, context, helpers, partials, data) { - options = { helpers: helpers, partials: partials, data: data }; - - if(partial === undefined) { - throw new Handlebars.Exception("The partial " + name + " could not be found"); - } else if(partial instanceof Function) { - return partial(context, options); - } else if (!Handlebars.compile) { - throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); - } else { - partials[name] = Handlebars.compile(partial); - return partials[name](context, options); - } - } -}; - -Handlebars.template = Handlebars.VM.template; -;
diff --git a/chrome/common/extensions/docs/examples/howto/sandbox/icon.png b/chrome/common/extensions/docs/examples/howto/sandbox/icon.png deleted file mode 100644 index 3620d4f..0000000 --- a/chrome/common/extensions/docs/examples/howto/sandbox/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/howto/sandbox/manifest.json b/chrome/common/extensions/docs/examples/howto/sandbox/manifest.json deleted file mode 100644 index 0fd7c52..0000000 --- a/chrome/common/extensions/docs/examples/howto/sandbox/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "name": "Sandboxed Frame", - "description": "Demonstrate use of handlebars inside a sandboxed frame", - "version": "1.0", - "manifest_version": 2, - "permissions": ["notifications"], - "background": { - "page": "eventpage.html", - "persistent": false - }, - "browser_action": { - "default_icon" : "icon.png", - "default_title": "Start Event Page" - }, - "sandbox": { - "pages": ["sandbox.html"] - }, - "web_accessible_resources": ["icon.png"] -}
diff --git a/chrome/common/extensions/docs/examples/howto/sandbox/sandbox.html b/chrome/common/extensions/docs/examples/howto/sandbox/sandbox.html deleted file mode 100644 index d66fa223..0000000 --- a/chrome/common/extensions/docs/examples/howto/sandbox/sandbox.html +++ /dev/null
@@ -1,44 +0,0 @@ -<!-- - - Copyright (c) 2012 The Chromium Authors. All rights reserved. - - Use of this source code is governed by a BSD-style license that can be - - found in the LICENSE file. - --> -<!doctype html> -<html> - <head> - <script src="handlebars-1.0.0.beta.6.js"></script> - </head> - <body> - <script id="hello-world-template" type="text/x-handlebars-template"> - <div class="entry"> - <h1>Hello, {{thing}}!</h1> - </div> - </script> - <script> - var templates = []; - var source = document.getElementById('hello-world-template').innerHTML; - templates['hello'] = Handlebars.compile(source); - - // Set up message event handler: - window.addEventListener('message', function(event) { - var command = event.data.command; - var name = event.data.name || 'hello'; - switch(command) { - case 'render': - event.source.postMessage({ - name: name, - html: templates[name](event.data.context) - }, event.origin); - break; - - // You could imagine additional functionality. For instance: - // - // case 'new': - // templates[event.data.name] = Handlebars.compile(event.data.source); - // event.source.postMessage({name: name, success: true}, event.origin); - // break; - } - }); - </script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/howto/tab_shortcuts/manifest.json b/chrome/common/extensions/docs/examples/howto/tab_shortcuts/manifest.json deleted file mode 100644 index 198ac7a..0000000 --- a/chrome/common/extensions/docs/examples/howto/tab_shortcuts/manifest.json +++ /dev/null
@@ -1,26 +0,0 @@ -{ - "name": "Tab Shortcuts", - "version": "1.0", - "description": "Allows pinning and duplication of tabs via keyboard shortcuts.", - "manifest_version": 2, - "background": { - "scripts": ["tab_shortcuts.js"], - "persistent": false - }, - "commands": { - "toggle-pin-tab": { - "suggested_key": { - "default": "Ctrl+Shift+X", - "mac": "Command+Shift+X" - }, - "description": "Toggles whether the current tab is pinned." - }, - "duplicate-tab": { - "suggested_key": { - "default": "Ctrl+Shift+Z", - "mac": "Command+Shift+Z" - }, - "description": "Duplicates the current tab." - } - } -}
diff --git a/chrome/common/extensions/docs/examples/howto/tab_shortcuts/tab_shortcuts.js b/chrome/common/extensions/docs/examples/howto/tab_shortcuts/tab_shortcuts.js deleted file mode 100644 index 4ff711f..0000000 --- a/chrome/common/extensions/docs/examples/howto/tab_shortcuts/tab_shortcuts.js +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright (c) 2013 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. - -/** - * Register a callback function with the commands api, which will be called when - * one of our registered commands is detected. - */ -chrome.commands.onCommand.addListener(function(command) { - // Call 'update' with an empty properties object to get access to the current - // tab (given to us in the callback function). - chrome.tabs.update({}, function(tab) { - if (command == 'toggle-pin-tab') - chrome.tabs.update({pinned: !tab.pinned}); - else if (command == 'duplicate-tab') - chrome.tabs.duplicate(tab.id); - }); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-128.png b/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-128.png deleted file mode 100644 index 9013abf..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-19.png b/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-19.png deleted file mode 100644 index af80e35e..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-19.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-48.png b/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-48.png deleted file mode 100644 index 4548ea3..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/analytics/analytics-extension-icon-48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/analytics/manifest.json b/chrome/common/extensions/docs/examples/tutorials/analytics/manifest.json deleted file mode 100644 index 11f90a0..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/analytics/manifest.json +++ /dev/null
@@ -1,17 +0,0 @@ -{ - "name": "Event Tracking with Google Analytics", - "version": "2.0.0", - "description": "A sample extension which uses Google Analytics to track usage.", - "browser_action": { - "default_title": "Open the popup", - "default_icon": "analytics-extension-icon-19.png", - "default_popup" : "popup.html" - }, - "icons": { - "48": "analytics-extension-icon-48.png", - "128": "analytics-extension-icon-128.png" - }, - - "manifest_version": 2, - "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'" -}
diff --git a/chrome/common/extensions/docs/examples/tutorials/analytics/popup.html b/chrome/common/extensions/docs/examples/tutorials/analytics/popup.html deleted file mode 100644 index 9a76c267..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/analytics/popup.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!DOCTYPE html> -<!-- - * Copyright (c) 2012 The Chromium Authors. All rights reserved. Use of this - * source code is governed by a BSD-style license that can be found in the - * LICENSE file. ---> -<html> - <head> - <style> - body { - width: 300px; - color: #000; - font-family: Arial; - } - #output { - color: #d00; - text-align: center; - } - </style> - <script src="popup.js"></script> - </head> - <body> - <h1>Popup</h1> - <p>Track the following actions:</p> - <button id='button1'>Button 1</button> - <button id='button2'>Button 2</button> - <button id='button3'>Button 3</button> - <button id='button4'>Button 4</button> - <button id='button5'>Button 5</button> - <button id='button6'>Button 6</button> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/analytics/popup.js b/chrome/common/extensions/docs/examples/tutorials/analytics/popup.js deleted file mode 100644 index 160fe15..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/analytics/popup.js +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/** - * Add your Analytics tracking ID here. - */ -var _AnalyticsCode = 'UA-XXXXXX-X'; - -/** - * Below is a modified version of the Google Analytics asynchronous tracking - * code snippet. It has been modified to pull the HTTPS version of ga.js - * instead of the default HTTP version. It is recommended that you use this - * snippet instead of the standard tracking snippet provided when setting up - * a Google Analytics account. - */ -var _gaq = _gaq || []; -_gaq.push(['_setAccount', _AnalyticsCode]); -_gaq.push(['_trackPageview']); - -(function() { - var ga = document.createElement('script'); - ga.type = 'text/javascript'; - ga.async = true; - ga.src = 'https://ssl.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(ga, s); -})(); - -/** - * Track a click on a button using the asynchronous tracking API. - * - * See http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html - * for information on how to use the asynchronous tracking API. - */ -function trackButtonClick(e) { - _gaq.push(['_trackEvent', e.target.id, 'clicked']); -} - -/** - * Now set up your event handlers for the popup's `button` elements once the - * popup's DOM has loaded. - */ -document.addEventListener('DOMContentLoaded', function () { - var buttons = document.querySelectorAll('button'); - for (var i = 0; i < buttons.length; i++) { - buttons[i].addEventListener('click', trackButtonClick); - } -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color.zip b/chrome/common/extensions/docs/examples/tutorials/broken_background_color.zip deleted file mode 100644 index 3b9b80f0..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color.zip +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/background.js b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/background.js deleted file mode 100644 index 9465c72..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/background.js +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -// There's a typo in the line below; oninstalled should be onInstalled. -chrome.runtime.oninstalled.addListener(function() { - chrome.storage.sync.set({color: '#3aa757'}, function() { - console.log('The color is green.'); - }); - chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { - chrome.declarativeContent.onPageChanged.addRules([{ - conditions: [new chrome.declarativeContent.PageStateMatcher({ - pageUrl: {hostEquals: 'developer.chrome.com'}, - })], - actions: [new chrome.declarativeContent.ShowPageAction()] - }]); - }); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started128.png b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started128.png deleted file mode 100644 index 4c1cf87..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started16.png b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started16.png deleted file mode 100644 index fb8531c..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started32.png b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started32.png deleted file mode 100644 index 7715223..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started48.png b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started48.png deleted file mode 100644 index 94ddde9b..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/images/get_started48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/manifest.json b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/manifest.json deleted file mode 100644 index 8e84613..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/manifest.json +++ /dev/null
@@ -1,27 +0,0 @@ -{ - "name": "Broken Background Color", - "version": "1.0", - "description": "Fix an Extension!", - "permissions": ["activeTab", "declarativeContent", "storage"], - "options_page": "options.html", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "page_action": { - "default_popup": "popup.html", - "default_icon": { - "16": "images/get_started16.png", - "32": "images/get_started32.png", - "48": "images/get_started48.png", - "128": "images/get_started128.png" - } - }, - "icons": { - "16": "images/get_started16.png", - "32": "images/get_started32.png", - "48": "images/get_started48.png", - "128": "images/get_started128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/options.html b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/options.html deleted file mode 100644 index b46772d..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/options.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style> - button { - height: 30px; - width: 30px; - outline: none; - margin: 10px; - } - </style> - </head> - <body> - <div id="buttonDiv"> - </div> - <div> - <p>Choose a different background color!</p> - </div> - </body> - <script src="options.js"></script> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/options.js b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/options.js deleted file mode 100644 index 94f8e545b..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/options.js +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -let page = document.getElementById('buttonDiv'); -const kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1']; -function constructOptions(kButtonColors) { - for (let item of kButtonColors) { - let button = document.createElement('button'); - button.style.backgroundColor = item; - button.addEventListener('click', function() { - chrome.storage.sync.set({color: item}, function() { - console.log('color is ' + item); - }) - }); - page.appendChild(button); - } -} -constructOptions(kButtonColors);
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/popup.html b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/popup.html deleted file mode 100644 index 77247ec2..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/popup.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style> - button { - height: 30px; - width: 30px; - outline: none; - background-color: #3aa757; - } - </style> - </head> - <body> - <button id="changeColor"></button> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/popup.js b/chrome/common/extensions/docs/examples/tutorials/broken_background_color/popup.js deleted file mode 100644 index baec3802..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/broken_background_color/popup.js +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -let changeColor = document.getElementById('changeColor'); - -chrome.storage.sync.get('color', function(data) { - changeColor.style.backgroundColor = data.color; - changeColor.setAttribute('value', data.color); -}); - -changeColor.onclick = function(element) { - let color = element.target.value; - // The extension must query the active tab - // before it can injected a content script - chrome.tabs.executeScript( - tabs[0].id, - // Scripts injected with tabs.executeScript() will not have access to - // variables from this context, leaving |color| undefined. - {code: 'document.body.style.backgroundColor = color;'}); -};
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/background.js b/chrome/common/extensions/docs/examples/tutorials/get_started/background.js deleted file mode 100644 index 0dc66a6..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/background.js +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -chrome.runtime.onInstalled.addListener(function() { - chrome.storage.sync.set({color: '#3aa757'}, function() { - console.log("The color is green."); - }); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/images.zip b/chrome/common/extensions/docs/examples/tutorials/get_started/images.zip deleted file mode 100644 index 3a18b55..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/images.zip +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started128.png b/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started128.png deleted file mode 100644 index 4c1cf87..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started16.png b/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started16.png deleted file mode 100644 index fb8531c..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started32.png b/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started32.png deleted file mode 100644 index 7715223..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started48.png b/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started48.png deleted file mode 100644 index 94ddde9b..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/images/get_started48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/manifest.json b/chrome/common/extensions/docs/examples/tutorials/get_started/manifest.json deleted file mode 100644 index b9ff56c22..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/manifest.json +++ /dev/null
@@ -1,6 +0,0 @@ -{ - "name": "Getting Started Example", - "version": "1.0", - "description": "Build an Extension!", - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/options.html b/chrome/common/extensions/docs/examples/tutorials/get_started/options.html deleted file mode 100644 index 1b28273..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/options.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style> - button { - height: 30px; - width: 30px; - outline: none; - margin: 10px; - } - </style> - </head> - <body> - <div id="buttonDiv"> - </div> - </body> - <script src="options.js"></script> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/options.js b/chrome/common/extensions/docs/examples/tutorials/get_started/options.js deleted file mode 100644 index 94f8e545b..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/options.js +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -let page = document.getElementById('buttonDiv'); -const kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1']; -function constructOptions(kButtonColors) { - for (let item of kButtonColors) { - let button = document.createElement('button'); - button.style.backgroundColor = item; - button.addEventListener('click', function() { - chrome.storage.sync.set({color: item}, function() { - console.log('color is ' + item); - }) - }); - page.appendChild(button); - } -} -constructOptions(kButtonColors);
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/popup.html b/chrome/common/extensions/docs/examples/tutorials/get_started/popup.html deleted file mode 100644 index f857131..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/popup.html +++ /dev/null
@@ -1,16 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style> - button { - height: 30px; - width: 30px; - outline: none; - } - </style> - </head> - <body> - <button id="changeColor"></button> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started/popup.js b/chrome/common/extensions/docs/examples/tutorials/get_started/popup.js deleted file mode 100644 index abe2aad1..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started/popup.js +++ /dev/null
@@ -1,11 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -let changeColor = document.getElementById('changeColor'); -chrome.storage.sync.get('color', function(data) { - changeColor.style.backgroundColor = data.color; - changeColor.setAttribute('value', data.color); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete.zip b/chrome/common/extensions/docs/examples/tutorials/get_started_complete.zip deleted file mode 100644 index f075650..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete.zip +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/background.js b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/background.js deleted file mode 100644 index ddc4cfd8..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/background.js +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -chrome.runtime.onInstalled.addListener(function() { - chrome.storage.sync.set({color: '#3aa757'}, function() { - console.log('The color is green.'); - }); - chrome.declarativeContent.onPageChanged.removeRules(undefined, function() { - chrome.declarativeContent.onPageChanged.addRules([{ - conditions: [new chrome.declarativeContent.PageStateMatcher({ - pageUrl: {hostEquals: 'developer.chrome.com'}, - })], - actions: [new chrome.declarativeContent.ShowPageAction()] - }]); - }); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started128.png b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started128.png deleted file mode 100644 index 4c1cf87..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started128.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started16.png b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started16.png deleted file mode 100644 index fb8531c..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started16.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started32.png b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started32.png deleted file mode 100644 index 7715223..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started32.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started48.png b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started48.png deleted file mode 100644 index 94ddde9b..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/images/get_started48.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/manifest.json b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/manifest.json deleted file mode 100644 index 71290e77..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/manifest.json +++ /dev/null
@@ -1,27 +0,0 @@ -{ - "name": "Getting Started Example", - "version": "1.0", - "description": "Build an Extension!", - "permissions": ["activeTab", "declarativeContent", "storage"], - "options_page": "options.html", - "background": { - "scripts": ["background.js"], - "persistent": false - }, - "page_action": { - "default_popup": "popup.html", - "default_icon": { - "16": "images/get_started16.png", - "32": "images/get_started32.png", - "48": "images/get_started48.png", - "128": "images/get_started128.png" - } - }, - "icons": { - "16": "images/get_started16.png", - "32": "images/get_started32.png", - "48": "images/get_started48.png", - "128": "images/get_started128.png" - }, - "manifest_version": 2 -}
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/options.html b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/options.html deleted file mode 100644 index b46772d..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/options.html +++ /dev/null
@@ -1,21 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style> - button { - height: 30px; - width: 30px; - outline: none; - margin: 10px; - } - </style> - </head> - <body> - <div id="buttonDiv"> - </div> - <div> - <p>Choose a different background color!</p> - </div> - </body> - <script src="options.js"></script> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/options.js b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/options.js deleted file mode 100644 index 94f8e545b..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/options.js +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -let page = document.getElementById('buttonDiv'); -const kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1']; -function constructOptions(kButtonColors) { - for (let item of kButtonColors) { - let button = document.createElement('button'); - button.style.backgroundColor = item; - button.addEventListener('click', function() { - chrome.storage.sync.set({color: item}, function() { - console.log('color is ' + item); - }) - }); - page.appendChild(button); - } -} -constructOptions(kButtonColors);
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/popup.html b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/popup.html deleted file mode 100644 index f857131..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/popup.html +++ /dev/null
@@ -1,16 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <style> - button { - height: 30px; - width: 30px; - outline: none; - } - </style> - </head> - <body> - <button id="changeColor"></button> - <script src="popup.js"></script> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/popup.js b/chrome/common/extensions/docs/examples/tutorials/get_started_complete/popup.js deleted file mode 100644 index ea9b26f..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/get_started_complete/popup.js +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -let changeColor = document.getElementById('changeColor'); - -chrome.storage.sync.get('color', function(data) { - changeColor.style.backgroundColor = data.color; - changeColor.setAttribute('value', data.color); -}); - -changeColor.onclick = function(element) { - let color = element.target.value; - chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { - chrome.tabs.executeScript( - tabs[0].id, - {code: 'document.body.style.backgroundColor = "' + color + '";'}); - }); -};
diff --git a/chrome/common/extensions/docs/examples/tutorials/getstarted/icon.png b/chrome/common/extensions/docs/examples/tutorials/getstarted/icon.png deleted file mode 100644 index d86677db..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/getstarted/icon.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/getstarted/manifest.json b/chrome/common/extensions/docs/examples/tutorials/getstarted/manifest.json deleted file mode 100644 index 28a1fda3..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/getstarted/manifest.json +++ /dev/null
@@ -1,16 +0,0 @@ -{ - "manifest_version": 2, - - "name": "Getting started example", - "description": "This extension allows the user to change the background color of the current page.", - "version": "1.0", - - "browser_action": { - "default_icon": "icon.png", - "default_popup": "popup.html" - }, - "permissions": [ - "activeTab", - "storage" - ] -}
diff --git a/chrome/common/extensions/docs/examples/tutorials/getstarted/popup.html b/chrome/common/extensions/docs/examples/tutorials/getstarted/popup.html deleted file mode 100644 index 1a96b226..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/getstarted/popup.html +++ /dev/null
@@ -1,49 +0,0 @@ -<!doctype html> -<!-- - This page is shown when the extension button is clicked, because the - "browser_action" field in manifest.json contains the "default_popup" key with - value "popup.html". - --> -<html> - <head> - <title>Getting Started Extension's Popup</title> - <style type="text/css"> - body { - margin: 10px; - white-space: nowrap; - } - - h1 { - font-size: 15px; - } - - #container { - align-items: center; - display: flex; - justify-content: space-between; - } - </style> - - <!-- - - JavaScript and HTML must be in separate files: see our Content Security - - Policy documentation[1] for details and explanation. - - - - [1]: https://developer.chrome.com/extensions/contentSecurityPolicy - --> - <script src="popup.js"></script> - </head> - - <body> - <h1>Background Color Changer</h1> - <div id="container"> - <span>Choose a color</span> - <select id="dropdown"> - <option selected disabled hidden value=''></option> - <option value="white">White</option> - <option value="pink">Pink</option> - <option value="green">Green</option> - <option value="yellow">Yellow</option> - </select> - </div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/getstarted/popup.js b/chrome/common/extensions/docs/examples/tutorials/getstarted/popup.js deleted file mode 100644 index 30ea3f55..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/getstarted/popup.js +++ /dev/null
@@ -1,126 +0,0 @@ -// Copyright (c) 2014 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. - -/** - * Get the current URL. - * - * @param {function(string)} callback called when the URL of the current tab - * is found. - */ -function getCurrentTabUrl(callback) { - // Query filter to be passed to chrome.tabs.query - see - // https://developer.chrome.com/extensions/tabs#method-query - var queryInfo = { - active: true, - currentWindow: true - }; - - chrome.tabs.query(queryInfo, (tabs) => { - // chrome.tabs.query invokes the callback with a list of tabs that match the - // query. When the popup is opened, there is certainly a window and at least - // one tab, so we can safely assume that |tabs| is a non-empty array. - // A window can only have one active tab at a time, so the array consists of - // exactly one tab. - var tab = tabs[0]; - - // A tab is a plain object that provides information about the tab. - // See https://developer.chrome.com/extensions/tabs#type-Tab - var url = tab.url; - - // tab.url is only available if the "activeTab" permission is declared. - // If you want to see the URL of other tabs (e.g. after removing active:true - // from |queryInfo|), then the "tabs" permission is required to see their - // "url" properties. - console.assert(typeof url == 'string', 'tab.url should be a string'); - - callback(url); - }); - - // Most methods of the Chrome extension APIs are asynchronous. This means that - // you CANNOT do something like this: - // - // var url; - // chrome.tabs.query(queryInfo, (tabs) => { - // url = tabs[0].url; - // }); - // alert(url); // Shows "undefined", because chrome.tabs.query is async. -} - -/** - * Change the background color of the current page. - * - * @param {string} color The new background color. - */ -function changeBackgroundColor(color) { - var script = 'document.body.style.backgroundColor="' + color + '";'; - // See https://developer.chrome.com/extensions/tabs#method-executeScript. - // chrome.tabs.executeScript allows us to programmatically inject JavaScript - // into a page. Since we omit the optional first argument "tabId", the script - // is inserted into the active tab of the current window, which serves as the - // default. - chrome.tabs.executeScript({ - code: script - }); -} - -/** - * Gets the saved background color for url. - * - * @param {string} url URL whose background color is to be retrieved. - * @param {function(string)} callback called with the saved background color for - * the given url on success, or a falsy value if no color is retrieved. - */ -function getSavedBackgroundColor(url, callback) { - // See https://developer.chrome.com/apps/storage#type-StorageArea. We check - // for chrome.runtime.lastError to ensure correctness even when the API call - // fails. - chrome.storage.sync.get(url, (items) => { - callback(chrome.runtime.lastError ? null : items[url]); - }); -} - -/** - * Sets the given background color for url. - * - * @param {string} url URL for which background color is to be saved. - * @param {string} color The background color to be saved. - */ -function saveBackgroundColor(url, color) { - var items = {}; - items[url] = color; - // See https://developer.chrome.com/apps/storage#type-StorageArea. We omit the - // optional callback since we don't need to perform any action once the - // background color is saved. - chrome.storage.sync.set(items); -} - -// This extension loads the saved background color for the current tab if one -// exists. The user can select a new background color from the dropdown for the -// current page, and it will be saved as part of the extension's isolated -// storage. The chrome.storage API is used for this purpose. This is different -// from the window.localStorage API, which is synchronous and stores data bound -// to a document's origin. Also, using chrome.storage.sync instead of -// chrome.storage.local allows the extension data to be synced across multiple -// user devices. -document.addEventListener('DOMContentLoaded', () => { - getCurrentTabUrl((url) => { - var dropdown = document.getElementById('dropdown'); - - // Load the saved background color for this page and modify the dropdown - // value, if needed. - getSavedBackgroundColor(url, (savedColor) => { - if (savedColor) { - changeBackgroundColor(savedColor); - dropdown.value = savedColor; - } - }); - - // Ensure the background color is changed and saved when the dropdown - // selection changes. - dropdown.addEventListener('change', () => { - changeBackgroundColor(dropdown.value); - saveBackgroundColor(url, dropdown.value); - }); - }); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/hello_extensions/hello.html b/chrome/common/extensions/docs/examples/tutorials/hello_extensions/hello.html deleted file mode 100644 index c717ab4..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/hello_extensions/hello.html +++ /dev/null
@@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title> Hello Extensions </title> - </head> - - <body> - <h1>Hello Extensions</h1> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/hello_extensions/hello_extensions.png b/chrome/common/extensions/docs/examples/tutorials/hello_extensions/hello_extensions.png deleted file mode 100644 index 63ea0d20..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/hello_extensions/hello_extensions.png +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/hello_extensions/manifest.json b/chrome/common/extensions/docs/examples/tutorials/hello_extensions/manifest.json deleted file mode 100644 index d21bdaa..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/hello_extensions/manifest.json +++ /dev/null
@@ -1,19 +0,0 @@ -{ - "name": "Hello Extensions", - "description" : "Base Level Extension", - "version": "1.0", - "browser_action": { - "default_popup": "hello.html", - "default_icon": "hello_extensions.png" - }, - "manifest_version": 2, - "commands": { - "_execute_browser_action": { - "suggested_key": { - "default": "Ctrl+Shift+F", - "mac": "MacCtrl+Shift+F" - }, - "description": "Opens hello.html" - } - } -}
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/background.js b/chrome/common/extensions/docs/examples/tutorials/oauth_starter/background.js deleted file mode 100644 index dd2c417..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/background.js +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -chrome.browserAction.onClicked.addListener(function() { - chrome.tabs.create({url: 'index.html'}); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/index.html b/chrome/common/extensions/docs/examples/tutorials/oauth_starter/index.html deleted file mode 100644 index a254f12..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/index.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!-- Copyright 2018 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. --> - -<html> - <head> - <title>FriendBlock</title> - <style> - button { - padding: 10px; - background-color: #3C79F8; - display: inline-block; - } - </style> - </head> - <body> - <button>FriendBlock Contacts</button> - <div id="friendDiv"></div> - </body> -</html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/manifest.json b/chrome/common/extensions/docs/examples/tutorials/oauth_starter/manifest.json deleted file mode 100644 index 1035894..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/manifest.json +++ /dev/null
@@ -1,15 +0,0 @@ -{ - "name": "OAuth Tutorial FriendBlock", - "version": "1.0", - "description": "Uses OAuth to connect to Google's People API and display contacts photos.", - "manifest_version": 2, - "browser_action": { - "default_title": "FriendBlock, friends face's in a block." - }, - "background": { - "scripts": [ - "background.js" - ], - "persistent": false - } - }
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/oauth.js b/chrome/common/extensions/docs/examples/tutorials/oauth_starter/oauth.js deleted file mode 100644 index 73e23976..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_starter/oauth.js +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -window.onload = function() { - document.querySelector('button').addEventListener('click', function() { - chrome.identity.getAuthToken({interactive: true}, function(token) { - console.log(token); - }); - }); -};
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete.zip b/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete.zip deleted file mode 100644 index 72a3843..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete.zip +++ /dev/null Binary files differ
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/background.js b/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/background.js deleted file mode 100644 index dd2c417..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/background.js +++ /dev/null
@@ -1,9 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -chrome.browserAction.onClicked.addListener(function() { - chrome.tabs.create({url: 'index.html'}); -});
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/index.html b/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/index.html deleted file mode 100644 index bf79418..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/index.html +++ /dev/null
@@ -1,17 +0,0 @@ -<html> - <head> - <title>FriendBlock</title> - <style> - button { - padding: 10px; - background-color: #3C79F8; - display: inline-block; - } - </style> - <script type="text/javascript" src="oauth.js"></script> - </head> - <body> - <button>FriendBlock Contacts</button> - <div id="friendDiv"></div> - </body> - </html>
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/manifest.json b/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/manifest.json deleted file mode 100644 index 5afe50be..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/manifest.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "name": "OAuth Tutorial FriendBlock", - "version": "1.0", - "description": "Uses OAuth to connect to Google's People API and display contacts photos.", - "manifest_version": 2, - "browser_action": { - "default_title": "FriendBlock, friends face's in a block." - }, - "permissions": [ - "identity" - ], - "background": { - "scripts": [ - "background.js" - ], - "persistent": false - }, - "oauth2": { - "client_id": "ClientIDFromGoogleAPIConsole", - "scopes":["https://www.googleapis.com/auth/contacts.readonly"] - }, - "key": "KeyFromDeveloperDashboardHere" -}
diff --git a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/oauth.js b/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/oauth.js deleted file mode 100644 index f59da65..0000000 --- a/chrome/common/extensions/docs/examples/tutorials/oauth_tutorial_complete/oauth.js +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2018 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. - -'use strict'; - -window.onload = function() { - document.querySelector('button').addEventListener('click', function() { - chrome.identity.getAuthToken({interactive: true}, function(token) { - var init = { - method: 'GET', - async: true, - headers: { - Authorization: 'Bearer ' + token, - 'Content-Type': 'application/json' - }, - 'contentType': 'json' - }; - fetch( - 'https://people.googleapis.com/v1/contactGroups/all?maxMembers=20&key=<API_Key_Here>', - init) - .then((response) => response.json()) - .then(function(data) { - let photoDiv = document.querySelector('#friendDiv'); - let returnedContacts = data.memberResourceNames; - for (var i = 0; i < returnedContacts.length; i++) { - fetch( - 'https://people.googleapis.com/v1/' + returnedContacts[i] + - '?personFields=photos&key=<API_Key_Here>', - init) - .then((response) => response.json()) - .then(function(data) { - let profileImg = document.createElement('img'); - profileImg.src = data.photos[0].url; - photoDiv.appendChild(profileImg); - }); - }; - }); - }); - }); -};
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 6a1a6f3..6193195 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2703,9 +2703,6 @@ const char kBrowserProfilePickerAvailabilityOnStartup[] = "profile.picker_availability_on_startup"; -// Whether the profile picker has been shown at least once. -const char kBrowserProfilePickerShown[] = "profile.picker_shown"; - // Whether to show the profile picker on startup or not. const char kBrowserShowProfilePickerOnStartup[] = "profile.show_picker_on_startup";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index dfbb36e91..7944b9a 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -903,7 +903,6 @@ extern const char kBrowserAddPersonEnabled[]; extern const char kForceBrowserSignin[]; extern const char kBrowserProfilePickerAvailabilityOnStartup[]; -extern const char kBrowserProfilePickerShown[]; extern const char kBrowserShowProfilePickerOnStartup[]; extern const char kSigninAllowedOnNextStartup[]; extern const char kSigninInterceptionEnabled[];
diff --git a/chrome/common/qr_code_generator/BUILD.gn b/chrome/common/qr_code_generator/BUILD.gn deleted file mode 100644 index 1d68242..0000000 --- a/chrome/common/qr_code_generator/BUILD.gn +++ /dev/null
@@ -1,27 +0,0 @@ -# Copyright 2020 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. - -declare_args() { - # Enables building a development / debugging binary. - enable_qr_print = false -} - -source_set("qr_code_generator") { - sources = [ - "dino_image.h", - "qr_code_generator.cc", - "qr_code_generator.h", - ] - - deps = [ "//base" ] - - public_deps = [ "//base" ] -} - -if (enable_qr_print) { - executable("qr_print") { - sources = [ "qr_print.cc" ] - deps = [ ":qr_code_generator" ] - } -}
diff --git a/chrome/common/qr_code_generator/dino_image.h b/chrome/common/qr_code_generator/dino_image.h deleted file mode 100644 index c1c1cd9c..0000000 --- a/chrome/common/qr_code_generator/dino_image.h +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2020 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_COMMON_QR_CODE_GENERATOR_DINO_IMAGE_H_ -#define CHROME_COMMON_QR_CODE_GENERATOR_DINO_IMAGE_H_ - -// Contains constants clients use to to render a dino on top of a QR image. -namespace dino_image { - -// Width of the dino pixel data. -static constexpr int kDinoWidth = 20; -// Height of the dino pixel data. -static constexpr int kDinoHeight = 22; -// Height of the dino pixel data, head segment. -static constexpr int kDinoHeadHeight = 8; -// Height of the dino image data, body segment. -static constexpr int kDinoBodyHeight = kDinoHeight - kDinoHeadHeight; -// Width of the dino image data. -static constexpr int kDinoWidthBytes = (kDinoWidth + 7) / 8; - -// Pixel data for the dino's head, facing right. -static const unsigned char kDinoHeadRight[kDinoWidthBytes * kDinoHeadHeight] = { - // clang-format off - 0b00000000, 0b00011111, 0b11100000, - 0b00000000, 0b00111111, 0b11110000, - 0b00000000, 0b00110111, 0b11110000, - 0b00000000, 0b00111111, 0b11110000, - 0b00000000, 0b00111111, 0b11110000, - 0b00000000, 0b00111111, 0b11110000, - 0b00000000, 0b00111110, 0b00000000, - 0b00000000, 0b00111111, 0b11000000, - // clang-format on -}; - -// Pixel data for the dino's head, facing left. -static const unsigned char kDinoHeadLeft[kDinoWidthBytes * kDinoHeadHeight] = { - // clang-format off - 0b00000111, 0b11111000, 0b00000000, - 0b00001111, 0b11111100, 0b00000000, - 0b00001111, 0b11101100, 0b00000000, - 0b00001111, 0b11111100, 0b00000000, - 0b00001111, 0b11111100, 0b00000000, - 0b00001111, 0b11111100, 0b00000000, - 0b00000000, 0b01111100, 0b00000000, - 0b00000011, 0b11111100, 0b00000000, - // clang-format on -}; - -// Pixel data for the dino's body. -static const unsigned char kDinoBody[kDinoWidthBytes * kDinoBodyHeight] = { - // clang-format off - 0b10000000, 0b01111100, 0b00000000, - 0b10000001, 0b11111100, 0b00000000, - 0b11000011, 0b11111111, 0b00000000, - 0b11100111, 0b11111101, 0b00000000, - 0b11111111, 0b11111100, 0b00000000, - 0b11111111, 0b11111100, 0b00000000, - 0b01111111, 0b11111000, 0b00000000, - 0b00111111, 0b11111000, 0b00000000, - 0b00011111, 0b11110000, 0b00000000, - 0b00001111, 0b11100000, 0b00000000, - 0b00000111, 0b01100000, 0b00000000, - 0b00000110, 0b00100000, 0b00000000, - 0b00000100, 0b00100000, 0b00000000, - 0b00000110, 0b00110000, 0b00000000, - // clang-format on -}; - -} // namespace dino_image -#endif // CHROME_COMMON_QR_CODE_GENERATOR_DINO_IMAGE_H_
diff --git a/chrome/common/qr_code_generator/qr_code_generator.cc b/chrome/common/qr_code_generator/qr_code_generator.cc deleted file mode 100644 index d7186fc1..0000000 --- a/chrome/common/qr_code_generator/qr_code_generator.cc +++ /dev/null
@@ -1,981 +0,0 @@ -// Copyright 2020 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/common/qr_code_generator/qr_code_generator.h" - -#include <math.h> -#include <string.h> - -#include <ostream> -#include <vector> - -#include "base/check_op.h" -#include "base/notreached.h" - -// kMaxVersionWith8BitLength is the maximum QR version that uses an 8 (rather -// than 16) bit length in 8-bit byte mode. See table 3. -static constexpr int kMaxVersionWith8BitLength = 9; - -// A structure containing QR version-specific constants and data. -// All versions currently use error correction at level M. -struct QRVersionInfo { - constexpr QRVersionInfo(const int version, - const uint32_t encoded_version, - const int size, - const size_t group1_bytes, - const size_t group1_num_blocks, - const size_t group1_block_data_bytes, - const size_t group2_bytes, - const size_t group2_num_blocks, - const size_t group2_block_data_bytes, - const std::array<int, 3> alignment_locations) - : version(version), - encoded_version(encoded_version), - size(size), - group1_bytes(group1_bytes), - group1_num_blocks(group1_num_blocks), - group1_block_data_bytes(group1_block_data_bytes), - group2_bytes(group2_bytes), - group2_num_blocks(group2_num_blocks), - group2_block_data_bytes(group2_block_data_bytes), - alignment_locations(alignment_locations) { - if (version < 1 || version > 40 || size < 0 || - !CheckBlockGroupParameters(group1_bytes, group1_num_blocks, - group1_block_data_bytes) || - (group2_num_blocks != 0 && - !CheckBlockGroupParameters(group2_bytes, group2_num_blocks, - group2_block_data_bytes)) || - (version < 7 && encoded_version != 0) || - (version >= 7 && - encoded_version >> 12 != static_cast<uint32_t>(version)) || - (version <= kMaxVersionWith8BitLength && input_bytes() >= 256) || - (group2_num_blocks != 0 && - group2_block_ec_bytes() != group1_block_ec_bytes())) { - __builtin_unreachable(); - } - } - - // The version of the QR code. - const int version; - - // An 18-bit value that contains the version, BCH (18,6)-encoded. Only valid - // for versions seven and above. See table D.1 for values. - const uint32_t encoded_version; - - // The number of "tiles" in each dimension for a QR code of |version|. See - // table 1. (The colored squares in in QR codes are called tiles in the - // spec.) - const int size; - - // Values taken from Table 9, page 38, for a QR code of version |version|. - const size_t group1_bytes; - const size_t group1_num_blocks; - const size_t group1_block_data_bytes; - const size_t group2_bytes; - const size_t group2_num_blocks; - const size_t group2_block_data_bytes; - - const std::array<int, 3> alignment_locations; - - // Total number of tiles for the QR code, size*size. - constexpr int total_size() const { return size * size; } - - constexpr size_t total_bytes() const { return group1_bytes + group2_bytes; } - - constexpr size_t group1_block_bytes() const { - return group1_bytes / group1_num_blocks; - } - - constexpr size_t group1_block_ec_bytes() const { - return group1_block_bytes() - group1_block_data_bytes; - } - - constexpr size_t group1_data_bytes() const { - return group1_block_data_bytes * group1_num_blocks; - } - - constexpr size_t group2_block_bytes() const { - if (group2_num_blocks == 0) - return 0; - return group2_bytes / group2_num_blocks; - } - - constexpr size_t group2_block_ec_bytes() const { - return group2_block_bytes() - group2_block_data_bytes; - } - - constexpr size_t group2_data_bytes() const { - return group2_block_data_bytes * group2_num_blocks; - } - - // Two bytes of overhead are needed for QR framing. - // If extending beyond version 26, framing would need to be updated. - constexpr size_t input_bytes() const { - if (version <= 9) { - return group1_data_bytes() + group2_data_bytes() - 2; - } else { - return group1_data_bytes() + group2_data_bytes() - 3; - } - } - - private: - static constexpr bool CheckBlockGroupParameters( - const size_t bytes, - const size_t num_blocks, - const size_t block_data_bytes) { - if (num_blocks == 0 || bytes % num_blocks != 0 || block_data_bytes == 0 || - block_data_bytes * num_blocks > bytes || - (bytes - block_data_bytes * num_blocks) % num_blocks != 0) { - return false; - } - - return true; - } - - DISALLOW_COPY_AND_ASSIGN(QRVersionInfo); -}; - -namespace { - -constexpr QRVersionInfo version_infos[] = { - // See table 9 in the spec for the source of these numbers. - - // 5-M - // 134 bytes, as 2 blocks of 67. - { - 5, // version - 0, // encoded version (not included in this version) - 37, // size (num tiles in each axis) - - // Block group 1: - 134, // Total bytes in group - 2, // Number of blocks - 43, // Data bytes per block - - // Block group 2: - 0, - 0, - 0, - - // Alignment locations - {6, 30, 0}, - }, - - // 7-M - // 196 bytes, as 4 blocks of 49. - { - 7, // version - 0b000111110010010100, // encoded version - 45, // size (num tiles in each axis) - - // Block group 1: - 196, // Total bytes in group - 4, // Number of blocks - 31, // Data bytes per block - - // Block group 2: - 0, - 0, - 0, - - // Alignment locations - {6, 22, 38}, - }, - - // 9-M - // 292 bytes, as 3 blocks of 58 plus 2 blocks of 59. - { - 9, // version - 0b001001101010011001, // encoded version - 53, // size (num tiles in each axis) - - // Block group 1: - 174, // Total bytes in group - 3, // Number of blocks - 36, // Data bytes per block - - // Block group 2: - 118, - 2, - 37, - - // Alignment locations - {6, 26, 46}, - }, - - // 12-M - // 466 bytes, as 6 blocks of 58 and 2 blocks of 59. - { - 12, // version - 0b001100011101100010, // encoded version - 65, // size (num tiles in each axis) - - // Block group 1: - 348, // Total bytes in group - 6, // Number of blocks - 36, // Data bytes per block - - // Block group 2: - 118, - 2, - 37, - - // Alignment locations - {6, 32, 58}, - }, -}; - -const QRVersionInfo* GetVersionForDataSize(size_t num_data_bytes) { - for (const auto& version : version_infos) { - if (version.input_bytes() >= num_data_bytes) { - return &version; - } - } - return nullptr; -} - -// kMaxMask is the maximum masking function number. See table 10. -constexpr uint8_t kMaxMask = 7; - -// The following functions implement the masks specified in table 10. - -uint8_t MaskFunction0(int x, int y) { - return (x + y) % 2 == 0; -} -uint8_t MaskFunction1(int x, int y) { - return y % 2 == 0; -} -uint8_t MaskFunction2(int x, int y) { - return x % 3 == 0; -} -uint8_t MaskFunction3(int x, int y) { - return (x + y) % 3 == 0; -} -uint8_t MaskFunction4(int x, int y) { - return ((y / 2) + (x / 3)) % 2 == 0; -} -uint8_t MaskFunction5(int x, int y) { - return ((x * y) % 2) + ((x * y) % 3) == 0; -} -uint8_t MaskFunction6(int x, int y) { - return (((x * y) % 2) + ((x * y) % 3)) % 2 == 0; -} -uint8_t MaskFunction7(int x, int y) { - return (((x + y) % 2) + ((x * y) % 3)) % 2 == 0; -} - -static uint8_t (*const kMaskFunctions[kMaxMask + 1])(int x, int y) = { - MaskFunction0, MaskFunction1, MaskFunction2, MaskFunction3, - MaskFunction4, MaskFunction5, MaskFunction6, MaskFunction7, -}; - -// kFormatInformation is taken from table C.1 on page 80 and specifies the -// format value for each masking function, assuming ECC level 'M'. -static const uint16_t kFormatInformation[kMaxMask + 1] = { - 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, -}; - -} // namespace - -QRCodeGenerator::QRCodeGenerator() = default; - -QRCodeGenerator::~QRCodeGenerator() = default; - -QRCodeGenerator::GeneratedCode::GeneratedCode() = default; -QRCodeGenerator::GeneratedCode::GeneratedCode( - QRCodeGenerator::GeneratedCode&&) = default; -QRCodeGenerator::GeneratedCode::~GeneratedCode() = default; - -base::Optional<QRCodeGenerator::GeneratedCode> QRCodeGenerator::Generate( - base::span<const uint8_t> in, - base::Optional<uint8_t> mask) { - CHECK(!mask || *mask <= kMaxMask); - - // We're currently using a minimal set of versions to shrink test surface. - // When expanding, take care to validate across different platforms and - // a selection of QR Scanner apps. - const QRVersionInfo* const version_info = GetVersionForDataSize(in.size()); - if (!version_info) { - return base::nullopt; - } - - if (version_info != version_info_) { - version_info_ = version_info; - d_.resize(version_info_->total_size()); - } - // Previous data and "set" bits must be cleared. - memset(&d_[0], 0, version_info_->total_size()); - - PutVerticalTiming(6); - PutHorizontalTiming(6); - PutFinder(3, 3); - PutFinder(3, version_info_->size - 4); - PutFinder(version_info_->size - 4, 3); - - const auto& alignment_locations = version_info_->alignment_locations; - size_t num_alignment_locations = 0; - for (size_t i = 0; i < alignment_locations.size(); i++) { - if (alignment_locations[i] == 0) { - break; - } - num_alignment_locations++; - } - - for (size_t i = 0; i < num_alignment_locations; i++) { - for (size_t j = 0; j < num_alignment_locations; j++) { - // Three of the corners already have finder symbols. - if ((i == 0 && j == 0) || (i == 0 && j == num_alignment_locations - 1) || - (i == num_alignment_locations - 1 && j == 0)) { - continue; - } - - PutAlignment(alignment_locations[i], alignment_locations[j]); - } - } - - if (version_info_->encoded_version != 0) { - PutVersionBlocks(version_info_->encoded_version); - } - - // Add the mode and character count. - - // QR codes require some framing of the data. This requires: - // Version 1-9: 4 bits for mode + 8 bits for char count = 12 bits - // Version 10-40: 4 bits for mode + 16 bits for char count = 20 bits - // Details are in Table 3. - // Since 12 and 20 are not a multiple of eight, a frame-shift of all - // subsequent bytes is required. - const size_t framed_input_size = - version_info_->group1_data_bytes() + version_info_->group2_data_bytes(); - std::vector<uint8_t> prefixed_data(framed_input_size); - size_t framing_offset_bytes = 0; - if (version_info->version <= kMaxVersionWith8BitLength) { - DCHECK_LT(in.size(), 0x100u) << "in.size() too large for 8-bit length"; - const uint8_t len8 = static_cast<uint8_t>(in.size()); - prefixed_data[0] = 0x40 | (len8 >> 4); - prefixed_data[1] = len8 << 4; - if (!in.empty()) { - prefixed_data[1] |= in[0] >> 4; - } - framing_offset_bytes = 2; - } else { - DCHECK_LT(in.size(), 0x10000u) << "in.size() too large for 16-bit length"; - const uint16_t len16 = static_cast<uint16_t>(in.size()); - prefixed_data[0] = 0x40 | (len16 >> 12); - prefixed_data[1] = len16 >> 4; - prefixed_data[2] = len16 << 4; - if (!in.empty()) { - prefixed_data[2] |= in[0] >> 4; - } - framing_offset_bytes = 3; - } - DCHECK_LE(in.size() + framing_offset_bytes, prefixed_data.size()); - - for (size_t i = 0; i < in.size() - 1; i++) { - prefixed_data[i + framing_offset_bytes] = (in[i] << 4) | (in[i + 1] >> 4); - } - if (!in.empty()) { - prefixed_data[in.size() - 1 + framing_offset_bytes] = in[in.size() - 1] - << 4; - } - - // The QR code looks a little odd with fixed padding. Thus replicate the - // message to fill the input. - for (size_t i = in.size() + framing_offset_bytes; i < framed_input_size; - i++) { - prefixed_data[i] = prefixed_data[i % (in.size() + framing_offset_bytes)]; - } - - // Each block of input data is expanded with error correcting - // information and then interleaved. - - // Error Correction for Group 1, present for all versions. - const size_t group1_num_blocks = version_info_->group1_num_blocks; - const size_t group1_block_bytes = version_info_->group1_block_bytes(); - const size_t group1_block_data_bytes = version_info_->group1_block_data_bytes; - const size_t group1_block_ec_bytes = version_info_->group1_block_ec_bytes(); - std::vector<std::vector<uint8_t>> expanded_blocks(group1_num_blocks); - for (size_t i = 0; i < group1_num_blocks; i++) { - expanded_blocks[i].resize(group1_block_bytes); - AddErrorCorrection( - expanded_blocks[i], - base::span<const uint8_t>(&prefixed_data[group1_block_data_bytes * i], - group1_block_data_bytes), - group1_block_bytes, group1_block_ec_bytes); - } - - // Error Correction for Group 2, present for some versions. - // Factor out the number of bytes written by the prior group. - const size_t group_data_offset = version_info_->group1_data_bytes(); - const size_t group2_num_blocks = version_info_->group2_num_blocks; - const size_t group2_block_bytes = version_info_->group2_block_bytes(); - const size_t group2_block_data_bytes = version_info_->group2_block_data_bytes; - const size_t group2_block_ec_bytes = version_info_->group2_block_ec_bytes(); - - std::vector<std::vector<uint8_t>> expanded_blocks_2; - if (group2_num_blocks > 0) { - expanded_blocks_2.resize(group2_num_blocks); - for (size_t i = 0; i < group2_num_blocks; i++) { - expanded_blocks_2[i].resize(group2_block_bytes); - AddErrorCorrection( - expanded_blocks_2[i], - base::span<const uint8_t>( - &prefixed_data[group_data_offset + group2_block_data_bytes * i], - group2_block_data_bytes), - group2_block_bytes, group2_block_ec_bytes); - } - } - - const size_t total_bytes = version_info_->total_bytes(); - uint8_t interleaved_data[total_bytes]; - CHECK(total_bytes == group1_block_bytes * group1_num_blocks + - group2_block_bytes * group2_num_blocks) - << "internal error"; - - size_t k = 0; - // Interleave data from all blocks. All non-ECC data is written before any ECC - // data. The group two blocks, if any, will be longer than the group one - // blocks. Once group one is exhausted then the interleave considers only - // group two. - DCHECK(group2_num_blocks == 0 || version_info_->group2_block_data_bytes > - version_info_->group1_block_data_bytes); - - size_t j = 0; - for (; j < version_info_->group1_block_data_bytes; j++) { - for (size_t i = 0; i < group1_num_blocks; i++) { - interleaved_data[k++] = expanded_blocks[i][j]; - } - for (size_t i = 0; i < group2_num_blocks; i++) { - interleaved_data[k++] = expanded_blocks_2[i][j]; - } - } - if (group2_num_blocks > 0) { - for (; j < version_info_->group2_block_data_bytes; j++) { - for (size_t i = 0; i < group2_num_blocks; i++) { - interleaved_data[k++] = expanded_blocks_2[i][j]; - } - } - } - - // The number of ECC bytes in each group is the same so the interleave - // considers them uniformly. - DCHECK(version_info_->group2_num_blocks == 0 || - version_info_->group2_block_ec_bytes() == - version_info_->group1_block_ec_bytes()); - for (size_t j = 0; j < version_info_->group1_block_ec_bytes(); j++) { - for (size_t i = 0; i < group1_num_blocks; i++) { - interleaved_data[k++] = - expanded_blocks[i][version_info_->group1_block_data_bytes + j]; - } - for (size_t i = 0; i < group2_num_blocks; i++) { - interleaved_data[k++] = - expanded_blocks_2[i][version_info_->group2_block_data_bytes + j]; - } - } - DCHECK_EQ(k, total_bytes); - - uint8_t best_mask = mask.value_or(0); - base::Optional<unsigned> lowest_penalty; - - // If |mask| was not specified, then evaluate each masking function to find - // the one with the lowest penalty score. - for (uint8_t mask_num = 0; !mask && mask_num <= kMaxMask; mask_num++) { - // kFormatInformation is the encoded formatting word for the QR code that - // this code generates. See tables 10 and 12. For example: - // 00 011 - // --|--- - // error correction M | Mask pattern 3 - // - // It's translated into a 15-bit value using the table on page 80, which is - // stored in |kFormatInformation|. - PutFormatBits(kFormatInformation[mask_num]); - - PutBits(interleaved_data, sizeof(interleaved_data), - kMaskFunctions[mask_num]); - - const unsigned penalty = CountPenaltyPoints(); - if (!lowest_penalty || *lowest_penalty > penalty) { - lowest_penalty = penalty; - best_mask = mask_num; - } - } - - // Repaint with the best mask function. - PutFormatBits(kFormatInformation[best_mask]); - PutBits(interleaved_data, sizeof(interleaved_data), - kMaskFunctions[best_mask]); - - GeneratedCode code; - code.data = base::span<uint8_t>(&d_[0], version_info_->total_size()); - code.qr_size = version_info_->size; - return code; -} - -// PutFinder paints a finder symbol at the given coordinates. -void QRCodeGenerator::PutFinder(int x, int y) { - DCHECK_GE(x, 3); - DCHECK_GE(y, 3); - fillAt(x - 3, y - 3, 7, 0b11); - fillAt(x - 2, y - 2, 5, 0b10); - fillAt(x - 2, y + 2, 5, 0b10); - fillAt(x - 3, y + 3, 7, 0b11); - - static constexpr uint8_t kLine[7] = {0b11, 0b10, 0b11, 0b11, - 0b11, 0b10, 0b11}; - copyTo(x - 3, y - 1, kLine, sizeof(kLine)); - copyTo(x - 3, y, kLine, sizeof(kLine)); - copyTo(x - 3, y + 1, kLine, sizeof(kLine)); - - at(x - 3, y - 2) = 0b11; - at(x + 3, y - 2) = 0b11; - at(x - 3, y + 2) = 0b11; - at(x + 3, y + 2) = 0b11; - - for (int xx = x - 4; xx <= x + 4; xx++) { - clipped(xx, y - 4) = 0b10; - clipped(xx, y + 4) = 0b10; - } - for (int yy = y - 3; yy <= y + 3; yy++) { - clipped(x - 4, yy) = 0b10; - clipped(x + 4, yy) = 0b10; - } -} - -// PutAlignment paints an alignment symbol centered at the given coordinates. -void QRCodeGenerator::PutAlignment(int x, int y) { - fillAt(x - 2, y - 2, 5, 0b11); - fillAt(x - 2, y + 2, 5, 0b11); - static constexpr uint8_t kLine[5] = {0b11, 0b10, 0b10, 0b10, 0b11}; - copyTo(x - 2, y - 1, kLine, sizeof(kLine)); - copyTo(x - 2, y, kLine, sizeof(kLine)); - copyTo(x - 2, y + 1, kLine, sizeof(kLine)); - at(x, y) = 0b11; -} - -// PutVerticalTiming paints the vertical timing signal. -void QRCodeGenerator::PutVerticalTiming(int x) { - for (int y = 0; y < version_info_->size; y++) { - at(x, y) = 0b10 | (1 ^ (y & 1)); - } -} - -// PutVerticalTiming paints the horizontal timing signal. -void QRCodeGenerator::PutHorizontalTiming(int y) { - for (int x = 0; x < version_info_->size; x++) { - at(x, y) = 0b10 | (1 ^ (x & 1)); - } -} - -// PutFormatBits paints the 15-bit, pre-encoded format metadata. See page 56 -// for the location of the format bits. -void QRCodeGenerator::PutFormatBits(const uint16_t format) { - // kRun1 is the location of the initial format bits, where the upper nibble - // is the x coordinate and the lower the y. - static constexpr uint8_t kRun1[15] = { - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, - 0x78, 0x58, 0x48, 0x38, 0x28, 0x18, 0x08, - }; - - uint16_t v = format; - for (size_t i = 0; i < sizeof(kRun1); i++) { - const uint8_t location = kRun1[i]; - at(location >> 4, location & 15) = 0b10 | (v & 1); - v >>= 1; - } - - const int size = version_info_->size; - v = format; - for (int x = size - 1; x >= size - 1 - 7; x--) { - at(x, 8) = 0b10 | (v & 1); - v >>= 1; - } - - at(8, size - 1 - 7) = 0b11; - for (int y = size - 1 - 6; y <= size - 1; y++) { - at(8, y) = 0b10 | (v & 1); - v >>= 1; - } -} - -void QRCodeGenerator::PutVersionBlocks(uint32_t encoded_version) { - // Version 7 and larger require 18-bit version information taking the form - // of 6x3 rectangles above the bottom-left locator and to the left of the - // top-right locator. - const int size = version_info_->size; - - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 3; j++) { - // Bottom-left rectangle is top-to-bottom, left-to-right - at(i, size - 8 - 3 + j) = 0b10 | (encoded_version & 1); - // Top-right rectangle is left-to-right, top-to-bottom - at(size - 8 - 3 + j, i) = 0b10 | (encoded_version & 1); - // Shift to consider the next bit. - encoded_version >>= 1; - } - } -} - -// PutBits writes the given data into the QR code in correct order, avoiding -// structural elements that must have already been painted. See section 7.7.3 -// about the placement algorithm. -void QRCodeGenerator::PutBits(const uint8_t* data, - size_t data_len, - uint8_t (*mask_func)(int, int)) { - // BitStream vends bits from |data| on demand, in the order that QR codes - // expect them. - class BitStream { - public: - BitStream(const uint8_t* data, size_t data_len) - : data_(data), data_len_(data_len), i_(0), bits_in_current_byte_(0) {} - - uint8_t Next() { - if (bits_in_current_byte_ == 0) { - if (i_ >= data_len_) { - byte_ = 0; - } else { - byte_ = data_[i_++]; - } - bits_in_current_byte_ = 8; - } - - const uint8_t ret = byte_ >> 7; - byte_ <<= 1; - bits_in_current_byte_--; - return ret; - } - - private: - const uint8_t* const data_; - const size_t data_len_; - size_t i_; - unsigned bits_in_current_byte_; - uint8_t byte_; - }; - - BitStream stream(data, data_len); - - bool going_up = true; - int x = version_info_->size - 1; - int y = version_info_->size - 1; - - for (;;) { - uint8_t& right = at(x, y); - // Test the current value in the QR code to avoid painting over any - // existing structural elements. - if ((right & 2) == 0) { - right = stream.Next() ^ mask_func(x, y); - } - - uint8_t& left = at(x - 1, y); - if ((left & 2) == 0) { - left = stream.Next() ^ mask_func(x - 1, y); - } - - if ((going_up && y == 0) || (!going_up && y == version_info_->size - 1)) { - if (x == 1) { - break; - } - x -= 2; - // The vertical timing column is skipped over. - if (x == 6) { - x--; - } - going_up = !going_up; - } else { - if (going_up) { - y--; - } else { - y++; - } - } - } -} - -// at returns a reference to the given element of |d_|. -uint8_t& QRCodeGenerator::at(int x, int y) { - DCHECK_LE(0, x); - DCHECK_LT(x, version_info_->size); - DCHECK_LE(0, y); - DCHECK_LT(y, version_info_->size); - return d_[version_info_->size * y + x]; -} - -// fillAt sets the |len| elements at (x, y) to |value|. -void QRCodeGenerator::fillAt(int x, int y, size_t len, uint8_t value) { - DCHECK_LE(0, x); - DCHECK_LE(static_cast<int>(x + len), version_info_->size); - DCHECK_LE(0, y); - DCHECK_LT(y, version_info_->size); - memset(&d_[version_info_->size * y + x], value, len); -} - -// copyTo copies |len| elements from |data| to the elements at (x, y). -void QRCodeGenerator::copyTo(int x, int y, const uint8_t* data, size_t len) { - DCHECK_LE(0, x); - DCHECK_LE(static_cast<int>(x + len), version_info_->size); - DCHECK_LE(0, y); - DCHECK_LT(y, version_info_->size); - memcpy(&d_[version_info_->size * y + x], data, len); -} - -// clipped returns a reference to the given element of |d_|, or to -// |clip_dump_| if the coordinates are out of bounds. -uint8_t& QRCodeGenerator::clipped(int x, int y) { - if (0 <= x && x < version_info_->size && 0 <= y && y < version_info_->size) { - return d_[version_info_->size * y + x]; - } - return clip_dump_; -} - -// GF28Mul returns the product of |a| and |b| (which must be field elements, -// i.e. < 256) in the field GF(2^8) mod x^8 + x^4 + x^3 + x^2 + 1. -// static -uint8_t QRCodeGenerator::GF28Mul(uint16_t a, uint16_t b) { - uint16_t acc = 0; - - // Perform 8-bit, carry-less multiplication of |a| and |b|. - for (int i = 0; i < 8; i++) { - const uint16_t mask = ~((b & 1) - 1); - acc ^= a & mask; - b >>= 1; - a <<= 1; - } - - // Add multiples of the modulus to eliminate all bits past a byte. Note that - // the bits in |modulus| have a one where there's a non-zero power of |x| in - // the field modulus. - uint16_t modulus = 0b100011101 << 7; - for (int i = 15; i >= 8; i--) { - const uint16_t mask = ~((acc >> i) - 1); - acc ^= modulus & mask; - modulus >>= 1; - } - - return acc; -} - -// AddErrorCorrection writes the Reed-Solomon expanded version of |in| to -// |out|. -// |out| should have length block_bytes for the code's version. -// |in| should have length block_data_bytes for the code's version. -void QRCodeGenerator::AddErrorCorrection(base::span<uint8_t> out, - base::span<const uint8_t> in, - size_t block_bytes, - size_t block_ec_bytes) { - // kGenerator is the product of (z - x^i) for 0 <= i < |block_ec_bytes|, - // where x is the term of GF(2^8) and z is the term of a polynomial ring - // over GF(2^8). It's generated with the following Sage script: - // - // F.<x> = GF(2^8, modulus = x^8 + x^4 + x^3 + x^2 + 1) - // R.<z> = PolynomialRing(F, 'z') - // - // def toByte(p): - // return sum([(1<<i) * int(term) for (i, term) in - // enumerate(p.polynomial())]) - // - // def generatorPoly(n): - // acc = (z - F(1)) - // for i in range(1,n): - // acc *= (z - x^i) - // return acc - // - // gen = generatorPoly(24) - // coeffs = list(gen) - // gen = [toByte(x) for x in coeffs] - // print 'uint8_t kGenerator[' + str(len(gen)) + '] = {' + str(gen) + '}' - - // Used for 7-M: 18 error correction codewords per block. - static const uint8_t kGenerator18[] = { - 146, 217, 67, 32, 75, 173, 82, 73, 220, 240, - 215, 199, 175, 149, 113, 183, 251, 239, 1, - }; - - // Used for 9-M and 12-M; 22 error correction codewords per block. - static const uint8_t kGenerator22[] = { - 245, 145, 26, 230, 218, 86, 253, 67, 123, 29, 137, 28, - 40, 69, 189, 19, 244, 182, 176, 131, 179, 89, 1, - }; - - // Used for 5-M, 24 error correction codewords per block. - static const uint8_t kGenerator24[] = { - 117, 144, 217, 127, 247, 237, 1, 206, 43, 61, 72, 130, 73, - 229, 150, 115, 102, 216, 237, 178, 70, 169, 118, 122, 1, - }; - - const uint8_t* generator = nullptr; - switch (block_ec_bytes) { - case 18: - generator = kGenerator18; - break; - case 22: - generator = kGenerator22; - break; - case 24: - generator = kGenerator24; - break; - default: { - NOTREACHED() << "Unsupported Generator Polynomial for block_ec_bytes: " - << block_ec_bytes; - return; - } - } - - // The error-correction bytes are the remainder of dividing |in| * x^k by - // |kGenerator|, where |k| is the number of EC codewords. Polynomials here - // are represented in little-endian order, i.e. the value at index |i| is - // the coefficient of z^i. - - // Multiplication of |in| by x^k thus just involves moving it up. - uint8_t remainder[block_bytes]; - DCHECK_LE(block_ec_bytes, block_bytes); - memset(remainder, 0, block_ec_bytes); - size_t block_data_bytes = block_bytes - block_ec_bytes; - // Reed-Solomon input is backwards. See section 7.5.2. - for (size_t i = 0; i < block_data_bytes; i++) { - remainder[block_ec_bytes + i] = in[block_data_bytes - 1 - i]; - } - - // Progressively eliminate the leading coefficient by subtracting some - // multiple of |generator| until we have a value smaller than |generator|. - for (size_t i = block_bytes - 1; i >= block_ec_bytes; i--) { - // The leading coefficient of |generator| is 1, so the multiple to - // subtract to eliminate the leading term of |remainder| is the value of - // that leading term. The polynomial ring is characteristic two, so - // subtraction is the same as addition, which is XOR. - for (size_t j = 0; j < block_ec_bytes; j++) { - remainder[i - block_ec_bytes + j] ^= GF28Mul(generator[j], remainder[i]); - } - } - - memmove(&out[0], &in[0], block_data_bytes); - // Remove the Reed-Solomon remainder again to match QR's convention. - for (size_t i = 0; i < block_ec_bytes; i++) { - out[block_data_bytes + i] = remainder[block_ec_bytes - 1 - i]; - } -} - -unsigned QRCodeGenerator::CountPenaltyPoints() const { - const int size = version_info_->size; - unsigned penalty = 0; - - // The spec penalises the pattern X.XXX.X with four unpainted tiles to - // the left or right. These are "finder-like" patterns. To catch them, a - // sliding window of 11 tiles is used. - static const unsigned k11Bits = 0x7ff; - static const unsigned kFinderLeft = 0b00001011101; - static const unsigned kFinderRight = 0b10111010000; - - // Count: - // * Horizontal runs of the same color, at least five tiles in a row. - // * The number of horizontal finder-like patterns. - // * Total number of painted tiles, which is used later. - unsigned current_run_length; - int current_color; - unsigned total_painted_tiles = 0; - unsigned window = 0; - - size_t i = 0; - for (int y = 0; y < size; y++) { - current_color = d_[i++] & 1; - current_run_length = 0; - window = current_color; - total_painted_tiles += current_color; - - for (int x = 1; x < size; x++) { - const int color = d_[i++] & 1; - - window = k11Bits & ((window << 1) | color); - if (window == kFinderLeft || window == kFinderRight) { - penalty += 40; - } - - total_painted_tiles += color; - - if (color == current_color) { - current_run_length++; - continue; - } - - if (current_run_length >= 5) { - penalty += current_run_length - 2; - } - current_run_length = 0; - current_color = color; - } - - if (current_run_length >= 5) { - penalty += current_run_length - 2; - } - - window = k11Bits & (window << 4); - if (window == kFinderRight) { - penalty += 40; - } - } - DCHECK_EQ(i, static_cast<size_t>(size * size)); - - // Count: - // * Vertical runs of the same color, at least five tiles in a row. - // * The number of vertical finder-like patterns. - for (int x = 0; x < size; x++) { - i = x; - current_run_length = 0; - current_color = d_[i] & 1; - i += size; - window = current_color; - - for (int y = 1; y < size; y++, i += size) { - const int color = d_[i] & 1; - window = k11Bits & ((window << 1) | color); - if (window == kFinderLeft || window == kFinderRight) { - penalty += 40; - } - - if (color == current_color) { - current_run_length++; - continue; - } - - if (current_run_length >= 5) { - penalty += current_run_length - 2; - } - current_run_length = 0; - current_color = color; - } - - if (current_run_length >= 5) { - penalty += current_run_length - 2; - } - - window = k11Bits & (window << 4); - if (window == kFinderRight) { - penalty += 40; - } - } - DCHECK_EQ(i, static_cast<size_t>(size * size + size - 1)); - - // Count 2x2 blocks of the same color. - i = 0; - for (int y = 0; y < size - 1; y++) { - for (int x = 0; x < size - 1; x++) { - const int color = d_[i++] & 1; - if ((d_[i + 1] & 1) == color && (d_[i + size] & 1) == color && - (d_[i + size + 1] & 1) == color) { - penalty += 3; - } - } - } - - // Each deviation of 5% away from 50%-painted costs five points. - DCHECK_LE(total_painted_tiles, static_cast<unsigned>(size) * size); - double painted_fraction = static_cast<double>(total_painted_tiles) / - (static_cast<double>(size) * size); - if (painted_fraction < 0.5) { - painted_fraction = 1.0 - painted_fraction; - } - const double deviation = (painted_fraction - 0.5) / 0.05; - penalty += 5 * static_cast<unsigned>(floor(deviation)); - - return penalty; -}
diff --git a/chrome/common/qr_code_generator/qr_code_generator.h b/chrome/common/qr_code_generator/qr_code_generator.h deleted file mode 100644 index 7f431c0..0000000 --- a/chrome/common/qr_code_generator/qr_code_generator.h +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2020 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_COMMON_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_ -#define CHROME_COMMON_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <vector> - -#include "base/containers/span.h" -#include "base/optional.h" - -struct QRVersionInfo; - -// QRCodeGenerator generates class M QR codes of various versions. -// References in the following comments refer to ISO 18004 (3rd edition). -// Supports versions up to 26 by adding constants. -class QRCodeGenerator { - public: - // Contains output data for Generate(). - // The default state contains no data. - struct GeneratedCode { - public: - GeneratedCode(); - GeneratedCode(GeneratedCode&&); - ~GeneratedCode(); - - // Pixel data; pointer to an array of bytes, where the least-significant - // bit of each byte is set if that tile should be "black". - // Clients should ensure four modules of padding when rendering the code. - // On error, will not be populated, and will evaluate to false. - base::span<uint8_t> data; - - // Width and height (which are equal) of the generated data, in tiles. - int qr_size = 0; - - DISALLOW_COPY_AND_ASSIGN(GeneratedCode); - }; - - // Static parameters for V5 QR codes. - // These exist while migrating clients to dynamic sizes. - struct V5 { - static constexpr int kSize = 37; - static constexpr int kTotalSize = kSize * kSize; - static constexpr size_t kNumSegments = 2; - static constexpr size_t kSegmentDataBytes = 43; - static constexpr size_t kDataBytes = kSegmentDataBytes * kNumSegments; - static constexpr size_t kInputBytes = kDataBytes - 2; - }; - - QRCodeGenerator(); - ~QRCodeGenerator(); - - // Generates a QR code containing the given data. - // The generator will attempt to choose a version that fits the data. The - // returned span's length is input-dependent and not known at compile-time in - // this case. The optional |mask| argument specifies the QR mask value to use - // (from 0 to 7). If not specified, the optimal mask is calculated per the - // algorithm specified in the QR standard. - base::Optional<GeneratedCode> Generate( - base::span<const uint8_t> in, - base::Optional<uint8_t> mask = base::nullopt); - - private: - // PutFinder paints a finder symbol at the given coordinates. - void PutFinder(int x, int y); - - // PutAlignment paints an alignment symbol centered at the given coordinates. - void PutAlignment(int x, int y); - - // PutVerticalTiming paints the vertical timing signal. - void PutVerticalTiming(int x); - - // PutVerticalTiming paints the horizontal timing signal. - void PutHorizontalTiming(int y); - - // PutFormatBits paints the 15-bit, pre-encoded format metadata. See page 56 - // for the location of the format bits. - void PutFormatBits(const uint16_t format); - - // PutVersionBlocks writes the two blocks of version information for QR - // versions seven and above. - void PutVersionBlocks(const uint32_t encoded_version); - - // PutBits writes the given data into the QR code in correct order, avoiding - // structural elements that must have already been painted. See section 7.7.3 - // about the placement algorithm. - void PutBits(const uint8_t* data, - size_t data_len, - uint8_t (*mask_func)(int, int)); - - // at returns a reference to the given element of |d_|. - uint8_t& at(int x, int y); - - // fillAt sets the |len| elements at (x, y) to |value|. - void fillAt(int x, int y, size_t len, uint8_t value); - - // copyTo copies |len| elements from |data| to the elements at (x, y). - void copyTo(int x, int y, const uint8_t* data, size_t len); - - // clipped returns a reference to the given element of |d_|, or to - // |clip_dump_| if the coordinates are out of bounds. - uint8_t& clipped(int x, int y); - - // GF28Mul returns the product of |a| and |b| (which must be field elements, - // i.e. < 256) in the field GF(2^8) mod x^8 + x^4 + x^3 + x^2 + 1. - static uint8_t GF28Mul(uint16_t a, uint16_t b); - - // AddErrorCorrection writes the Reed-Solomon expanded version of |in| to - // |out|. - // |out| should have length block_bytes for the code's version. - // |in| should have length block_data_bytes for the code's version. - // |block_bytes| and |block_ec_bytes| must be provided for the current - // version/level/group. - void AddErrorCorrection(base::span<uint8_t> out, - base::span<const uint8_t> in, - size_t block_bytes, - size_t block_ec_bytes); - - // CountPenaltyPoints sums the penalty points for the current, fully drawn, - // code. See table 11. - unsigned CountPenaltyPoints() const; - - // Parameters for the currently-selected version of the QR code. - // Generate() will pick a version that can contain enough data. - // Unowned; nullptr until initialized in Generate(). - const QRVersionInfo* version_info_ = nullptr; - - // d_ represents a QR code with one byte per pixel. Each byte is one pixel. - // The LSB is set if the pixel is "black". The second bit is set if the pixel - // is part of the structure of the QR code, i.e. finder or alignment symbols, - // timing patterns, or format data. - // Initialized and possibly reinitialized in Generate(). - std::vector<uint8_t> d_; - - // clip_dump_ is the target of paints that would otherwise fall outside of the - // QR code. - uint8_t clip_dump_; -}; - -#endif // CHROME_COMMON_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_
diff --git a/chrome/common/qr_code_generator/qr_code_generator_unittest.cc b/chrome/common/qr_code_generator/qr_code_generator_unittest.cc deleted file mode 100644 index 20d49e0..0000000 --- a/chrome/common/qr_code_generator/qr_code_generator_unittest.cc +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2020 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/common/qr_code_generator/qr_code_generator.h" - -#include "testing/gtest/include/gtest/gtest.h" - -TEST(QRCodeGenerator, Generate) { - // Without a QR decoder implementation, there's a limit to how much we can - // test the QR encoder. Therefore this test just runs a generation to ensure - // that no DCHECKs are hit and that the output has the correct structure. When - // run under ASan, this will also check that every byte of the output has been - // written to. - QRCodeGenerator qr; - uint8_t input[QRCodeGenerator::V5::kInputBytes]; - memset(input, 'a', sizeof(input)); - base::Optional<QRCodeGenerator::GeneratedCode> qr_code = qr.Generate(input); - ASSERT_NE(qr_code, base::nullopt); - auto& qr_data = qr_code->data; - - int index = 0; - ASSERT_EQ(qr_data.size(), - static_cast<size_t>(QRCodeGenerator::V5::kTotalSize)); - for (int y = 0; y < QRCodeGenerator::V5::kSize; y++) { - for (int x = 0; x < QRCodeGenerator::V5::kSize; x++) { - ASSERT_EQ(0, qr_data[index++] & 0b11111100); - } - } -} - -TEST(QRCodeGenerator, GenerateVersionSelection) { - // Ensure that dynamic version selection works, - // even when reusing the same QR Generator object. - // Longer inputs produce longer codes. - QRCodeGenerator qr; - - uint8_t input_small[10]; - memset(input_small, 'a', sizeof(input_small)); - base::Optional<QRCodeGenerator::GeneratedCode> qr_code_small( - qr.Generate(input_small)); - ASSERT_NE(qr_code_small, base::nullopt); - int size_small = qr_code_small->data.size(); - - uint8_t input_large[100]; - memset(input_large, 'a', sizeof(input_large)); - base::Optional<QRCodeGenerator::GeneratedCode> qr_code_large( - qr.Generate(input_large)); - ASSERT_NE(qr_code_large, base::nullopt); - int size_large = qr_code_large->data.size(); - - ASSERT_GT(size_small, 0); - ASSERT_GT(size_large, 0); - ASSERT_GT(size_large, size_small); -}
diff --git a/chrome/common/qr_code_generator/qr_print.cc b/chrome/common/qr_code_generator/qr_print.cc deleted file mode 100644 index ade1e38..0000000 --- a/chrome/common/qr_code_generator/qr_print.cc +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2020 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. - -// This helper binary can be compiled to aid in development / debugging of the -// QR generation code. It prints a QR code to the console and thus allows much -// faster iteration. It is not built by default, see the BUILD.gn in this -// directory. - -#include <stdio.h> - -#include <utility> - -#include "base/containers/span.h" -#include "base/optional.h" -#include "base/strings/string_number_conversions.h" -#include "chrome/common/qr_code_generator/qr_code_generator.h" - -// kTerminalBackgroundIsBright controls the output polarity. Many QR scanners -// will cope with inverted bright / dark but, if you have a bright terminal -// background, you may need to change this. -constexpr bool kTerminalBackgroundIsBright = false; - -// kPaint is a pair of UTF-8 encoded code points for U+2588 ("FULL BLOCK"). -static constexpr char kPaint[] = "\xe2\x96\x88\xe2\x96\x88"; -static constexpr char kNoPaint[] = " "; - -static void PrintHorizontalLine(const char* white, int size) { - for (int x = 0; x < size + 2; x++) { - fputs(white, stdout); - } - fputs("\n", stdout); -} - -int main(int argc, char** argv) { - // Presubmits don't allow fprintf to a variable called |stderr|. - FILE* const STDERR = stderr; - - if (argc < 2 || argc > 3) { - fprintf(STDERR, "Usage: %s <input string> [mask number]\n", argv[0]); - return 1; - } - - const uint8_t* const input = reinterpret_cast<const uint8_t*>(argv[1]); - const size_t input_len = strlen(argv[1]); - - base::Optional<uint8_t> mask; - if (argc == 3) { - unsigned mask_unsigned; - if (!base::StringToUint(argv[2], &mask_unsigned) || mask_unsigned > 7) { - fprintf(STDERR, "Mask numbers run from zero to seven.\n"); - return 1; - } - mask = static_cast<uint8_t>(mask_unsigned); - } - - const char* black = kNoPaint; - const char* white = kPaint; - if (kTerminalBackgroundIsBright) { - std::swap(black, white); - } - - QRCodeGenerator generator; - base::Optional<QRCodeGenerator::GeneratedCode> code = - generator.Generate(base::span<const uint8_t>(input, input_len), mask); - if (!code) { - fprintf(STDERR, "Input too long to be encoded.\n"); - return 2; - } - - const int size = code->qr_size; - PrintHorizontalLine(white, size); - - int i = 0; - for (int y = 0; y < size; y++) { - fputs(white, stdout); - for (int x = 0; x < size; x++) { - fputs((code->data[i++] & 1) ? black : white, stdout); - } - fputs(white, stdout); - fputs("\n", stdout); - } - - PrintHorizontalLine(white, size); - - return 0; -}
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 8425272f..fea876e 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1494,10 +1494,11 @@ // Web Share is conditionally enabled here in chrome/, to avoid it being // made available in other clients of content/ that do not have a Web Share // Mojo implementation (e.g. WebView). Web Share is shipped on Android. -#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) +#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) || defined(OS_MAC) if (base::FeatureList::IsEnabled(features::kWebShare)) #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) || defined(OS_ANDROID) +#if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) || defined(OS_MAC) || \ + defined(OS_ANDROID) blink::WebRuntimeFeatures::EnableWebShare(true); #endif
diff --git a/chrome/services/qrcode_generator/BUILD.gn b/chrome/services/qrcode_generator/BUILD.gn index 638a9c9..2cb53b93 100644 --- a/chrome/services/qrcode_generator/BUILD.gn +++ b/chrome/services/qrcode_generator/BUILD.gn
@@ -13,7 +13,7 @@ deps = [ "//base", "//chrome:strings", - "//chrome/common/qr_code_generator", + "//components/qr_code_generator", "//mojo/public/cpp/bindings", "//net", "//ui/gfx",
diff --git a/chrome/services/qrcode_generator/DEPS b/chrome/services/qrcode_generator/DEPS index 0fc51a2e..b4a1baf1 100644 --- a/chrome/services/qrcode_generator/DEPS +++ b/chrome/services/qrcode_generator/DEPS
@@ -1,3 +1,3 @@ include_rules = [ - "+chrome/common/qr_code_generator.h", + "+components/qr_code_generator", ]
diff --git a/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc b/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc index 2d1aa6a..104e68e 100644 --- a/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc +++ b/chrome/services/qrcode_generator/qrcode_generator_service_impl.cc
@@ -9,8 +9,8 @@ #include <utility> #include "base/strings/string_util.h" -#include "chrome/common/qr_code_generator/dino_image.h" -#include "chrome/common/qr_code_generator/qr_code_generator.h" +#include "components/qr_code_generator/dino_image.h" +#include "components/qr_code_generator/qr_code_generator.h" #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/size.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index c7ffce3..3141408f8 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -442,6 +442,8 @@ sources += [ "../browser/extensions/browsertest_util.cc", "../browser/extensions/browsertest_util.h", + "../browser/extensions/extension_apitest.cc", + "../browser/extensions/extension_apitest.h", "../browser/extensions/extension_browsertest.cc", "../browser/extensions/extension_browsertest.h", "../browser/extensions/permissions_test_util.cc", @@ -911,7 +913,6 @@ data = [ "data/", "//chrome/browser/page_load_metrics/integration_tests/data/", - "//chrome/common/extensions/docs/examples/apps/calculator/", "//components/test/data/arc/", "//components/test/data/autofill/", "//components/test/data/payments/", @@ -1693,7 +1694,8 @@ } if (is_mac) { - sources += [ "../browser/metrics/power_metrics_provider_mac_unittest.cc" ] + sources += + [ "../browser/metrics/power/power_metrics_provider_mac_unittest.cc" ] } if (is_chromeos_ash) { @@ -2016,6 +2018,7 @@ "../browser/extensions/background_page_apitest.cc", "../browser/extensions/background_scripts_apitest.cc", "../browser/extensions/background_xhr_browsertest.cc", + "../browser/extensions/calculator_app_browsertest.cc", "../browser/extensions/chrome_app_api_browsertest.cc", "../browser/extensions/chrome_test_extension_loader_browsertest.cc", "../browser/extensions/chrome_theme_url_browsertest.cc", @@ -2029,13 +2032,10 @@ "../browser/extensions/corb_and_cors_extension_browsertest.cc", "../browser/extensions/cross_origin_xhr_apitest.cc", "../browser/extensions/crx_installer_browsertest.cc", - "../browser/extensions/docs/examples/apps/calculator_browsertest.cc", "../browser/extensions/error_console/error_console_browsertest.cc", "../browser/extensions/events_apitest.cc", "../browser/extensions/execute_script_apitest.cc", "../browser/extensions/extension_action_runner_browsertest.cc", - "../browser/extensions/extension_apitest.cc", - "../browser/extensions/extension_apitest.h", "../browser/extensions/extension_bindings_apitest.cc", "../browser/extensions/extension_bookmarklet_browsertest.cc", "../browser/extensions/extension_browsertest_browsertest.cc", @@ -3500,7 +3500,6 @@ "../browser/endpoint_fetcher/endpoint_fetcher_unittest.cc", "../browser/engagement/important_sites_util_unittest.cc", "../browser/engagement/site_engagement_helper_unittest.cc", - "../browser/engagement/site_engagement_score_unittest.cc", "../browser/engagement/site_engagement_service_unittest.cc", "../browser/enterprise/util/affiliation_unittest.cc", "../browser/enterprise/util/managed_browser_utils_unittest.cc", @@ -3847,7 +3846,6 @@ "../common/ini_parser_unittest.cc", "../common/net/safe_search_util_unittest.cc", "../common/pref_names_util_unittest.cc", - "../common/qr_code_generator/qr_code_generator_unittest.cc", "../renderer/chrome_content_renderer_client_unittest.cc", "../renderer/chrome_render_frame_observer_unittest.cc", "../renderer/instant_restricted_id_cache_unittest.cc", @@ -4315,10 +4313,6 @@ ] } - if (is_win || is_mac || (is_linux && !is_chromeos_lacros)) { - sources += [ "../browser/ui/profile_picker_unittest.cc" ] - } - if (enable_offline_pages) { sources += [ "../browser/offline_pages/background_loader_offliner_unittest.cc",
diff --git a/chrome/test/chromedriver/support/release/release.sh b/chrome/test/chromedriver/support/release/release.sh index de8427a..cf7ec64 100755 --- a/chrome/test/chromedriver/support/release/release.sh +++ b/chrome/test/chromedriver/support/release/release.sh
@@ -42,27 +42,33 @@ rm -rf $tgt rm -rf chromedriver_linux64 rm -rf chromedriver_mac64 +rm -rf chromedriver_mac64_m1 rm -rf chromedriver_win32 mkdir $src mkdir $tgt +mkdir chromedriver_mac64_m1 gsutil cp gs://chrome-unsigned/desktop-5c0tCh/$version/linux64/chromedriver_linux64.zip $src gsutil cp gs://chrome-unsigned/desktop-5c0tCh/$version/mac64/chromedriver_mac64.zip $src +gsutil cp gs://chrome-unsigned/desktop-5c0tCh/$version/mac-arm64/chromedriver_mac64.zip $src/chromedriver_mac64_m1.zip gsutil cp gs://chrome-unsigned/desktop-5c0tCh/$version/win-clang/chromedriver_win32.zip $src unzip $src/chromedriver_linux64.zip unzip $src/chromedriver_mac64.zip +unzip $src/chromedriver_mac64_m1.zip -d chromedriver_mac64_m1/ unzip $src/chromedriver_win32.zip strip chromedriver_linux64/chromedriver zip -j $tgt/chromedriver_linux64.zip chromedriver_linux64/chromedriver zip -j $tgt/chromedriver_mac64.zip chromedriver_mac64/chromedriver +zip -j $tgt/chromedriver_mac64_m1.zip chromedriver_mac64_m1/chromedriver_mac64/chromedriver zip -j $tgt/chromedriver_win32.zip chromedriver_win32/chromedriver.exe gsutil cp $tgt/chromedriver_linux64.zip gs://chromedriver/$version/chromedriver_linux64.zip gsutil cp $tgt/chromedriver_mac64.zip gs://chromedriver/$version/chromedriver_mac64.zip +gsutil cp $tgt/chromedriver_mac64_m1.zip gs://chromedriver/$version/chromedriver_mac64_m1.zip gsutil cp $tgt/chromedriver_win32.zip gs://chromedriver/$version/chromedriver_win32.zip echo -n $version > latest
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/LICENSE b/chrome/test/data/extensions/calculator_app/LICENSE similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/LICENSE rename to chrome/test/data/extensions/calculator_app/LICENSE
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/OWNERS b/chrome/test/data/extensions/calculator_app/OWNERS similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/OWNERS rename to chrome/test/data/extensions/calculator_app/OWNERS
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/README.md b/chrome/test/data/extensions/calculator_app/README.md similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/README.md rename to chrome/test/data/extensions/calculator_app/README.md
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/LICENSE b/chrome/test/data/extensions/calculator_app/app/LICENSE similarity index 100% copy from chrome/common/extensions/docs/examples/apps/calculator/app/LICENSE copy to chrome/test/data/extensions/calculator_app/app/LICENSE
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/calculator.html b/chrome/test/data/extensions/calculator_app/app/calculator.html similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/calculator.html rename to chrome/test/data/extensions/calculator_app/app/calculator.html
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/controller.js b/chrome/test/data/extensions/calculator_app/app/controller.js similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/controller.js rename to chrome/test/data/extensions/calculator_app/app/controller.js
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/images/buttons_1x.png b/chrome/test/data/extensions/calculator_app/app/images/buttons_1x.png similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/images/buttons_1x.png rename to chrome/test/data/extensions/calculator_app/app/images/buttons_1x.png Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/images/buttons_2x.png b/chrome/test/data/extensions/calculator_app/app/images/buttons_2x.png similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/images/buttons_2x.png rename to chrome/test/data/extensions/calculator_app/app/images/buttons_2x.png Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/images/icon-128x128.png b/chrome/test/data/extensions/calculator_app/app/images/icon-128x128.png similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/images/icon-128x128.png rename to chrome/test/data/extensions/calculator_app/app/images/icon-128x128.png Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/images/icon-16x16.png b/chrome/test/data/extensions/calculator_app/app/images/icon-16x16.png similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/images/icon-16x16.png rename to chrome/test/data/extensions/calculator_app/app/images/icon-16x16.png Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/manifest.json b/chrome/test/data/extensions/calculator_app/app/manifest.json similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/manifest.json rename to chrome/test/data/extensions/calculator_app/app/manifest.json
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/model.js b/chrome/test/data/extensions/calculator_app/app/model.js similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/model.js rename to chrome/test/data/extensions/calculator_app/app/model.js
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/style.css b/chrome/test/data/extensions/calculator_app/app/style.css similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/style.css rename to chrome/test/data/extensions/calculator_app/app/style.css
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/app/view.js b/chrome/test/data/extensions/calculator_app/app/view.js similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/app/view.js rename to chrome/test/data/extensions/calculator_app/app/view.js
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/assets/440-280-tile.png b/chrome/test/data/extensions/calculator_app/assets/440-280-tile.png similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/assets/440-280-tile.png rename to chrome/test/data/extensions/calculator_app/assets/440-280-tile.png Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/assets/promo.png b/chrome/test/data/extensions/calculator_app/assets/promo.png similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/assets/promo.png rename to chrome/test/data/extensions/calculator_app/assets/promo.png Binary files differ
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/tests/automatic.html b/chrome/test/data/extensions/calculator_app/tests/automatic.html similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/tests/automatic.html rename to chrome/test/data/extensions/calculator_app/tests/automatic.html
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/tests/manual.css b/chrome/test/data/extensions/calculator_app/tests/manual.css similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/tests/manual.css rename to chrome/test/data/extensions/calculator_app/tests/manual.css
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/tests/manual.html b/chrome/test/data/extensions/calculator_app/tests/manual.html similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/tests/manual.html rename to chrome/test/data/extensions/calculator_app/tests/manual.html
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/tests/manual.js b/chrome/test/data/extensions/calculator_app/tests/manual.js similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/tests/manual.js rename to chrome/test/data/extensions/calculator_app/tests/manual.js
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/tests/tests.js b/chrome/test/data/extensions/calculator_app/tests/tests.js similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/tests/tests.js rename to chrome/test/data/extensions/calculator_app/tests/tests.js
diff --git a/chrome/common/extensions/docs/examples/apps/calculator/tests/utilities.js b/chrome/test/data/extensions/calculator_app/tests/utilities.js similarity index 100% rename from chrome/common/extensions/docs/examples/apps/calculator/tests/utilities.js rename to chrome/test/data/extensions/calculator_app/tests/utilities.js
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn index daa980cd..de7f52cb 100644 --- a/chrome/test/data/pdf/BUILD.gn +++ b/chrome/test/data/pdf/BUILD.gn
@@ -39,6 +39,7 @@ #":touch_handling_test", ":viewer_pdf_sidenav_test", ":viewer_pdf_toolbar_new_test", + ":viewer_properties_dialog_test", ":viewer_thumbnail_bar_test", ":viewer_thumbnail_test", ":viewport_test", @@ -206,6 +207,15 @@ externs_list = [ "$externs_path/test.js" ] } +js_library("viewer_properties_dialog_test") { + deps = [ + "../webui:test_util.m", + "//chrome/browser/resources/pdf:pdf_viewer", + "//chrome/browser/resources/pdf/elements:viewer-properties-dialog", + ] + externs_list = [ "$externs_path/test.js" ] +} + js_library("viewer_thumbnail_bar_test") { deps = [ "../webui:test_util.m",
diff --git a/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js b/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js index 157fb1c..4f09908 100644 --- a/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js +++ b/chrome/test/data/pdf/viewer_pdf_toolbar_new_test.js
@@ -313,6 +313,16 @@ await whenFired; chrome.test.succeed(); }, + async function testPropertiesButton() { + const toolbar = createToolbar(); + const button = toolbar.shadowRoot.querySelector('#properties-button'); + chrome.test.assertTrue(!!button); + + const whenFired = eventToPromise('properties-click', toolbar); + button.click(); + await whenFired; + chrome.test.succeed(); + } ]; chrome.test.runTests(tests);
diff --git a/chrome/test/data/pdf/viewer_properties_dialog_test.js b/chrome/test/data/pdf/viewer_properties_dialog_test.js new file mode 100644 index 0000000..7553839 --- /dev/null +++ b/chrome/test/data/pdf/viewer_properties_dialog_test.js
@@ -0,0 +1,44 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {eventToPromise} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/_test_resources/webui/test_util.m.js'; +import {ViewerPropertiesDialogElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/elements/viewer-properties-dialog.js'; +import {PDFViewerElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer.js'; + +const viewer = /** @type {!PDFViewerElement} */ ( + document.body.querySelector('pdf-viewer')); + +async function ensurePropertiesDialogOpen() { + chrome.test.assertFalse(!!getPropertiesDialog()); + const whenOpen = eventToPromise('cr-dialog-open', viewer); + const toolbar = viewer.shadowRoot.querySelector('viewer-pdf-toolbar-new'); + toolbar.dispatchEvent(new CustomEvent('properties-click')); + await whenOpen; + chrome.test.assertTrue(!!getPropertiesDialog()); +} + +async function ensurePropertiesDialogClose() { + const dialog = getPropertiesDialog(); + chrome.test.assertTrue(!!dialog); + const whenClosed = eventToPromise('close', dialog); + dialog.shadowRoot.querySelector('#close').click(); + await whenClosed; + chrome.test.assertFalse(!!getPropertiesDialog()); +} + +/** @return {!ViewerPropertiesDialogElement} */ +function getPropertiesDialog() { + return /** @type {!ViewerPropertiesDialogElement} */ ( + viewer.shadowRoot.querySelector('#properties-dialog')); +} + +const tests = [ + async function testPropertiesDialog() { + await ensurePropertiesDialogOpen(); + await ensurePropertiesDialogClose(); + chrome.test.succeed(); + }, +]; + +chrome.test.runTests(tests);
diff --git a/chrome/test/data/webui/history/history_list_focus_test.js b/chrome/test/data/webui/history/history_list_focus_test.js index 32c735c..3d32c19 100644 --- a/chrome/test/data/webui/history/history_list_focus_test.js +++ b/chrome/test/data/webui/history/history_list_focus_test.js
@@ -146,6 +146,7 @@ assertEquals(4, element.historyData_.length); assertEquals(4, items.length); items[3].$['menu-button'].click(); + await flushTasks(); element.$$('#menuRemoveButton').click(); assertNotEquals(items[2].$['menu-button'], element.lastFocused_); await testService.whenCalled('removeVisits');
diff --git a/chrome/test/data/webui/test_util.js b/chrome/test/data/webui/test_util.js index f0d8b88..e07d5f5 100644 --- a/chrome/test/data/webui/test_util.js +++ b/chrome/test/data/webui/test_util.js
@@ -132,7 +132,7 @@ // Promises have microtask timing, so we use setTimeout to explicitly force // a new task. return new Promise(function(resolve, reject) { - window.setTimeout(resolve, 1); + window.setTimeout(resolve, 0); }); }
diff --git a/chrome/test/media_router/BUILD.gn b/chrome/test/media_router/BUILD.gn index f3dbc7f..1ebfd0a 100644 --- a/chrome/test/media_router/BUILD.gn +++ b/chrome/test/media_router/BUILD.gn
@@ -26,13 +26,18 @@ ] deps = [ ":test_support", + "//build:chromeos_buildflags", "//chrome/app:generated_resources", "//chrome/browser", "//chrome/browser/media/router", "//chrome/browser/ui", "//chrome/common", + "//chrome/test:test_support", "//chrome/test:test_support_ui", "//components/media_router/common", + "//components/policy/core/browser", + "//components/policy/core/common:test_support", + "//components/sessions", "//content/public/browser", "//content/test:test_support", "//media:test_support", @@ -40,6 +45,8 @@ "//net:test_support", "//testing/gtest", "//ui/base", + "//ui/events:test_support", + "//ui/views:test_support", "//url", ] data_deps = [
diff --git a/chrome/updater/crash_reporter.cc b/chrome/updater/crash_reporter.cc index ec96de24..02a18ae 100644 --- a/chrome/updater/crash_reporter.cc +++ b/chrome/updater/crash_reporter.cc
@@ -73,6 +73,7 @@ std::vector<std::string> arguments; arguments.push_back(base::StrCat({"--", kCrashHandlerSwitch})); + // TODO(crbug.com/1163583): use the production front end instead of staging. crashpad::CrashpadClient* client = GetCrashpadClient(); if (!client->StartHandler(handler_path, database_path, /*metrics_dir=*/base::FilePath(),
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc index 2069446..0d121a2 100644 --- a/chrome/updater/test/integration_tests.cc +++ b/chrome/updater/test/integration_tests.cc
@@ -238,7 +238,8 @@ } // TODO(crbug.com/1163524): Enable on Windows. -TEST_F(IntegrationTest, ReportsActive) { +// TODO(crbug.com/1163625): Failing on Mac 10.11. +TEST_F(IntegrationTest, DISABLED_ReportsActive) { // A longer than usual timeout is needed for this test because the macOS // UpdateServiceInternal server takes at least 10 seconds to shut down after // Install, and RegisterApp cannot make progress until it shut downs and
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index c29da56..396258fb 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13707.0.0 \ No newline at end of file +13708.0.0 \ No newline at end of file
diff --git a/chromeos/components/camera_app_ui/resources/css/main.css b/chromeos/components/camera_app_ui/resources/css/main.css index df4586d..e7d3b8e 100644 --- a/chromeos/components/camera_app_ui/resources/css/main.css +++ b/chromeos/components/camera_app_ui/resources/css/main.css
@@ -653,11 +653,11 @@ margin: var(--option-item-vpadding) 0; } -body._3sec #toggle-timer:checked { +body.timer-3s #toggle-timer:checked { background-image: url(/images/camera_button_timer_on_3s.svg); } -body._10sec #toggle-timer:checked { +body.timer-10s #toggle-timer:checked { background-image: url(/images/camera_button_timer_on_10s.svg); } @@ -704,11 +704,11 @@ display: none; } -body._30fps #toggle-fps { +body.fps-30 #toggle-fps { background-image: url(/images/camera_button_fps_30.svg); } -body._60fps #toggle-fps { +body.fps-60 #toggle-fps { background-image: url(/images/camera_button_fps_60.svg); } @@ -955,7 +955,7 @@ transform: translateY(-50%); } -body._4x4 #preview-grid-horizontal::before { +body.grid-4x4 #preview-grid-horizontal::before { border-bottom: 1px solid white; content: ''; height: 0; @@ -965,20 +965,20 @@ top: 0; } -body.grid._3x3 #preview-grid-horizontal, -body.view-grid-settings._3x3 #preview-grid-horizontal { +body.grid-3x3 #preview-grid-horizontal, +body.view-grid-settings.grid-3x3 #preview-grid-horizontal { height: 33.333%; } -body.grid.golden #preview-grid-horizontal, -body.view-grid-settings.golden #preview-grid-horizontal { +body.grid.grid-golden #preview-grid-horizontal, +body.view-grid-settings.grid-golden #preview-grid-horizontal { height: 23.607%; } -body.grid._4x4 #preview-grid-horizontal, -body.grid._4x4 #preview-grid-horizontal::before, -body.view-grid-settings._4x4 #preview-grid-horizontal, -body.view-grid-settings._4x4 #preview-grid-horizontal::before { +body.grid.grid-4x4 #preview-grid-horizontal, +body.grid.grid-4x4 #preview-grid-horizontal::before, +body.view-grid-settings.grid-4x4 #preview-grid-horizontal, +body.view-grid-settings.grid-4x4 #preview-grid-horizontal::before { height: 50%; } @@ -993,7 +993,7 @@ width: 100%; } -body._4x4 #preview-grid-vertical::before { +body.grid-4x4 #preview-grid-vertical::before { border-right: 1px solid white; /* csschecker-disable-line left-right */ bottom: 0; content: ''; @@ -1003,20 +1003,20 @@ width: 0; } -body.grid._3x3 #preview-grid-vertical, -body.view-grid-settings._3x3 #preview-grid-vertical { +body.grid.grid-3x3 #preview-grid-vertical, +body.view-grid-settings.grid-3x3 #preview-grid-vertical { width: 33.333%; } -body.grid.golden #preview-grid-vertical, -body.view-grid-settings.golden #preview-grid-vertical { +body.grid.grid-golden #preview-grid-vertical, +body.view-grid-settings.grid-golden #preview-grid-vertical { width: 23.607%; } -body.grid._4x4 #preview-grid-vertical, -body.grid._4x4 #preview-grid-vertical::before, -body.view-grid-settings._4x4 #preview-grid-vertical, -body.view-grid-settings._4x4 #preview-grid-vertical::before { +body.grid.grid-4x4 #preview-grid-vertical, +body.grid.grid-4x4 #preview-grid-vertical::before, +body.view-grid-settings.grid-4x4 #preview-grid-vertical, +body.view-grid-settings.grid-4x4 #preview-grid-vertical::before { width: 50%; } @@ -1343,11 +1343,11 @@ display: none; } -body._3x3 .description span[i18n-content=label_grid_3x3], -body._4x4 .description span[i18n-content=label_grid_4x4], -body.golden .description span[i18n-content=label_grid_golden], -body._3sec .description span[i18n-content=label_timer_3s], -body._10sec .description span[i18n-content=label_timer_10s], +body.grid-3x3 .description span[i18n-content=label_grid_3x3], +body.grid-4x4 .description span[i18n-content=label_grid_4x4], +body.grid-golden .description span[i18n-content=label_grid_golden], +body.timer-3s .description span[i18n-content=label_timer_3s], +body.timer-10s .description span[i18n-content=label_timer_10s], .menu-item.resol-item .description span { display: inline; }
diff --git a/chromeos/components/camera_app_ui/resources/js/device/constraints_preferrer.js b/chromeos/components/camera_app_ui/resources/js/device/constraints_preferrer.js index 3a001477..5785804 100644 --- a/chromeos/components/camera_app_ui/resources/js/device/constraints_preferrer.js +++ b/chromeos/components/camera_app_ui/resources/js/device/constraints_preferrer.js
@@ -289,7 +289,7 @@ } this.toggleFps_.checked = prefFps === 60; SUPPORTED_CONSTANT_FPS.forEach( - (fps) => state.set(state.assertState(`_${fps}fps`), fps === prefFps)); + (fps) => state.set(state.assertState(`fps-${fps}`), fps === prefFps)); this.prefFpses_[deviceId] = this.prefFpses_[deviceId] || {}; this.prefFpses_[deviceId][resolution] = prefFps; this.saveFpsPreference_();
diff --git a/chromeos/components/camera_app_ui/resources/js/state.js b/chromeos/components/camera_app_ui/resources/js/state.js index a758b45..ed8792f 100644 --- a/chromeos/components/camera_app_ui/resources/js/state.js +++ b/chromeos/components/camera_app_ui/resources/js/state.js
@@ -17,11 +17,11 @@ CAMERA_CONFIGURING: 'camera-configuring', CAMERA_SWITCHING: 'camera-switching', EXPERT: 'expert', - FPS_30: '_30fps', - FPS_60: '_60fps', - GRID_3x3: '_3x3', - GRID_4x4: '_4x4', - GRID_GOLDEN: 'golden', + FPS_30: 'fps-30', + FPS_60: 'fps-60', + GRID_3x3: 'grid-3x3', + GRID_4x4: 'grid-4x4', + GRID_GOLDEN: 'grid-golden', GRID: 'grid', HAS_BACK_CAMERA: 'has-back-camera', HAS_EXTERNAL_SCREEN: 'has-external-screen', @@ -56,8 +56,8 @@ TAB_NAVIGATION: 'tab-navigation', TAKING: 'taking', TALL: 'tall', - TIMER_10SEC: '_10sec', - TIMER_3SEC: '_3sec', + TIMER_10SEC: 'timer-10s', + TIMER_3SEC: 'timer-3s', TIMER: 'timer', };
diff --git a/chromeos/components/camera_app_ui/resources/views/main.html b/chromeos/components/camera_app_ui/resources/views/main.html index 35dc83a6..b17bd9c 100644 --- a/chromeos/components/camera_app_ui/resources/views/main.html +++ b/chromeos/components/camera_app_ui/resources/views/main.html
@@ -23,7 +23,7 @@ <script src="/js/mojo/camera_app_helper.mojom-lite.js"></script> <script type="module" src="/js/init.js"></script> </head> - <body class="sound mirror mic _3x3 view-splash"> + <body class="sound mirror mic grid-3x3 view-splash"> <div id="view-camera"> <div id="preview-box"> <div id="preview-viewport"> @@ -279,17 +279,19 @@ </div> <label class="menu-item circle"> <input id="grid-3x3" class="icon" type="radio" tabindex="0" - name="gridtype" data-state="_3x3" data-key="toggle3x3" checked> + name="gridtype" data-state="grid-3x3" data-key="toggle3x3" + checked> <span i18n-content="label_grid_3x3" i18n-aria="aria_grid_3x3"></span> </label> <label class="menu-item circle"> <input id="grid-4x4" class="icon" type="radio" tabindex="0" - name="gridtype" data-state="_4x4" data-key="toggle4x4"> + name="gridtype" data-state="grid-4x4" data-key="toggle4x4"> <span i18n-content="label_grid_4x4" i18n-aria="aria_grid_4x4"></span> </label> <label class="menu-item circle"> <input id="grid-golden" class="icon" type="radio" tabindex="0" - name="gridtype" data-state="golden" data-key="toggleGolden"> + name="gridtype" data-state="grid-golden" + data-key="toggleGolden"> <span i18n-content="label_grid_golden"></span> </label> </div> @@ -302,13 +304,13 @@ </div> <label class="menu-item circle"> <input id="timer-3s" class="icon" type="radio" tabindex="0" - name="timerdur" data-state="_3sec" data-key="toggle3sec" + name="timerdur" data-state="timer-3s" data-key="toggle3sec" checked> <span i18n-content="label_timer_3s"></span> </label> <label class="menu-item circle"> <input id="timer-10s" class="icon" type="radio" tabindex="0" - name="timerdur" data-state="_10sec" data-key="toggle10sec"> + name="timerdur" data-state="timer-10s" data-key="toggle10sec"> <span i18n-content="label_timer_10s"></span> </label> </div>
diff --git a/chromeos/components/scanning/resources/scanning_shared_css.html b/chromeos/components/scanning/resources/scanning_shared_css.html index 22739cb..f4d65c2 100644 --- a/chromeos/components/scanning/resources/scanning_shared_css.html +++ b/chromeos/components/scanning/resources/scanning_shared_css.html
@@ -20,6 +20,7 @@ @apply --scanning-select-font; background-position-x: calc(100% - 12px); color: var(--scanning-select-text-color); + padding-inline-end: 32px; padding-inline-start: 16px; }
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index af60935..3ff4352 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -378,6 +378,11 @@ const base::Feature kClipboardHistorySimpleRender{ "ClipboardHistorySimpleRender", base::FEATURE_DISABLED_BY_DEFAULT}; +// If enabled, a blue new nudge will show on the context menu option for +// clipboard history. +const base::Feature kClipboardHistoryContextMenuNudge{ + "ClipboardHistoryContextMenuNudge", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables copying an image to the system clipboard to support pasting onto // different surfaces const base::Feature kEnableFilesAppCopyImage{"EnableFilesAppCopyImage", @@ -810,6 +815,10 @@ base::FeatureList::IsEnabled(kClipboardHistorySimpleRender); } +bool IsClipboardHistoryContextMenuNudgeEnabled() { + return base::FeatureList::IsEnabled(kClipboardHistoryContextMenuNudge); +} + bool IsPhoneHubEnabled() { return base::FeatureList::IsEnabled(kPhoneHub); }
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index d5d5f4c..77d045f 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -168,6 +168,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kClipboardHistorySimpleRender; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +extern const base::Feature kClipboardHistoryContextMenuNudge; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kEnableFilesAppCopyImage; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kFsNosymfollow; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) @@ -351,6 +353,8 @@ bool IsClipboardHistoryNudgeSessionResetEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsClipboardHistorySimpleRenderEnabled(); +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +bool IsClipboardHistoryContextMenuNudgeEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsOobeChromeVoxHintEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsOobeScreensPriorityEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsPhoneHubEnabled();
diff --git a/chromeos/services/assistant/proxy/service_controller_proxy.cc b/chromeos/services/assistant/proxy/service_controller_proxy.cc index 8390fc7..3aa6c29 100644 --- a/chromeos/services/assistant/proxy/service_controller_proxy.cc +++ b/chromeos/services/assistant/proxy/service_controller_proxy.cc
@@ -212,7 +212,6 @@ switch (new_state) { case ServiceState::kStarted: - DCHECK_EQ(state_, State::kStarting); FinishCreatingAssistant(); break; case ServiceState::kRunning: @@ -237,6 +236,16 @@ } void ServiceControllerProxy::FinishCreatingAssistant() { + if (state_ == State::kStopped) { + // We can come here if the system went into shutdown while the mojom + // service was busy starting Libassistant. + // This means the |AssistantManager| could be destroyed at any second, + // so we simply clean up and bail out. + on_start_done_callback_.reset(); + pending_display_connection_ = nullptr; + return; + } + DCHECK(on_start_done_callback_.has_value()); DCHECK_NE(pending_display_connection_, nullptr);
diff --git a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc index 8dd23ef..6a24d10 100644 --- a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc +++ b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.cc
@@ -15,6 +15,10 @@ namespace multidevice_setup { // static +constexpr base::TimeDelta + EligibleHostDevicesProviderImpl::kInactiveDeviceThresholdInDays; + +// static EligibleHostDevicesProviderImpl::Factory* EligibleHostDevicesProviderImpl::Factory::test_factory_ = nullptr; @@ -119,6 +123,35 @@ std::move(device_activity_status_ptr)}); } + // Remove inactive devices. A device is inactive if it has a + // last_activity_time before some defined threshold. + base::Time now = base::Time::Now(); + eligible_active_devices_from_last_sync_.erase( + std::remove_if( + eligible_active_devices_from_last_sync_.begin(), + eligible_active_devices_from_last_sync_.end(), + [&id_to_activity_status_map, + &now](const multidevice::DeviceWithConnectivityStatus& device) { + auto it = id_to_activity_status_map.find( + device.remote_device.instance_id()); + + if (it == id_to_activity_status_map.end()) { + return false; + } + + base::Time last_activity_time = + std::get<1>(*it)->last_activity_time; + + // Do not filter out devices whose last activity time was not set by + // the server. + if (last_activity_time == base::Time()) { + return false; + } + + return now - last_activity_time > kInactiveDeviceThresholdInDays; + }), + eligible_active_devices_from_last_sync_.end()); + // Sort the list preferring online devices, then last activity time, then // last update time. std::sort(
diff --git a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h index 2211b27..3cd64b6 100644 --- a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h +++ b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl.h
@@ -20,6 +20,9 @@ : public EligibleHostDevicesProvider, public device_sync::DeviceSyncClient::Observer { public: + static constexpr base::TimeDelta kInactiveDeviceThresholdInDays = + base::TimeDelta::FromDays(30); + class Factory { public: static std::unique_ptr<EligibleHostDevicesProvider> Create(
diff --git a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc index 75dae4f1..65a732dd 100644 --- a/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc +++ b/chromeos/services/multidevice_setup/eligible_host_devices_provider_impl_unittest.cc
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/stl_util.h" #include "base/test/scoped_feature_list.h" +#include "base/time/time_override.h" #include "chromeos/components/multidevice/remote_device_test_util.h" #include "chromeos/components/multidevice/software_feature.h" #include "chromeos/components/multidevice/software_feature_state.h" @@ -180,6 +181,11 @@ fake_device_sync_client()->set_synced_devices(devices); fake_device_sync_client()->NotifyNewDevicesSynced(); + // Set current time so that no devices are filtered out based on their last + // activity time + base::subtle::ScopedTimeClockOverrides time_now_override( + []() { return base::Time::FromTimeT(20000); }, nullptr, nullptr); + std::vector<device_sync::mojom::DeviceActivityStatusPtr> device_activity_statuses; device_activity_statuses.emplace_back( @@ -255,6 +261,67 @@ } TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest, + GetDevicesActivityStatusRemovesInactiveDevices) { + if (!use_get_devices_activity_status()) { + return; + } + + SetBitsOnTestDevices(); + + base::subtle::ScopedTimeClockOverrides time_now_override( + []() { + return base::Time() + + EligibleHostDevicesProviderImpl::kInactiveDeviceThresholdInDays + + base::TimeDelta::FromDays(1000); + }, + nullptr, nullptr); + + multidevice::RemoteDeviceRefList devices{test_devices()[0], test_devices()[1], + test_devices()[2], test_devices()[3], + test_devices()[4]}; + fake_device_sync_client()->set_synced_devices(devices); + fake_device_sync_client()->NotifyNewDevicesSynced(); + + std::vector<device_sync::mojom::DeviceActivityStatusPtr> + device_activity_statuses; + device_activity_statuses.emplace_back( + device_sync::mojom::DeviceActivityStatus::New( + test_devices()[0].instance_id(), base::Time(), + cryptauthv2::ConnectivityStatus::ONLINE)); + device_activity_statuses.emplace_back( + device_sync::mojom::DeviceActivityStatus::New( + test_devices()[1].instance_id(), + base::Time::Now() - + EligibleHostDevicesProviderImpl::kInactiveDeviceThresholdInDays - + base::TimeDelta::FromDays(1), + cryptauthv2::ConnectivityStatus::OFFLINE)); + device_activity_statuses.emplace_back( + device_sync::mojom::DeviceActivityStatus::New( + test_devices()[2].instance_id(), + base::Time::Now() - + EligibleHostDevicesProviderImpl::kInactiveDeviceThresholdInDays - + base::TimeDelta::FromDays(10), + cryptauthv2::ConnectivityStatus::ONLINE)); + device_activity_statuses.emplace_back( + device_sync::mojom::DeviceActivityStatus::New( + test_devices()[3].instance_id(), + base::Time::Now() - + EligibleHostDevicesProviderImpl::kInactiveDeviceThresholdInDays, + cryptauthv2::ConnectivityStatus::ONLINE)); + + fake_device_sync_client()->InvokePendingGetDevicesActivityStatusCallback( + device_sync::mojom::NetworkRequestResult::kSuccess, + std::move(device_activity_statuses)); + + multidevice::DeviceWithConnectivityStatusList eligible_active_devices = + provider()->GetEligibleActiveHostDevices(); + + EXPECT_EQ(2u, eligible_active_devices.size()); + EXPECT_EQ(test_devices()[3], eligible_active_devices[0].remote_device); + EXPECT_EQ(test_devices()[0], eligible_active_devices[1].remote_device); +} + +TEST_P(MultiDeviceSetupEligibleHostDevicesProviderImplTest, GetDevicesActivityStatusFailedRequest) { if (!use_get_devices_activity_status()) { return;
diff --git a/components/BUILD.gn b/components/BUILD.gn index 6d935dd..dfe7e2d 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -105,7 +105,6 @@ "//components/keyed_service/core:unit_tests", "//components/language/core/browser:unit_tests", "//components/language/core/common:unit_tests", - "//components/language_usage_metrics:unit_tests", "//components/leveldb_proto:unit_tests", "//components/lookalikes/core:unit_tests", "//components/metrics:unit_tests", @@ -128,6 +127,7 @@ "//components/prefs:unit_tests", "//components/previews/core:unit_tests", "//components/proxy_config:unit_tests", + "//components/qr_code_generator:unit_tests", "//components/query_parser:unit_tests", "//components/rappor:unit_tests", "//components/reading_list/core:unit_tests", @@ -297,6 +297,7 @@ "//components/services/paint_preview_compositor:unit_tests", "//components/services/quarantine:unit_tests", "//components/services/storage:tests", + "//components/site_engagement/content:unit_tests", "//components/site_isolation:unit_tests", "//components/spellcheck/browser:unit_tests", "//components/spellcheck/renderer:unit_tests",
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 8bced55..95f1bba 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -401,7 +401,7 @@ "//components/history/core/browser", "//components/infobars/core", "//components/keyed_service/core", - "//components/language_usage_metrics", + "//components/language/core/browser", "//components/leveldb_proto", "//components/os_crypt", "//components/policy/core/browser",
diff --git a/components/autofill/core/browser/DEPS b/components/autofill/core/browser/DEPS index 99a308e..ba108cc 100644 --- a/components/autofill/core/browser/DEPS +++ b/components/autofill/core/browser/DEPS
@@ -4,7 +4,7 @@ "+components/history/core/browser", "+components/infobars/core", "+components/keyed_service/core", - "+components/language_usage_metrics", + "+components/language/core/browser", "+components/leveldb_proto", "+components/metrics", "+components/policy",
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index 4e667a9..253ad6c 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -26,7 +26,7 @@ #include "components/autofill/core/common/autofill_prefs.h" #include "components/autofill/core/common/autofill_tick_clock.h" #include "components/autofill/core/common/form_data.h" -#include "components/language_usage_metrics/language_usage_metrics.h" +#include "components/language/core/browser/language_usage_metrics.h" #include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" @@ -2483,7 +2483,7 @@ base::StringPiece locale) { base::UmaHistogramSparse( "Autofill.ParsedFieldTypesUsingTranslatedPageLanguage", - language_usage_metrics::LanguageUsageMetrics::ToLanguageCode(locale)); + language::LanguageUsageMetrics::ToLanguageCode(locale)); } // static
diff --git a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc index 5611c9d..6fc8c69 100644 --- a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc +++ b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
@@ -22,6 +22,7 @@ #include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" +#include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h" #include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h" @@ -47,13 +48,31 @@ "ContentSettings.Popups.StrongBlocker.NumBlocked"; class SafeBrowsingTriggeredPopupBlockerTest - : public content::RenderViewHostTestHarness { + : public content::RenderViewHostTestHarness, + public subresource_filter::SubresourceFilterClient { public: SafeBrowsingTriggeredPopupBlockerTest() = default; ~SafeBrowsingTriggeredPopupBlockerTest() override { settings_map_->ShutdownOnUIThread(); } + // subresource_filter::SubresourceFilterClient: + void ShowNotification() override {} + subresource_filter::mojom::ActivationLevel OnPageActivationComputed( + content::NavigationHandle* navigation_handle, + subresource_filter::mojom::ActivationLevel initial_activation_level, + subresource_filter::ActivationDecision* decision) override { + return initial_activation_level; + } + void OnAdsViolationTriggered( + content::RenderFrameHost*, + subresource_filter::mojom::AdsViolation) override {} + const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> + GetSafeBrowsingDatabaseManager() override { + return nullptr; + } + void OnReloadRequested() override {} + // content::RenderViewHostTestHarness: void SetUp() override { content::RenderViewHostTestHarness::SetUp(); @@ -142,7 +161,7 @@ content::NavigationHandle* handle) { return std::make_unique< subresource_filter::SubresourceFilterSafeBrowsingActivationThrottle>( - handle, /*delegate=*/nullptr, content::GetIOThreadTaskRunner({}), + handle, this, content::GetIOThreadTaskRunner({}), fake_safe_browsing_database_); }
diff --git a/components/content_capture/OWNERS b/components/content_capture/OWNERS index ce296e0..45bd69b 100644 --- a/components/content_capture/OWNERS +++ b/components/content_capture/OWNERS
@@ -1 +1,2 @@ michaelbai@chromium.org +wangxianzhu@chromium.org
diff --git a/components/content_capture/common/content_capture_features.cc b/components/content_capture/common/content_capture_features.cc index 58832c3..3258e664 100644 --- a/components/content_capture/common/content_capture_features.cc +++ b/components/content_capture/common/content_capture_features.cc
@@ -16,7 +16,7 @@ base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kContentCaptureTriggeringForExperiment{ - "ContentCaptureTriggeringForExperiment", base::FEATURE_ENABLED_BY_DEFAULT}; + "ContentCaptureTriggeringForExperiment", base::FEATURE_DISABLED_BY_DEFAULT}; #else const base::Feature kContentCapture{"ContentCapture", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index eb3c212..862288d 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -734,9 +734,8 @@ jar_path = _native_intermediate_jar_path # Since only the unprocessed jar is used, no need to complete the bytecode - # processing step or check desugar deps. + # processing step. enable_bytecode_checks = false - ignore_desugar_missing_deps = true deps = [ ":repackage_native_impl" ] }
diff --git a/components/feed/core/v2/public/feed_service.cc b/components/feed/core/v2/public/feed_service.cc index a561223..ba1b9a1 100644 --- a/components/feed/core/v2/public/feed_service.cc +++ b/components/feed/core/v2/public/feed_service.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/command_line.h" +#include "base/scoped_observation.h" #include "build/build_config.h" #include "components/feed/core/shared_prefs/pref_names.h" #include "components/feed/core/v2/feed_network_impl.h" @@ -60,7 +61,7 @@ : feed_stream_(feed_stream), identity_manager_(identity_manager) { // May be null for some profiles. if (history_service) - history_service->AddObserver(this); + scoped_history_service_observer_.Observe(history_service); } HistoryObserverImpl(const HistoryObserverImpl&) = delete; HistoryObserverImpl& operator=(const HistoryObserverImpl&) = delete; @@ -76,6 +77,9 @@ private: FeedStream* feed_stream_; signin::IdentityManager* identity_manager_; + base::ScopedObservation<history::HistoryService, + history::HistoryServiceObserver> + scoped_history_service_observer_{this}; }; class FeedService::NetworkDelegateImpl : public FeedNetworkImpl::Delegate {
diff --git a/components/full_restore/BUILD.gn b/components/full_restore/BUILD.gn index cc303cc..f1c2363 100644 --- a/components/full_restore/BUILD.gn +++ b/components/full_restore/BUILD.gn
@@ -34,6 +34,7 @@ "//components/account_id:account_id", "//components/services/app_service/public/cpp:intents", "//components/services/app_service/public/mojom", + "//components/sessions", "//ui/aura", ] } @@ -43,11 +44,13 @@ sources = [ "full_restore_info_unittest.cc", + "full_restore_read_and_save_unittest.cc", "restore_data_unittest.cc", ] deps = [ ":full_restore", + "//content/test:test_support", "//testing/gtest", ] }
diff --git a/components/full_restore/DEPS b/components/full_restore/DEPS index 345e89de..609bb50 100644 --- a/components/full_restore/DEPS +++ b/components/full_restore/DEPS
@@ -3,5 +3,12 @@ "+chromeos/ui/base/window_state_type.h", "+components/account_id/account_id.h", "+components/services/app_service/public", + "+content/public/test", "+ui", ] + +specific_include_rules = { + "full_restore_save_handler\.cc": [ + "+components/sessions/core/session_id.h", + ], +}
diff --git a/components/full_restore/full_restore_read_and_save_unittest.cc b/components/full_restore/full_restore_read_and_save_unittest.cc new file mode 100644 index 0000000..f14404d --- /dev/null +++ b/components/full_restore/full_restore_read_and_save_unittest.cc
@@ -0,0 +1,175 @@ +// Copyright 2021 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 <memory> +#include <utility> + +#include "ash/public/cpp/ash_features.h" +#include "base/files/scoped_temp_dir.h" +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "base/timer/timer.h" +#include "components/full_restore/app_launch_info.h" +#include "components/full_restore/app_restore_data.h" +#include "components/full_restore/full_restore_read_handler.h" +#include "components/full_restore/full_restore_save_handler.h" +#include "components/full_restore/full_restore_utils.h" +#include "components/full_restore/restore_data.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace full_restore { + +namespace { + +const char kAppId[] = "aaa"; + +const int32_t kId1 = 100; +const int32_t kId2 = 200; + +} // namespace + +// Unit tests for restore data. +class FullRestoreReadAndSaveTest : public testing::Test { + public: + FullRestoreReadAndSaveTest() = default; + ~FullRestoreReadAndSaveTest() override = default; + + FullRestoreReadAndSaveTest(const FullRestoreReadAndSaveTest&) = delete; + FullRestoreReadAndSaveTest& operator=(const FullRestoreReadAndSaveTest&) = + delete; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature(ash::features::kFullRestore); + ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir()); + } + + const base::FilePath& GetPath() { return tmp_dir_.GetPath(); } + + void ReadFromFile(const base::FilePath& file_path) { + FullRestoreReadHandler* read_handler = + FullRestoreReadHandler::GetInstance(); + base::RunLoop run_loop; + + read_handler->ReadFromFile( + file_path, base::BindLambdaForTesting( + [&](std::unique_ptr<RestoreData> restore_data) { + run_loop.Quit(); + restore_data_ = std::move(restore_data); + })); + run_loop.Run(); + } + + const RestoreData* GetRestoreData(const base::FilePath& file_path) { + return restore_data_.get(); + } + + void AddAppLaunchInfo(const base::FilePath& file_path, int32_t id) { + full_restore::SaveAppLaunchInfo( + file_path, std::make_unique<full_restore::AppLaunchInfo>(kAppId, id)); + } + + void VerifyRestoreData(const base::FilePath& file_path, int32_t id) { + ReadFromFile(file_path); + + const auto* restore_data = GetRestoreData(file_path); + ASSERT_TRUE(restore_data != nullptr); + + const auto& launch_list = restore_data->app_id_to_launch_list(); + EXPECT_EQ(1u, launch_list.size()); + + // Verify for |kAppId| + const auto launch_list_it = launch_list.find(kAppId); + EXPECT_TRUE(launch_list_it != launch_list.end()); + EXPECT_EQ(1u, launch_list_it->second.size()); + + // Verify for |id| + const auto app_restore_data_it = launch_list_it->second.find(id); + EXPECT_TRUE(app_restore_data_it != launch_list_it->second.end()); + } + + content::BrowserTaskEnvironment& task_environment() { + return task_environment_; + } + + private: + content::BrowserTaskEnvironment task_environment_; + base::ScopedTempDir tmp_dir_; + + base::test::ScopedFeatureList scoped_feature_list_; + + std::unique_ptr<RestoreData> restore_data_; +}; + +TEST_F(FullRestoreReadAndSaveTest, ReadEmptyRestoreData) { + ReadFromFile(GetPath()); + EXPECT_FALSE(GetRestoreData(GetPath())); +} + +TEST_F(FullRestoreReadAndSaveTest, SaveAndReadRestoreData) { + FullRestoreSaveHandler* save_handler = FullRestoreSaveHandler::GetInstance(); + base::OneShotTimer* timer = save_handler->GetTimerForTesting(); + + // Add app launch info, and verity the timer starts. + AddAppLaunchInfo(GetPath(), kId1); + EXPECT_TRUE(timer->IsRunning()); + + // Add one more app launch info, and verity the timer is still running. + AddAppLaunchInfo(GetPath(), kId2); + EXPECT_TRUE(timer->IsRunning()); + + // Simulate timeout, and verity the timer stops. + timer->FireNow(); + task_environment().RunUntilIdle(); + + ReadFromFile(GetPath()); + + // Verify the restore data can be read correctly. + const auto* restore_data = GetRestoreData(GetPath()); + ASSERT_TRUE(restore_data); + + const auto& launch_list = restore_data->app_id_to_launch_list(); + EXPECT_EQ(1u, launch_list.size()); + + // Verify for |kAppId| + const auto launch_list_it = launch_list.find(kAppId); + EXPECT_TRUE(launch_list_it != launch_list.end()); + EXPECT_EQ(2u, launch_list_it->second.size()); + + // Verify for |kId1| + const auto app_restore_data_it1 = launch_list_it->second.find(kId1); + EXPECT_TRUE(app_restore_data_it1 != launch_list_it->second.end()); + + // Verify for |kId2| + const auto app_restore_data_it2 = launch_list_it->second.find(kId2); + EXPECT_TRUE(app_restore_data_it2 != launch_list_it->second.end()); +} + +TEST_F(FullRestoreReadAndSaveTest, MultipleFilePaths) { + FullRestoreSaveHandler* save_handler = FullRestoreSaveHandler::GetInstance(); + base::OneShotTimer* timer = save_handler->GetTimerForTesting(); + + base::ScopedTempDir tmp_dir1; + base::ScopedTempDir tmp_dir2; + ASSERT_TRUE(tmp_dir1.CreateUniqueTempDir()); + ASSERT_TRUE(tmp_dir2.CreateUniqueTempDir()); + + // Add app launch info for |tmp_dir1|, and verity the timer starts. + AddAppLaunchInfo(tmp_dir1.GetPath(), kId1); + EXPECT_TRUE(timer->IsRunning()); + + // Add app launch info for |tmp_dir2|, and verity the timer is still running. + AddAppLaunchInfo(tmp_dir2.GetPath(), kId2); + EXPECT_TRUE(timer->IsRunning()); + + // Simulate timeout, and verity the timer stops. + timer->FireNow(); + task_environment().RunUntilIdle(); + + VerifyRestoreData(tmp_dir1.GetPath(), kId1); + VerifyRestoreData(tmp_dir2.GetPath(), kId2); +} + +} // namespace full_restore
diff --git a/components/full_restore/full_restore_read_handler.cc b/components/full_restore/full_restore_read_handler.cc index 198a812..bd1e814 100644 --- a/components/full_restore/full_restore_read_handler.cc +++ b/components/full_restore/full_restore_read_handler.cc
@@ -25,19 +25,23 @@ FullRestoreReadHandler::~FullRestoreReadHandler() = default; -void FullRestoreReadHandler::ReadFromFile(const base::FilePath& file_path) { - auto file_handler = base::MakeRefCounted<FullRestoreFileHandler>(file_path); +void FullRestoreReadHandler::ReadFromFile(const base::FilePath& profile_path, + Callback callback) { + auto file_handler = + base::MakeRefCounted<FullRestoreFileHandler>(profile_path); file_handler->owning_task_runner()->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&FullRestoreFileHandler::ReadFromFile, file_handler.get()), base::BindOnce(&FullRestoreReadHandler::OnGetRestoreData, - weak_factory_.GetWeakPtr(), file_path)); + weak_factory_.GetWeakPtr(), profile_path, + std::move(callback))); } void FullRestoreReadHandler::OnGetRestoreData( - const base::FilePath& file_path, + const base::FilePath& profile_path, + Callback callback, std::unique_ptr<RestoreData> restore_data) { - // TODO(crbug.com/1146900): Implement the restore_data saving. + std::move(callback).Run(std::move(restore_data)); } } // namespace full_restore
diff --git a/components/full_restore/full_restore_read_handler.h b/components/full_restore/full_restore_read_handler.h index d7e8647a..57572d7 100644 --- a/components/full_restore/full_restore_read_handler.h +++ b/components/full_restore/full_restore_read_handler.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/callback.h" #include "base/component_export.h" #include "base/memory/weak_ptr.h" @@ -25,6 +26,10 @@ // actual reading. class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreReadHandler { public: + // The callback function to get the restore data when the reading operation is + // done. + using Callback = base::OnceCallback<void(std::unique_ptr<RestoreData>)>; + static FullRestoreReadHandler* GetInstance(); FullRestoreReadHandler(); @@ -33,10 +38,15 @@ FullRestoreReadHandler(const FullRestoreReadHandler&) = delete; FullRestoreReadHandler& operator=(const FullRestoreReadHandler&) = delete; - void ReadFromFile(const base::FilePath& profile_dir); + // Reads the restore data from |profile_path| on a background task runner, and + // calls |callback| when the reading operation is done. + void ReadFromFile(const base::FilePath& profile_path, Callback callback); private: - void OnGetRestoreData(const base::FilePath& file_path, + // Invoked when reading the restore data from |profile_path| is finished, and + // calls |callback| to notify that the reading operation is done. + void OnGetRestoreData(const base::FilePath& profile_path, + Callback callback, std::unique_ptr<RestoreData>); base::WeakPtrFactory<FullRestoreReadHandler> weak_factory_{this};
diff --git a/components/full_restore/full_restore_save_handler.cc b/components/full_restore/full_restore_save_handler.cc index 0c1e132..0410d13 100644 --- a/components/full_restore/full_restore_save_handler.cc +++ b/components/full_restore/full_restore_save_handler.cc
@@ -4,6 +4,7 @@ #include "components/full_restore/full_restore_save_handler.h" +#include "ash/public/cpp/app_types.h" #include "base/bind.h" #include "base/files/file_path.h" #include "base/no_destructor.h" @@ -11,7 +12,12 @@ #include "base/time/time.h" #include "components/full_restore/app_launch_info.h" #include "components/full_restore/full_restore_file_handler.h" +#include "components/full_restore/full_restore_utils.h" #include "components/full_restore/restore_data.h" +#include "components/full_restore/window_info.h" +#include "components/sessions/core/session_id.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/aura/window.h" namespace full_restore { @@ -33,22 +39,54 @@ FullRestoreSaveHandler::~FullRestoreSaveHandler() = default; void FullRestoreSaveHandler::SaveAppLaunchInfo( - const base::FilePath& file_path, + const base::FilePath& profile_path, std::unique_ptr<AppLaunchInfo> app_launch_info) { if (!app_launch_info) return; + if (!app_launch_info->id.has_value()) { + // TODO(crbug.com/1146900): Handle ARC app windows. + return; + } + + window_id_to_app_restore_info_[app_launch_info->id.value()] = + std::make_pair(profile_path, app_launch_info->app_id); + // Each user should have one full restore file saving the restore data in the - // profile directory |file_path|. So |app_launch_info| is saved to the restore - // data for the user with the profile path |file_path|. - file_path_to_restore_data_[file_path].AddAppLaunchInfo( + // profile directory |profile_path|. So |app_launch_info| is saved to the + // restore data for the user with |profile_path|. + profile_path_to_restore_data_[profile_path].AddAppLaunchInfo( std::move(app_launch_info)); - should_update_.insert(file_path); + pending_save_profile_paths_.insert(profile_path); MaybeStartSaveTimer(); } +void FullRestoreSaveHandler::SaveWindowInfo(const WindowInfo& window_info) { + if (!window_info.window) + return; + + int32_t window_id = + window_info.window->GetProperty(::full_restore::kWindowIdKey); + + if (window_info.window->GetProperty(aura::client::kAppType) == + static_cast<int>(ash::AppType::ARC_APP)) { + // TODO(crbug.com/1146900): Handle ARC app windows. + return; + } + + if (!SessionID::IsValidValue(window_id)) + return; + + auto it = window_id_to_app_restore_info_.find(window_id); + if (it == window_id_to_app_restore_info_.end()) + return; + + profile_path_to_restore_data_[it->second.first].ModifyWindowInfo( + it->second.second, window_id, window_info); +} + void FullRestoreSaveHandler::MaybeStartSaveTimer() { if (!save_timer_.IsRunning() && save_running_.empty()) { save_timer_.Start(FROM_HERE, kSaveDelay, @@ -58,20 +96,20 @@ } void FullRestoreSaveHandler::Save() { - if (should_update_.empty()) + if (pending_save_profile_paths_.empty()) return; - for (const auto& file_path : should_update_) { + for (const auto& file_path : pending_save_profile_paths_) { save_running_.insert(file_path); BackendTaskRunner(file_path)->PostTaskAndReply( FROM_HERE, base::BindOnce(&FullRestoreFileHandler::WriteToFile, GetFileHandler(file_path), - file_path_to_restore_data_[file_path].Clone()), + profile_path_to_restore_data_[file_path].Clone()), base::BindOnce(&FullRestoreSaveHandler::OnSaveFinished, weak_factory_.GetWeakPtr(), file_path)); } - should_update_.clear(); + pending_save_profile_paths_.clear(); } void FullRestoreSaveHandler::OnSaveFinished(const base::FilePath& file_path) { @@ -80,12 +118,12 @@ FullRestoreFileHandler* FullRestoreSaveHandler::GetFileHandler( const base::FilePath& file_path) { - if (file_path_to_file_handler_.find(file_path) == - file_path_to_file_handler_.end()) { - file_path_to_file_handler_[file_path] = + if (profile_path_to_file_handler_.find(file_path) == + profile_path_to_file_handler_.end()) { + profile_path_to_file_handler_[file_path] = base::MakeRefCounted<FullRestoreFileHandler>(file_path); } - return file_path_to_file_handler_[file_path].get(); + return profile_path_to_file_handler_[file_path].get(); } base::SequencedTaskRunner* FullRestoreSaveHandler::BackendTaskRunner(
diff --git a/components/full_restore/full_restore_save_handler.h b/components/full_restore/full_restore_save_handler.h index b8a730d..4c459d3 100644 --- a/components/full_restore/full_restore_save_handler.h +++ b/components/full_restore/full_restore_save_handler.h
@@ -24,6 +24,7 @@ struct AppLaunchInfo; class FullRestoreFileHandler; class RestoreData; +struct WindowInfo; // FullRestoreSaveHandler is responsible for writing both the app launch // information and the app window information to disk. FullRestoreSaveHandler @@ -41,15 +42,20 @@ FullRestoreSaveHandler(const FullRestoreSaveHandler&) = delete; FullRestoreSaveHandler& operator=(const FullRestoreSaveHandler&) = delete; - // Save |app_launch_info| to the full restore file in |profile_dir|. - void SaveAppLaunchInfo(const base::FilePath& profile_dir, + // Save |app_launch_info| to the full restore file in |profile_path|. + void SaveAppLaunchInfo(const base::FilePath& profile_path, std::unique_ptr<AppLaunchInfo> app_launch_info); + // Save |window_info| to |profile_path_to_restore_data_|. + void SaveWindowInfo(const WindowInfo& window_info); + + base::OneShotTimer* GetTimerForTesting() { return &save_timer_; } + private: // Starts the timer that invokes Save (if timer isn't already running). void MaybeStartSaveTimer(); - // Passes |file_path_to_file_handler_| to the backend for saving. + // Passes |profile_path_to_restore_data_| to the backend for saving. void Save(); // Invoked when write to file operation for |file_path| is finished. @@ -60,16 +66,22 @@ base::SequencedTaskRunner* BackendTaskRunner(const base::FilePath& file_path); // Records whether there are new updates for saving between each saving delay. - // |ShouldUpdate| is cleared when Save is invoked. - std::set<base::FilePath> should_update_; + // |pending_save_profile_paths_| is cleared when Save is invoked. + std::set<base::FilePath> pending_save_profile_paths_; // The restore data for each user's profile. The key is the profile path. - std::map<base::FilePath, RestoreData> file_path_to_restore_data_; + std::map<base::FilePath, RestoreData> profile_path_to_restore_data_; // The file handler for each user's profile to write the restore data to the // full restore file for each user. The key is the profile path. std::map<base::FilePath, scoped_refptr<FullRestoreFileHandler>> - file_path_to_file_handler_; + profile_path_to_file_handler_; + + // The map from the window id to the full restore file path and the app id. + // The window id is saved in the window property. This map is used to find the + // file path and the app id when save the window info. + std::map<int32_t, std::pair<base::FilePath, std::string>> + window_id_to_app_restore_info_; // Timer used to delay the restore data writing to the full restore file. base::OneShotTimer save_timer_;
diff --git a/components/full_restore/full_restore_utils.cc b/components/full_restore/full_restore_utils.cc index 05febd5..a5b017df 100644 --- a/components/full_restore/full_restore_utils.cc +++ b/components/full_restore/full_restore_utils.cc
@@ -14,6 +14,8 @@ namespace full_restore { +DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kWindowIdKey, 0) + void SaveAppLaunchInfo(const base::FilePath& profile_dir, std::unique_ptr<AppLaunchInfo> app_launch_info) { if (!ash::features::IsFullRestoreEnabled() || !app_launch_info) @@ -23,12 +25,11 @@ profile_dir, std::move(app_launch_info)); } -void SaveWindowInfo(std::unique_ptr<WindowInfo> window_info) { +void SaveWindowInfo(const WindowInfo& window_info) { if (!ash::features::IsFullRestoreEnabled()) return; - // TODO(crbug.com/1146900): Save the window information to the full restore - // file. + FullRestoreSaveHandler::GetInstance()->SaveWindowInfo(window_info); } std::unique_ptr<WindowInfo> GetWindowInfo(aura::Window* window) {
diff --git a/components/full_restore/full_restore_utils.h b/components/full_restore/full_restore_utils.h index 8bcdafe7..f92ca52 100644 --- a/components/full_restore/full_restore_utils.h +++ b/components/full_restore/full_restore_utils.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/component_export.h" +#include "ui/base/class_property.h" class AccountId; @@ -24,6 +25,10 @@ struct AppLaunchInfo; struct WindowInfo; +// A property key to indicate the id for the window to be saved in RestoreData. +COMPONENT_EXPORT(FULL_RESTORE) +extern const ui::ClassProperty<int32_t>* const kWindowIdKey; + // Saves the app launch parameters to the full restore file. COMPONENT_EXPORT(FULL_RESTORE) void SaveAppLaunchInfo(const base::FilePath& profile_dir, @@ -31,7 +36,7 @@ // Saves the window information to the full restore file. COMPONENT_EXPORT(FULL_RESTORE) -void SaveWindowInfo(std::unique_ptr<WindowInfo> window_info); +void SaveWindowInfo(const WindowInfo& window_info); // Gets the window information from the full restore file. COMPONENT_EXPORT(FULL_RESTORE)
diff --git a/components/language/core/browser/BUILD.gn b/components/language/core/browser/BUILD.gn index 65741e7..41761e1 100644 --- a/components/language/core/browser/BUILD.gn +++ b/components/language/core/browser/BUILD.gn
@@ -16,6 +16,8 @@ "language_model_manager.h", "language_prefs.cc", "language_prefs.h", + "language_usage_metrics.cc", + "language_usage_metrics.h", "locale_util.cc", "locale_util.h", "pref_names.cc", @@ -43,6 +45,7 @@ "fluent_language_model_unittest.cc", "heuristic_language_model_unittest.cc", "language_prefs_unittest.cc", + "language_usage_metrics_unittest.cc", "url_language_histogram_unittest.cc", ] deps = [
diff --git a/components/language/core/browser/language_usage_metrics.cc b/components/language/core/browser/language_usage_metrics.cc new file mode 100644 index 0000000..1278dd4 --- /dev/null +++ b/components/language/core/browser/language_usage_metrics.cc
@@ -0,0 +1,105 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/language/core/browser/language_usage_metrics.h" + +#include <stddef.h> + +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" +#include "base/strings/string_tokenizer.h" +#include "components/language/core/browser/url_language_histogram.h" + +namespace language { + +// static +void LanguageUsageMetrics::RecordAcceptLanguages( + base::StringPiece accept_languages) { + std::set<int> languages; + ParseAcceptLanguages(accept_languages, &languages); + + UMA_HISTOGRAM_COUNTS_100("LanguageUsage.AcceptLanguage.Count", + languages.size()); + for (int language_code : languages) { + base::UmaHistogramSparse("LanguageUsage.AcceptLanguage", language_code); + } +} + +// static +void LanguageUsageMetrics::RecordPageLanguages( + const language::UrlLanguageHistogram& language_counts) { + const float kMinLanguageFrequency = 0.05; + std::vector<language::UrlLanguageHistogram::LanguageInfo> top_languages = + language_counts.GetTopLanguages(); + + for (const language::UrlLanguageHistogram::LanguageInfo& language_info : + top_languages) { + if (language_info.frequency < kMinLanguageFrequency) { + continue; + } + + const int language_code = ToLanguageCode(language_info.language_code); + if (language_code != 0) { + base::UmaHistogramSparse("LanguageUsage.MostFrequentPageLanguages", + language_code); + } + } +} + +// static +void LanguageUsageMetrics::RecordApplicationLanguage( + base::StringPiece application_locale) { + const int language_code = ToLanguageCode(application_locale); + if (language_code != 0) { + base::UmaHistogramSparse("LanguageUsage.ApplicationLanguage", + language_code); + } +} + +// static +int LanguageUsageMetrics::ToLanguageCode(base::StringPiece locale) { + base::StringPiece language_part = + locale.substr(0U, locale.find_first_of("-_")); + + int language_code = 0; + for (size_t i = 0U; i < language_part.size(); ++i) { + // It's undefined behavior in C++ to left-shift a signed int past its sign + // bit, so only shift until the int's sign bit is reached. Note that it's + // safe to shift up to sizeof(int) times because each character is only + // added if it's between 'a' and 'z', which all have a 0 in their 7th bit. + // For example, for 4-byte ints, "zzzz" would be converted to 0x7A7A7A7A, + // which doesn't quite reach the sign bit, making it safe to insert up to 4 + // characters. + if (i == sizeof(language_code)) + return 0; + + char ch = language_part[i]; + if ('A' <= ch && ch <= 'Z') + ch += ('a' - 'A'); + else if (ch < 'a' || 'z' < ch) + return 0; + + language_code <<= 8; + language_code += ch; + } + + return language_code; +} + +// static +void LanguageUsageMetrics::ParseAcceptLanguages( + base::StringPiece accept_languages, + std::set<int>* languages) { + languages->clear(); + base::CStringTokenizer locales( + accept_languages.data(), + accept_languages.data() + accept_languages.size(), ","); + while (locales.GetNext()) { + const int language_code = ToLanguageCode(locales.token_piece()); + if (language_code != 0) + languages->insert(language_code); + } +} + +} // namespace language
diff --git a/components/language/core/browser/language_usage_metrics.h b/components/language/core/browser/language_usage_metrics.h new file mode 100644 index 0000000..b6bf73c3 --- /dev/null +++ b/components/language/core/browser/language_usage_metrics.h
@@ -0,0 +1,62 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_LANGUAGE_CORE_BROWSER_LANGUAGE_USAGE_METRICS_H_ +#define COMPONENTS_LANGUAGE_CORE_BROWSER_LANGUAGE_USAGE_METRICS_H_ + +#include <set> + +#include "base/gtest_prod_util.h" +#include "base/macros.h" +#include "base/strings/string_piece.h" + +namespace language { +class UrlLanguageHistogram; + +// Methods to record language usage as UMA histograms. +class LanguageUsageMetrics { + public: + // Records accept languages as a UMA histogram. |accept_languages| is a + // case-insensitive comma-separated list of languages/locales of either xx, + // xx-YY, or xx_YY format where xx is iso-639 language code and YY is iso-3166 + // country code. Country code is ignored. That is, xx and XX-YY are considered + // identical and recorded once. + static void RecordAcceptLanguages(base::StringPiece accept_languages); + + // Records detected page language history as a UMA histogram. + // |UrlLanguageHistogram| is a mapping of page language to frequency. Country + // codes are ignored for page language. Each language is counted once + // regardless of frequency. Languages with a frequency below 0.05 are ignored. + static void RecordPageLanguages( + const language::UrlLanguageHistogram& language_counts); + + // Records the application language as a UMA histogram. |application_locale| + // is a case-insensitive locale string of either xx, xx-YY, or xx_YY format. + // Only the language part (xx in the example) is considered. + static void RecordApplicationLanguage(base::StringPiece application_locale); + + // Parses |locale| and returns the language code. Returns 0 in case of errors. + // The language code is calculated from two alphabets. For example, if + // |locale| is 'en' which represents 'English', the codes of 'e' and 'n' are + // 101 and 110 respectively, and the language code will be 101 * 256 + 100 = + // 25966. + // |locale| is case-insensitive, such that "EN" will return the same language + // code as "en". This function doesn't check whether |locale| is valid locale + // or not. + static int ToLanguageCode(base::StringPiece locale); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(LanguageUsageMetrics); + + // Parses |accept_languages| and returns a set of language codes in + // |languages|. + static void ParseAcceptLanguages(base::StringPiece accept_languages, + std::set<int>* languages); + + FRIEND_TEST_ALL_PREFIXES(LanguageUsageMetricsTest, ParseAcceptLanguages); +}; + +} // namespace language + +#endif // COMPONENTS_LANGUAGE_CORE_BROWSER_LANGUAGE_USAGE_METRICS_H_
diff --git a/components/language/core/browser/language_usage_metrics_unittest.cc b/components/language/core/browser/language_usage_metrics_unittest.cc new file mode 100644 index 0000000..29ab506 --- /dev/null +++ b/components/language/core/browser/language_usage_metrics_unittest.cc
@@ -0,0 +1,285 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/language/core/browser/language_usage_metrics.h" + +#include "base/macros.h" +#include "base/metrics/histogram.h" +#include "base/metrics/histogram_samples.h" +#include "base/metrics/statistics_recorder.h" +#include "components/language/core/browser/url_language_histogram.h" +#include "components/prefs/testing_pref_service.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::HistogramBase; +using base::HistogramSamples; +using base::SampleCountIterator; +using base::StatisticsRecorder; +using language::UrlLanguageHistogram; + +namespace language { + +namespace { + +class MetricsRecorder { + public: + explicit MetricsRecorder(const char* key) : key_(key) { + HistogramBase* histogram = StatisticsRecorder::FindHistogram(key_); + if (histogram) + base_samples_ = histogram->SnapshotSamples(); + } + + void CheckTotalCount(int count) { + Snapshot(); + EXPECT_EQ(count, GetTotalCount()); + } + + void CheckValueCount(HistogramBase::Sample value, int count) { + Snapshot(); + EXPECT_EQ(count, GetCountWithoutSnapshot(value)); + } + + private: + void Snapshot() { + HistogramBase* histogram = StatisticsRecorder::FindHistogram(key_); + if (!histogram) + return; + samples_ = histogram->SnapshotSamples(); + } + + HistogramBase::Count GetCountWithoutSnapshot(HistogramBase::Sample value) { + if (!samples_) + return 0; + HistogramBase::Count count = samples_->GetCount(value); + if (!base_samples_) + return count; + return count - base_samples_->GetCount(value); + } + + HistogramBase::Count GetTotalCount() { + if (!samples_) + return 0; + HistogramBase::Count count = samples_->TotalCount(); + if (!base_samples_) + return count; + return count - base_samples_->TotalCount(); + } + + std::string key_; + std::unique_ptr<HistogramSamples> base_samples_; + std::unique_ptr<HistogramSamples> samples_; + + DISALLOW_COPY_AND_ASSIGN(MetricsRecorder); +}; + +void RecordPageLanguageVisits(UrlLanguageHistogram& language_histogram, + std::string language, + int count) { + for (int i = 0; i < count; i++) { + language_histogram.OnPageVisited(language); + } +} + +struct LanguageCodeHash { + LanguageCodeHash() = default; + LanguageCodeHash(const std::string& code, int hash) + : code(code), hash(hash) {} + std::string code; + int hash; +}; + +} // namespace + +TEST(LanguageUsageMetricsTest, RecordPageLanguageCounts) { + const LanguageCodeHash EN("en", 25966); + const LanguageCodeHash ES("es", 25971); + const LanguageCodeHash JP("ja", 27233); + + TestingPrefServiceSimple prefs; + UrlLanguageHistogram::RegisterProfilePrefs(prefs.registry()); + UrlLanguageHistogram url_hist(&prefs); + + // Initialize recorder + MetricsRecorder recorder("LanguageUsage.MostFrequentPageLanguages"); + recorder.CheckTotalCount(0); + + // Check that nothing is recorded if less than 10 page visits. + RecordPageLanguageVisits(url_hist, EN.code, 8); + RecordPageLanguageVisits(url_hist, ES.code, 1); + LanguageUsageMetrics::RecordPageLanguages(url_hist); + recorder.CheckTotalCount(0); + + // Check that recording works at 10 page visits. + RecordPageLanguageVisits(url_hist, EN.code, 1); + LanguageUsageMetrics::RecordPageLanguages(url_hist); + recorder.CheckTotalCount(2); + recorder.CheckValueCount(EN.hash, 1); + recorder.CheckValueCount(ES.hash, 1); + + // Check that languages with frequency below 0.05 are not recorded. + RecordPageLanguageVisits(url_hist, EN.code, 28); // 37/40 + RecordPageLanguageVisits(url_hist, ES.code, 1); // 2/40 -> exactly 0.05 + RecordPageLanguageVisits(url_hist, JP.code, 1); // 1/40 -> below 0.05 + LanguageUsageMetrics::RecordPageLanguages(url_hist); + recorder.CheckTotalCount(4); + recorder.CheckValueCount(EN.hash, 2); + recorder.CheckValueCount(ES.hash, 2); + recorder.CheckValueCount(JP.hash, 0); +} + +TEST(LanguageUsageMetricsTest, RecordAcceptLanguages) { + const LanguageCodeHash EN("en", 25966); + const LanguageCodeHash ES("es", 25971); + const LanguageCodeHash JP("ja", 27233); + + // Initialize recorders + MetricsRecorder recorder("LanguageUsage.AcceptLanguage"); + MetricsRecorder recorder_count("LanguageUsage.AcceptLanguage.Count"); + recorder.CheckTotalCount(0); + recorder_count.CheckTotalCount(0); + + LanguageUsageMetrics::RecordAcceptLanguages("en"); + LanguageUsageMetrics::RecordAcceptLanguages("en"); + recorder.CheckTotalCount(2); + recorder.CheckValueCount(EN.hash, 2); + recorder_count.CheckTotalCount(2); + recorder_count.CheckValueCount(1, 2); + + LanguageUsageMetrics::RecordAcceptLanguages("en,es"); + recorder.CheckTotalCount(4); + recorder.CheckValueCount(EN.hash, 3); + recorder.CheckValueCount(ES.hash, 1); + recorder_count.CheckTotalCount(3); + recorder_count.CheckValueCount(1, 2); + recorder_count.CheckValueCount(2, 1); + + LanguageUsageMetrics::RecordAcceptLanguages("en,es,ja-JP"); + recorder.CheckTotalCount(7); + recorder.CheckTotalCount(7); + recorder.CheckValueCount(EN.hash, 4); + recorder.CheckValueCount(ES.hash, 2); + recorder.CheckValueCount(JP.hash, 1); + recorder_count.CheckTotalCount(4); + recorder_count.CheckValueCount(1, 2); + recorder_count.CheckValueCount(2, 1); + recorder_count.CheckValueCount(3, 1); +} + +TEST(LanguageUsageMetricsTest, RecordApplicationLanguage) { + const LanguageCodeHash EN("en", 25966); + const LanguageCodeHash ES("es", 25971); + + // Initialize recorder + MetricsRecorder recorder("LanguageUsage.ApplicationLanguage"); + + LanguageUsageMetrics::RecordApplicationLanguage("en"); + LanguageUsageMetrics::RecordApplicationLanguage("en-US"); + LanguageUsageMetrics::RecordApplicationLanguage("en-UK"); + recorder.CheckTotalCount(3); + recorder.CheckValueCount(EN.hash, 3); + + LanguageUsageMetrics::RecordApplicationLanguage("es"); + LanguageUsageMetrics::RecordApplicationLanguage("es-ES"); + LanguageUsageMetrics::RecordApplicationLanguage("es-419"); + recorder.CheckTotalCount(6); + recorder.CheckValueCount(ES.hash, 3); +} + +TEST(LanguageUsageMetricsTest, ParseAcceptLanguages) { + std::set<int> language_set; + std::set<int>::const_iterator it; + + const int ENGLISH = 25966; + const int SPANISH = 25971; + const int JAPANESE = 27233; + + // Basic single language case. + LanguageUsageMetrics::ParseAcceptLanguages("ja", &language_set); + EXPECT_EQ(1U, language_set.size()); + EXPECT_EQ(JAPANESE, *language_set.begin()); + + // Empty language. + LanguageUsageMetrics::ParseAcceptLanguages(std::string(), &language_set); + EXPECT_EQ(0U, language_set.size()); + + // Country code is ignored. + LanguageUsageMetrics::ParseAcceptLanguages("ja-JP", &language_set); + EXPECT_EQ(1U, language_set.size()); + EXPECT_EQ(JAPANESE, *language_set.begin()); + + // Case is ignored. + LanguageUsageMetrics::ParseAcceptLanguages("Ja-jP", &language_set); + EXPECT_EQ(1U, language_set.size()); + EXPECT_EQ(JAPANESE, *language_set.begin()); + + // Underscore as the separator. + LanguageUsageMetrics::ParseAcceptLanguages("ja_JP", &language_set); + EXPECT_EQ(1U, language_set.size()); + EXPECT_EQ(JAPANESE, *language_set.begin()); + + // The result contains a same language code only once. + LanguageUsageMetrics::ParseAcceptLanguages("ja-JP,ja", &language_set); + EXPECT_EQ(1U, language_set.size()); + EXPECT_EQ(JAPANESE, *language_set.begin()); + + // Basic two languages case. + LanguageUsageMetrics::ParseAcceptLanguages("en,ja", &language_set); + EXPECT_EQ(2U, language_set.size()); + it = language_set.begin(); + EXPECT_EQ(ENGLISH, *it); + EXPECT_EQ(JAPANESE, *++it); + + // Multiple languages. + LanguageUsageMetrics::ParseAcceptLanguages("ja-JP,en,es,ja,en-US", + &language_set); + EXPECT_EQ(3U, language_set.size()); + it = language_set.begin(); + EXPECT_EQ(ENGLISH, *it); + EXPECT_EQ(SPANISH, *++it); + EXPECT_EQ(JAPANESE, *++it); + + // Two empty languages. + LanguageUsageMetrics::ParseAcceptLanguages(",", &language_set); + EXPECT_EQ(0U, language_set.size()); + + // Trailing comma. + LanguageUsageMetrics::ParseAcceptLanguages("ja,", &language_set); + EXPECT_EQ(1U, language_set.size()); + EXPECT_EQ(JAPANESE, *language_set.begin()); + + // Leading comma. + LanguageUsageMetrics::ParseAcceptLanguages(",es", &language_set); + EXPECT_EQ(1U, language_set.size()); + EXPECT_EQ(SPANISH, *language_set.begin()); + + // Combination of invalid and valid. + LanguageUsageMetrics::ParseAcceptLanguages("1234,en", &language_set); + EXPECT_EQ(1U, language_set.size()); + it = language_set.begin(); + EXPECT_EQ(ENGLISH, *it); +} + +TEST(LanguageUsageMetricsTest, ToLanguageCode) { + const int SPANISH = 25971; + const int JAPANESE = 27233; + + // Basic case. + EXPECT_EQ(JAPANESE, LanguageUsageMetrics::ToLanguageCode("ja")); + + // Case is ignored. + EXPECT_EQ(SPANISH, LanguageUsageMetrics::ToLanguageCode("Es")); + + // Coutry code is ignored. + EXPECT_EQ(JAPANESE, LanguageUsageMetrics::ToLanguageCode("ja-JP")); + + // Invalid locales are considered as unknown language. + EXPECT_EQ(0, LanguageUsageMetrics::ToLanguageCode(std::string())); + EXPECT_EQ(0, LanguageUsageMetrics::ToLanguageCode("1234")); + + // "xx" is not acceptable because it doesn't exist in ISO 639-1 table. + // However, LanguageUsageMetrics doesn't tell what code is valid. + EXPECT_EQ(30840, LanguageUsageMetrics::ToLanguageCode("xx")); +} + +} // namespace language
diff --git a/components/language_usage_metrics/BUILD.gn b/components/language_usage_metrics/BUILD.gn deleted file mode 100644 index 26155ef..0000000 --- a/components/language_usage_metrics/BUILD.gn +++ /dev/null
@@ -1,28 +0,0 @@ -# Copyright 2014 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. - -static_library("language_usage_metrics") { - sources = [ - "language_usage_metrics.cc", - "language_usage_metrics.h", - ] - - deps = [ - "//base", - "//components/language/core/browser:browser", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ "language_usage_metrics_unittest.cc" ] - - deps = [ - ":language_usage_metrics", - "//base", - "//components/language/core/browser:browser", - "//components/prefs:test_support", - "//testing/gtest", - ] -}
diff --git a/components/language_usage_metrics/DEPS b/components/language_usage_metrics/DEPS deleted file mode 100644 index 27895b9..0000000 --- a/components/language_usage_metrics/DEPS +++ /dev/null
@@ -1,9 +0,0 @@ -include_rules = [ - "+components/language", -] - -specific_include_rules = { - ".*unittest.cc": [ - "+components/prefs", - ], -}
diff --git a/components/language_usage_metrics/DIR_METADATA b/components/language_usage_metrics/DIR_METADATA deleted file mode 100644 index 3c135cd..0000000 --- a/components/language_usage_metrics/DIR_METADATA +++ /dev/null
@@ -1,3 +0,0 @@ -monorail { - component: "UI>Browser>Language" -}
diff --git a/components/language_usage_metrics/OWNERS b/components/language_usage_metrics/OWNERS deleted file mode 100644 index bb5c3afc..0000000 --- a/components/language_usage_metrics/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://components/translate/OWNERS
diff --git a/components/language_usage_metrics/language_usage_metrics.cc b/components/language_usage_metrics/language_usage_metrics.cc deleted file mode 100644 index 4f9dd2f..0000000 --- a/components/language_usage_metrics/language_usage_metrics.cc +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/language_usage_metrics/language_usage_metrics.h" - -#include <stddef.h> - -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/string_tokenizer.h" -#include "components/language/core/browser/url_language_histogram.h" - -namespace language_usage_metrics { - -// static -void LanguageUsageMetrics::RecordAcceptLanguages( - base::StringPiece accept_languages) { - std::set<int> languages; - ParseAcceptLanguages(accept_languages, &languages); - - UMA_HISTOGRAM_COUNTS_100("LanguageUsage.AcceptLanguage.Count", - languages.size()); - for (int language_code : languages) { - base::UmaHistogramSparse("LanguageUsage.AcceptLanguage", language_code); - } -} - -// static -void LanguageUsageMetrics::RecordPageLanguages( - const language::UrlLanguageHistogram& language_counts) { - const float kMinLanguageFrequency = 0.05; - std::vector<language::UrlLanguageHistogram::LanguageInfo> top_languages = - language_counts.GetTopLanguages(); - - for (const language::UrlLanguageHistogram::LanguageInfo& language_info : - top_languages) { - if (language_info.frequency < kMinLanguageFrequency) { - continue; - } - - const int language_code = ToLanguageCode(language_info.language_code); - if (language_code != 0) { - base::UmaHistogramSparse("LanguageUsage.MostFrequentPageLanguages", - language_code); - } - } -} - -// static -void LanguageUsageMetrics::RecordApplicationLanguage( - base::StringPiece application_locale) { - const int language_code = ToLanguageCode(application_locale); - if (language_code != 0) { - base::UmaHistogramSparse("LanguageUsage.ApplicationLanguage", - language_code); - } -} - -// static -int LanguageUsageMetrics::ToLanguageCode(base::StringPiece locale) { - base::StringPiece language_part = - locale.substr(0U, locale.find_first_of("-_")); - - int language_code = 0; - for (size_t i = 0U; i < language_part.size(); ++i) { - // It's undefined behavior in C++ to left-shift a signed int past its sign - // bit, so only shift until the int's sign bit is reached. Note that it's - // safe to shift up to sizeof(int) times because each character is only - // added if it's between 'a' and 'z', which all have a 0 in their 7th bit. - // For example, for 4-byte ints, "zzzz" would be converted to 0x7A7A7A7A, - // which doesn't quite reach the sign bit, making it safe to insert up to 4 - // characters. - if (i == sizeof(language_code)) - return 0; - - char ch = language_part[i]; - if ('A' <= ch && ch <= 'Z') - ch += ('a' - 'A'); - else if (ch < 'a' || 'z' < ch) - return 0; - - language_code <<= 8; - language_code += ch; - } - - return language_code; -} - -// static -void LanguageUsageMetrics::ParseAcceptLanguages( - base::StringPiece accept_languages, - std::set<int>* languages) { - languages->clear(); - base::CStringTokenizer locales( - accept_languages.data(), - accept_languages.data() + accept_languages.size(), ","); - while (locales.GetNext()) { - const int language_code = ToLanguageCode(locales.token_piece()); - if (language_code != 0) - languages->insert(language_code); - } -} - -} // namespace language_usage_metrics
diff --git a/components/language_usage_metrics/language_usage_metrics.h b/components/language_usage_metrics/language_usage_metrics.h deleted file mode 100644 index f350bec..0000000 --- a/components/language_usage_metrics/language_usage_metrics.h +++ /dev/null
@@ -1,65 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_LANGUAGE_USAGE_METRICS_LANGUAGE_USAGE_METRICS_H_ -#define COMPONENTS_LANGUAGE_USAGE_METRICS_LANGUAGE_USAGE_METRICS_H_ - -#include <set> - -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/strings/string_piece.h" - -namespace language { -class UrlLanguageHistogram; -} - -namespace language_usage_metrics { - -// Methods to record language usage as UMA histograms. -class LanguageUsageMetrics { - public: - // Records accept languages as a UMA histogram. |accept_languages| is a - // case-insensitive comma-separated list of languages/locales of either xx, - // xx-YY, or xx_YY format where xx is iso-639 language code and YY is iso-3166 - // country code. Country code is ignored. That is, xx and XX-YY are considered - // identical and recorded once. - static void RecordAcceptLanguages(base::StringPiece accept_languages); - - // Records detected page language history as a UMA histogram. - // |UrlLanguageHistogram| is a mapping of page language to frequency. Country - // codes are ignored for page language. Each language is counted once - // regardless of frequency. Languages with a frequency below 0.05 are ignored. - static void RecordPageLanguages( - const language::UrlLanguageHistogram& language_counts); - - // Records the application language as a UMA histogram. |application_locale| - // is a case-insensitive locale string of either xx, xx-YY, or xx_YY format. - // Only the language part (xx in the example) is considered. - static void RecordApplicationLanguage(base::StringPiece application_locale); - - // Parses |locale| and returns the language code. Returns 0 in case of errors. - // The language code is calculated from two alphabets. For example, if - // |locale| is 'en' which represents 'English', the codes of 'e' and 'n' are - // 101 and 110 respectively, and the language code will be 101 * 256 + 100 = - // 25966. - // |locale| is case-insensitive, such that "EN" will return the same language - // code as "en". This function doesn't check whether |locale| is valid locale - // or not. - static int ToLanguageCode(base::StringPiece locale); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(LanguageUsageMetrics); - - // Parses |accept_languages| and returns a set of language codes in - // |languages|. - static void ParseAcceptLanguages(base::StringPiece accept_languages, - std::set<int>* languages); - - FRIEND_TEST_ALL_PREFIXES(LanguageUsageMetricsTest, ParseAcceptLanguages); -}; - -} // namespace language_usage_metrics - -#endif // COMPONENTS_LANGUAGE_USAGE_METRICS_LANGUAGE_USAGE_METRICS_H_
diff --git a/components/language_usage_metrics/language_usage_metrics_unittest.cc b/components/language_usage_metrics/language_usage_metrics_unittest.cc deleted file mode 100644 index 03195fc1..0000000 --- a/components/language_usage_metrics/language_usage_metrics_unittest.cc +++ /dev/null
@@ -1,285 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/language_usage_metrics/language_usage_metrics.h" - -#include "base/macros.h" -#include "base/metrics/histogram.h" -#include "base/metrics/histogram_samples.h" -#include "base/metrics/statistics_recorder.h" -#include "components/language/core/browser/url_language_histogram.h" -#include "components/prefs/testing_pref_service.h" -#include "testing/gtest/include/gtest/gtest.h" - -using base::HistogramBase; -using base::HistogramSamples; -using base::SampleCountIterator; -using base::StatisticsRecorder; -using language::UrlLanguageHistogram; - -namespace language_usage_metrics { - -namespace { - -class MetricsRecorder { - public: - explicit MetricsRecorder(const char* key) : key_(key) { - HistogramBase* histogram = StatisticsRecorder::FindHistogram(key_); - if (histogram) - base_samples_ = histogram->SnapshotSamples(); - } - - void CheckTotalCount(int count) { - Snapshot(); - EXPECT_EQ(count, GetTotalCount()); - } - - void CheckValueCount(HistogramBase::Sample value, int count) { - Snapshot(); - EXPECT_EQ(count, GetCountWithoutSnapshot(value)); - } - - private: - void Snapshot() { - HistogramBase* histogram = StatisticsRecorder::FindHistogram(key_); - if (!histogram) - return; - samples_ = histogram->SnapshotSamples(); - } - - HistogramBase::Count GetCountWithoutSnapshot(HistogramBase::Sample value) { - if (!samples_) - return 0; - HistogramBase::Count count = samples_->GetCount(value); - if (!base_samples_) - return count; - return count - base_samples_->GetCount(value); - } - - HistogramBase::Count GetTotalCount() { - if (!samples_) - return 0; - HistogramBase::Count count = samples_->TotalCount(); - if (!base_samples_) - return count; - return count - base_samples_->TotalCount(); - } - - std::string key_; - std::unique_ptr<HistogramSamples> base_samples_; - std::unique_ptr<HistogramSamples> samples_; - - DISALLOW_COPY_AND_ASSIGN(MetricsRecorder); -}; - -void RecordPageLanguageVisits(UrlLanguageHistogram& language_histogram, - std::string language, - int count) { - for (int i = 0; i < count; i++) { - language_histogram.OnPageVisited(language); - } -} - -struct LanguageCodeHash { - LanguageCodeHash() = default; - LanguageCodeHash(const std::string& code, int hash) - : code(code), hash(hash) {} - std::string code; - int hash; -}; - -} // namespace - -TEST(LanguageUsageMetricsTest, RecordPageLanguageCounts) { - const LanguageCodeHash EN("en", 25966); - const LanguageCodeHash ES("es", 25971); - const LanguageCodeHash JP("ja", 27233); - - TestingPrefServiceSimple prefs; - UrlLanguageHistogram::RegisterProfilePrefs(prefs.registry()); - UrlLanguageHistogram url_hist(&prefs); - - // Initialize recorder - MetricsRecorder recorder("LanguageUsage.MostFrequentPageLanguages"); - recorder.CheckTotalCount(0); - - // Check that nothing is recorded if less than 10 page visits. - RecordPageLanguageVisits(url_hist, EN.code, 8); - RecordPageLanguageVisits(url_hist, ES.code, 1); - LanguageUsageMetrics::RecordPageLanguages(url_hist); - recorder.CheckTotalCount(0); - - // Check that recording works at 10 page visits. - RecordPageLanguageVisits(url_hist, EN.code, 1); - LanguageUsageMetrics::RecordPageLanguages(url_hist); - recorder.CheckTotalCount(2); - recorder.CheckValueCount(EN.hash, 1); - recorder.CheckValueCount(ES.hash, 1); - - // Check that languages with frequency below 0.05 are not recorded. - RecordPageLanguageVisits(url_hist, EN.code, 28); // 37/40 - RecordPageLanguageVisits(url_hist, ES.code, 1); // 2/40 -> exactly 0.05 - RecordPageLanguageVisits(url_hist, JP.code, 1); // 1/40 -> below 0.05 - LanguageUsageMetrics::RecordPageLanguages(url_hist); - recorder.CheckTotalCount(4); - recorder.CheckValueCount(EN.hash, 2); - recorder.CheckValueCount(ES.hash, 2); - recorder.CheckValueCount(JP.hash, 0); -} - -TEST(LanguageUsageMetricsTest, RecordAcceptLanguages) { - const LanguageCodeHash EN("en", 25966); - const LanguageCodeHash ES("es", 25971); - const LanguageCodeHash JP("ja", 27233); - - // Initialize recorders - MetricsRecorder recorder("LanguageUsage.AcceptLanguage"); - MetricsRecorder recorder_count("LanguageUsage.AcceptLanguage.Count"); - recorder.CheckTotalCount(0); - recorder_count.CheckTotalCount(0); - - LanguageUsageMetrics::RecordAcceptLanguages("en"); - LanguageUsageMetrics::RecordAcceptLanguages("en"); - recorder.CheckTotalCount(2); - recorder.CheckValueCount(EN.hash, 2); - recorder_count.CheckTotalCount(2); - recorder_count.CheckValueCount(1, 2); - - LanguageUsageMetrics::RecordAcceptLanguages("en,es"); - recorder.CheckTotalCount(4); - recorder.CheckValueCount(EN.hash, 3); - recorder.CheckValueCount(ES.hash, 1); - recorder_count.CheckTotalCount(3); - recorder_count.CheckValueCount(1, 2); - recorder_count.CheckValueCount(2, 1); - - LanguageUsageMetrics::RecordAcceptLanguages("en,es,ja-JP"); - recorder.CheckTotalCount(7); - recorder.CheckTotalCount(7); - recorder.CheckValueCount(EN.hash, 4); - recorder.CheckValueCount(ES.hash, 2); - recorder.CheckValueCount(JP.hash, 1); - recorder_count.CheckTotalCount(4); - recorder_count.CheckValueCount(1, 2); - recorder_count.CheckValueCount(2, 1); - recorder_count.CheckValueCount(3, 1); -} - -TEST(LanguageUsageMetricsTest, RecordApplicationLanguage) { - const LanguageCodeHash EN("en", 25966); - const LanguageCodeHash ES("es", 25971); - - // Initialize recorder - MetricsRecorder recorder("LanguageUsage.ApplicationLanguage"); - - LanguageUsageMetrics::RecordApplicationLanguage("en"); - LanguageUsageMetrics::RecordApplicationLanguage("en-US"); - LanguageUsageMetrics::RecordApplicationLanguage("en-UK"); - recorder.CheckTotalCount(3); - recorder.CheckValueCount(EN.hash, 3); - - LanguageUsageMetrics::RecordApplicationLanguage("es"); - LanguageUsageMetrics::RecordApplicationLanguage("es-ES"); - LanguageUsageMetrics::RecordApplicationLanguage("es-419"); - recorder.CheckTotalCount(6); - recorder.CheckValueCount(ES.hash, 3); -} - -TEST(LanguageUsageMetricsTest, ParseAcceptLanguages) { - std::set<int> language_set; - std::set<int>::const_iterator it; - - const int ENGLISH = 25966; - const int SPANISH = 25971; - const int JAPANESE = 27233; - - // Basic single language case. - LanguageUsageMetrics::ParseAcceptLanguages("ja", &language_set); - EXPECT_EQ(1U, language_set.size()); - EXPECT_EQ(JAPANESE, *language_set.begin()); - - // Empty language. - LanguageUsageMetrics::ParseAcceptLanguages(std::string(), &language_set); - EXPECT_EQ(0U, language_set.size()); - - // Country code is ignored. - LanguageUsageMetrics::ParseAcceptLanguages("ja-JP", &language_set); - EXPECT_EQ(1U, language_set.size()); - EXPECT_EQ(JAPANESE, *language_set.begin()); - - // Case is ignored. - LanguageUsageMetrics::ParseAcceptLanguages("Ja-jP", &language_set); - EXPECT_EQ(1U, language_set.size()); - EXPECT_EQ(JAPANESE, *language_set.begin()); - - // Underscore as the separator. - LanguageUsageMetrics::ParseAcceptLanguages("ja_JP", &language_set); - EXPECT_EQ(1U, language_set.size()); - EXPECT_EQ(JAPANESE, *language_set.begin()); - - // The result contains a same language code only once. - LanguageUsageMetrics::ParseAcceptLanguages("ja-JP,ja", &language_set); - EXPECT_EQ(1U, language_set.size()); - EXPECT_EQ(JAPANESE, *language_set.begin()); - - // Basic two languages case. - LanguageUsageMetrics::ParseAcceptLanguages("en,ja", &language_set); - EXPECT_EQ(2U, language_set.size()); - it = language_set.begin(); - EXPECT_EQ(ENGLISH, *it); - EXPECT_EQ(JAPANESE, *++it); - - // Multiple languages. - LanguageUsageMetrics::ParseAcceptLanguages("ja-JP,en,es,ja,en-US", - &language_set); - EXPECT_EQ(3U, language_set.size()); - it = language_set.begin(); - EXPECT_EQ(ENGLISH, *it); - EXPECT_EQ(SPANISH, *++it); - EXPECT_EQ(JAPANESE, *++it); - - // Two empty languages. - LanguageUsageMetrics::ParseAcceptLanguages(",", &language_set); - EXPECT_EQ(0U, language_set.size()); - - // Trailing comma. - LanguageUsageMetrics::ParseAcceptLanguages("ja,", &language_set); - EXPECT_EQ(1U, language_set.size()); - EXPECT_EQ(JAPANESE, *language_set.begin()); - - // Leading comma. - LanguageUsageMetrics::ParseAcceptLanguages(",es", &language_set); - EXPECT_EQ(1U, language_set.size()); - EXPECT_EQ(SPANISH, *language_set.begin()); - - // Combination of invalid and valid. - LanguageUsageMetrics::ParseAcceptLanguages("1234,en", &language_set); - EXPECT_EQ(1U, language_set.size()); - it = language_set.begin(); - EXPECT_EQ(ENGLISH, *it); -} - -TEST(LanguageUsageMetricsTest, ToLanguageCode) { - const int SPANISH = 25971; - const int JAPANESE = 27233; - - // Basic case. - EXPECT_EQ(JAPANESE, LanguageUsageMetrics::ToLanguageCode("ja")); - - // Case is ignored. - EXPECT_EQ(SPANISH, LanguageUsageMetrics::ToLanguageCode("Es")); - - // Coutry code is ignored. - EXPECT_EQ(JAPANESE, LanguageUsageMetrics::ToLanguageCode("ja-JP")); - - // Invalid locales are considered as unknown language. - EXPECT_EQ(0, LanguageUsageMetrics::ToLanguageCode(std::string())); - EXPECT_EQ(0, LanguageUsageMetrics::ToLanguageCode("1234")); - - // "xx" is not acceptable because it doesn't exist in ISO 639-1 table. - // However, LanguageUsageMetrics doesn't tell what code is valid. - EXPECT_EQ(30840, LanguageUsageMetrics::ToLanguageCode("xx")); -} - -} // namespace language_usage_metrics
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc index e021b278..28f6f29 100644 --- a/components/omnibox/browser/omnibox_edit_model.cc +++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -61,29 +61,9 @@ namespace { -// Histogram name which counts the number of times that the user text is -// cleared. IME users are sometimes in the situation that IME was -// unintentionally turned on and failed to input latin alphabets (ASCII -// characters) or the opposite case. In that case, users may delete all -// the text and the user text gets cleared. We'd like to measure how often -// this scenario happens. -// -// Note that since we don't currently correlate "text cleared" events with -// IME usage, this also captures many other cases where users clear the text; -// though it explicitly doesn't log deleting all the permanent text as -// the first action of an editing sequence (see comments in -// OnAfterPossibleChange()). -const char kOmniboxUserTextClearedHistogram[] = "Omnibox.UserTextCleared"; - const char kOmniboxFocusResultedInNavigation[] = "Omnibox.FocusResultedInNavigation"; -enum UserTextClearedType { - OMNIBOX_USER_TEXT_CLEARED_BY_EDITING = 0, - OMNIBOX_USER_TEXT_CLEARED_WITH_ESCAPE = 1, - OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS, -}; - // Histogram name which counts the number of times the user enters // keyword hint mode and via what method. The possible values are listed // in the metrics OmniboxEnteredKeywordMode2 enum which is defined in metrics @@ -1222,12 +1202,6 @@ view_->Update(); } - if (!user_text_.empty()) { - UMA_HISTOGRAM_ENUMERATION(kOmniboxUserTextClearedHistogram, - OMNIBOX_USER_TEXT_CLEARED_WITH_ESCAPE, - OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS); - } - // Unconditionally revert/select all. This ensures any popup, whether due to // normal editing or ZeroSuggest, is closed, and the full text is selected. // This in turn allows the user to use escape to quickly select all the text @@ -1491,16 +1465,6 @@ has_temporary_text_ = false; just_deleted_text_ = state_changes.just_deleted_text; - if (user_input_in_progress_ && user_text_.empty()) { - // Log cases where the user started editing and then subsequently cleared - // all the text. Note that this explicitly doesn't catch cases like - // "hit ctrl-l to select whole edit contents, then hit backspace", because - // in such cases, |user_input_in_progress| won't be true here. - UMA_HISTOGRAM_ENUMERATION(kOmniboxUserTextClearedHistogram, - OMNIBOX_USER_TEXT_CLEARED_BY_EDITING, - OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS); - } - const bool no_selection = state_changes.new_sel_start == state_changes.new_sel_end;
diff --git a/components/optimization_guide/hints_fetcher.cc b/components/optimization_guide/hints_fetcher.cc index cf3810aa..344bc14e 100644 --- a/components/optimization_guide/hints_fetcher.cc +++ b/components/optimization_guide/hints_fetcher.cc
@@ -19,13 +19,13 @@ #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/variations/net/variations_http_headers.h" -#include "content/public/browser/network_service_instance.h" #include "net/base/load_flags.h" #include "net/base/url_util.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/simple_url_loader.h" @@ -81,12 +81,14 @@ HintsFetcher::HintsFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& optimization_guide_service_url, - PrefService* pref_service) + PrefService* pref_service, + network::NetworkConnectionTracker* network_connection_tracker) : optimization_guide_service_url_(net::AppendOrReplaceQueryParameter( optimization_guide_service_url, "key", features::GetOptimizationGuideServiceAPIKey())), pref_service_(pref_service), + network_connection_tracker_(network_connection_tracker), time_clock_(base::DefaultClock::GetInstance()) { url_loader_factory_ = std::move(url_loader_factory); CHECK(optimization_guide_service_url_.SchemeIs(url::kHttpsScheme)); @@ -154,7 +156,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_GT(optimization_types.size(), 0u); - if (content::GetNetworkConnectionTracker()->IsOffline()) { + if (network_connection_tracker_->IsOffline()) { RecordRequestStatusHistogram(request_context, HintsFetcherRequestStatus::kNetworkOffline); std::move(hints_fetched_callback).Run(base::nullopt);
diff --git a/components/optimization_guide/hints_fetcher.h b/components/optimization_guide/hints_fetcher.h index bc56f79..93d1bbc8 100644 --- a/components/optimization_guide/hints_fetcher.h +++ b/components/optimization_guide/hints_fetcher.h
@@ -23,6 +23,7 @@ class PrefService; namespace network { +class NetworkConnectionTracker; class SharedURLLoaderFactory; class SimpleURLLoader; } // namespace network @@ -64,14 +65,13 @@ // Guide Service. // // This class fetches new hints from the remote Optimization Guide Service. -// Owner must ensure that |hint_cache| remains alive for the lifetime of -// |HintsFetcher|. class HintsFetcher { public: HintsFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& optimization_guide_service_url, - PrefService* pref_service); + PrefService* pref_service, + network::NetworkConnectionTracker* network_connection_tracker); virtual ~HintsFetcher(); // Requests hints from the Optimization Guide Service if a request for them is @@ -150,6 +150,10 @@ // A reference to the PrefService for this profile. Not owned. PrefService* pref_service_ = nullptr; + // Listens to changes around the network connection. Not owned. Guaranteed to + // outlive |this|. + network::NetworkConnectionTracker* network_connection_tracker_; + // Holds the hosts being requested by the hints fetcher. std::vector<std::string> hosts_fetched_;
diff --git a/components/optimization_guide/hints_fetcher_factory.cc b/components/optimization_guide/hints_fetcher_factory.cc index 8dcfe0b..e194749 100644 --- a/components/optimization_guide/hints_fetcher_factory.cc +++ b/components/optimization_guide/hints_fetcher_factory.cc
@@ -5,6 +5,7 @@ #include "components/optimization_guide/hints_fetcher.h" #include "components/prefs/pref_service.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "services/network/public/cpp/shared_url_loader_factory.h" namespace optimization_guide { @@ -12,16 +13,19 @@ HintsFetcherFactory::HintsFetcherFactory( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& optimization_guide_service_url, - PrefService* pref_service) + PrefService* pref_service, + network::NetworkConnectionTracker* network_connection_tracker) : url_loader_factory_(url_loader_factory), optimization_guide_service_url_(optimization_guide_service_url), - pref_service_(pref_service) {} + pref_service_(pref_service), + network_connection_tracker_(network_connection_tracker) {} HintsFetcherFactory::~HintsFetcherFactory() = default; std::unique_ptr<HintsFetcher> HintsFetcherFactory::BuildInstance() { return std::make_unique<HintsFetcher>( - url_loader_factory_, optimization_guide_service_url_, pref_service_); + url_loader_factory_, optimization_guide_service_url_, pref_service_, + network_connection_tracker_); } } // namespace optimization_guide
diff --git a/components/optimization_guide/hints_fetcher_factory.h b/components/optimization_guide/hints_fetcher_factory.h index 9387ee6..bc7df44 100644 --- a/components/optimization_guide/hints_fetcher_factory.h +++ b/components/optimization_guide/hints_fetcher_factory.h
@@ -13,6 +13,7 @@ class PrefService; namespace network { +class NetworkConnectionTracker; class SharedURLLoaderFactory; } // namespace network @@ -27,7 +28,8 @@ HintsFetcherFactory( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, const GURL& optimization_guide_service_url, - PrefService* pref_service); + PrefService* pref_service, + network::NetworkConnectionTracker* network_connection_tracker); HintsFetcherFactory(const HintsFetcherFactory&) = delete; HintsFetcherFactory& operator=(const HintsFetcherFactory&) = delete; virtual ~HintsFetcherFactory(); @@ -46,6 +48,10 @@ // A reference to the PrefService for this profile. Not owned. PrefService* pref_service_ = nullptr; + + // A reference to the object that listens for changes in network connection. + // Not owned. Guaranteed to outlive |this|. + network::NetworkConnectionTracker* network_connection_tracker_; }; } // namespace optimization_guide
diff --git a/components/optimization_guide/hints_fetcher_unittest.cc b/components/optimization_guide/hints_fetcher_unittest.cc index 397c2dd..d7058094 100644 --- a/components/optimization_guide/hints_fetcher_unittest.cc +++ b/components/optimization_guide/hints_fetcher_unittest.cc
@@ -56,7 +56,8 @@ hints_fetcher_ = std::make_unique<HintsFetcher>( shared_url_loader_factory_, GURL(optimization_guide_service_url), - pref_service_.get()); + pref_service_.get(), + network::TestNetworkConnectionTracker::GetInstance()); hints_fetcher_->SetTimeClockForTesting(task_environment_.GetMockClock()); }
diff --git a/components/optimization_guide/hints_processing_util.cc b/components/optimization_guide/hints_processing_util.cc index b29324fd..c5d9d64 100644 --- a/components/optimization_guide/hints_processing_util.cc +++ b/components/optimization_guide/hints_processing_util.cc
@@ -53,6 +53,8 @@ return "LiteVideo"; case proto::OptimizationType::LINK_PERFORMANCE: return "LinkPerformance"; + case proto::OptimizationType::SHOPPING_PAGE_PREDICTOR: + return "ShoppingPagePredictor"; } NOTREACHED(); return std::string();
diff --git a/components/optimization_guide/proto/hints.proto b/components/optimization_guide/proto/hints.proto index 352520c..85104f2 100644 --- a/components/optimization_guide/proto/hints.proto +++ b/components/optimization_guide/proto/hints.proto
@@ -133,6 +133,11 @@ // This optimization is used to provide aggregated performance information // about pages linked to from the current page. LINK_PERFORMANCE = 14; + // Detects if a page is a shopping page or not. A tradeoff has been made here + // where the number of shopping page predictions for non-shopping pages is + // increased to reduce the number of non-shopping page predictions for + // shopping pages. + SHOPPING_PAGE_PREDICTOR = 15; } // Presents semantics for how page load URLs should be matched.
diff --git a/components/pdf_strings.grdp b/components/pdf_strings.grdp index 07fa88b..f4f6325 100644 --- a/components/pdf_strings.grdp +++ b/components/pdf_strings.grdp
@@ -43,6 +43,52 @@ Section </message> + <message name="IDS_PDF_PROPERTIES_DIALOG_TITLE" desc="Title of the dialog that displays the PDF document properties."> + Document properties + </message> + <message name="IDS_PDF_PROPERTIES_FILE_NAME" desc="Name of the property describing the file name of the PDF document."> + File name: + </message> + <message name="IDS_PDF_PROPERTIES_FILE_SIZE" desc="Name of the property describing the size of the PDF document."> + File size: + </message> + <message name="IDS_PDF_PROPERTIES_TITLE" desc="Name of the property describing the title of the PDF document."> + Title: + </message> + <message name="IDS_PDF_PROPERTIES_AUTHOR" desc="Name of the property describing the author of the PDF document."> + Author: + </message> + <message name="IDS_PDF_PROPERTIES_SUBJECT" desc="Name of the property describing the subject of the PDF document."> + Subject: + </message> + <message name="IDS_PDF_PROPERTIES_KEYWORDS" desc="Name of the property describing the keywords associated with the PDF document."> + Keywords: + </message> + <message name="IDS_PDF_PROPERTIES_CREATED" desc="Name of the property describing the date and time when the PDF document was created."> + Created: + </message> + <message name="IDS_PDF_PROPERTIES_MODIFIED" desc="Name of the property describing the date and time when the PDF document was most recently modified."> + Modified: + </message> + <message name="IDS_PDF_PROPERTIES_APPLICATION" desc="Name of the property describing the application that created the original document from which the PDF document was made."> + Application: + </message> + <message name="IDS_PDF_PROPERTIES_PDF_PRODUCER" desc="Name of the property describing the name of the application that converted the original document to a PDF document."> + PDF producer: + </message> + <message name="IDS_PDF_PROPERTIES_PDF_VERSION" desc="Name of the property describing the version of the PDF document."> + PDF version: + </message> + <message name="IDS_PDF_PROPERTIES_PAGE_COUNT" desc="Name of the property describing the number of pages in the PDF document."> + Page count: + </message> + <message name="IDS_PDF_PROPERTIES_PAGE_SIZE" desc="Name of the property describing the size of the pages of the PDF document."> + Page size: + </message> + <message name="IDS_PDF_PROPERTIES_FAST_WEB_VIEW" desc="Name of the property describing whether the PDF document is organized to be viewed efficiently in network environments."> + Fast web view: + </message> + <message name="IDS_PDF_TOOLTIP_ROTATE_CW" desc="Button tooltip for the button which rotates a PDF document clockwise"> Rotate clockwise </message>
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_APPLICATION.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_APPLICATION.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_APPLICATION.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_AUTHOR.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_AUTHOR.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_AUTHOR.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_CREATED.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_CREATED.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_CREATED.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_DIALOG_TITLE.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_DIALOG_TITLE.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FAST_WEB_VIEW.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FAST_WEB_VIEW.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FAST_WEB_VIEW.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FILE_NAME.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FILE_NAME.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FILE_NAME.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FILE_SIZE.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FILE_SIZE.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_FILE_SIZE.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_KEYWORDS.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_KEYWORDS.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_KEYWORDS.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_MODIFIED.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_MODIFIED.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_MODIFIED.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PAGE_COUNT.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PAGE_COUNT.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PAGE_COUNT.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PAGE_SIZE.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PAGE_SIZE.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PAGE_SIZE.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PDF_PRODUCER.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PDF_PRODUCER.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PDF_PRODUCER.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PDF_VERSION.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PDF_VERSION.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_PDF_VERSION.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_SUBJECT.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_SUBJECT.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_SUBJECT.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_TITLE.png.sha1 b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_TITLE.png.sha1 new file mode 100644 index 0000000..96fef3b --- /dev/null +++ b/components/pdf_strings_grdp/IDS_PDF_PROPERTIES_TITLE.png.sha1
@@ -0,0 +1 @@ +38eae0f694309a8f5baf803f90d7a8b6457c5254 \ No newline at end of file
diff --git a/components/performance_manager/public/v8_memory/web_memory.h b/components/performance_manager/public/v8_memory/web_memory.h index c855813..69024d6 100644 --- a/components/performance_manager/public/v8_memory/web_memory.h +++ b/components/performance_manager/public/v8_memory/web_memory.h
@@ -8,10 +8,8 @@ #include <memory> #include "base/callback.h" -#include "base/memory/scoped_refptr.h" -#include "base/types/pass_key.h" +#include "base/memory/weak_ptr.h" #include "components/performance_manager/public/mojom/web_memory.mojom.h" -#include "third_party/blink/public/common/tokens/tokens.h" namespace performance_manager { @@ -28,16 +26,25 @@ // performance.measureMemory without them. class WebMeasureMemorySecurityChecker { public: + // A callback that starts the memory measurement if the security check + // succeeds. The FrameNode that requested the measurement is included as a + // WeakPtr parameter because the security check might be done on another + // sequence, and the frame might be destroyed before the callback is invoked + // on the PM sequence. + using MeasureMemoryCallback = + base::OnceCallback<void(base::WeakPtr<FrameNode>)>; + virtual ~WebMeasureMemorySecurityChecker() = default; // Creates a WebMeasureMemorySecurityChecker for production use. static std::unique_ptr<WebMeasureMemorySecurityChecker> Create(); - // Invokes |measure_memory_closure| on the PM sequence if |frame| is allowed - // to call WebMeasureMemory, |bad_message_callback| otherwise. + // Invokes |measure_memory_callback| with |frame| as a parameter on the PM + // sequence if |frame| is allowed to call WebMeasureMemory, + // |bad_message_callback| otherwise. virtual void CheckMeasureMemoryIsAllowed( const FrameNode* frame, - base::OnceClosure measure_memory_closure, + MeasureMemoryCallback measure_memory_callback, mojo::ReportBadMessageCallback bad_message_callback) const = 0; }; @@ -50,6 +57,8 @@ // |security_checker|. If so, measures memory usage of each frame in // |frame_node|'s browsing context group and invokes |result_callback| with the // result; if not, invokes |bad_message_callback|. +// +// This must be called on the PM sequence. void WebMeasureMemory( const FrameNode* frame_node, mojom::WebMemoryMeasurement::Mode mode,
diff --git a/components/performance_manager/v8_memory/web_memory_impl.cc b/components/performance_manager/v8_memory/web_memory_impl.cc index ef1c1bc3..5540072 100644 --- a/components/performance_manager/v8_memory/web_memory_impl.cc +++ b/components/performance_manager/v8_memory/web_memory_impl.cc
@@ -15,7 +15,13 @@ #include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/page_node.h" #include "components/performance_manager/public/graph/process_node.h" +#include "components/performance_manager/public/performance_manager.h" +#include "components/performance_manager/public/render_frame_host_proxy.h" #include "components/performance_manager/public/v8_memory/web_memory.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "third_party/blink/public/common/features.h" #include "url/gurl.h" #include "url/origin.h" @@ -84,6 +90,33 @@ } } +// Checks if the frame referenced by |rfh_proxy| is crossOriginIsolated. If so, +// invokes |measure_memory_callback| on the PM sequences. If not, invokes +// |bad_message_callback| instead. If the frame disappears at any point, does +// nothing. +void CheckIsCrossOriginIsolatedOnUISeq( + const RenderFrameHostProxy& rfh_proxy, + WebMeasureMemorySecurityChecker::MeasureMemoryCallback + measure_memory_callback, + mojo::ReportBadMessageCallback bad_message_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + content::RenderFrameHost* rfh = rfh_proxy.Get(); + if (!rfh) { + // Frame was deleted before the task ran. + return; + } + if (rfh->GetCrossOriginIsolationStatus() == + content::RenderFrameHost::CrossOriginIsolationStatus::kNotIsolated) { + std::move(bad_message_callback) + .Run("Requesting frame must be cross-origin isolated."); + return; + } + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce(std::move(measure_memory_callback), + PerformanceManager::GetFrameNodeForRenderFrameHost(rfh))); +} + } // anonymous namespace //////////////////////////////////////////////////////////////////////////////// @@ -100,9 +133,14 @@ WebMemoryMeasurer::~WebMemoryMeasurer() = default; // static -void WebMemoryMeasurer::MeasureMemory(const FrameNode* frame_node, - mojom::WebMemoryMeasurement::Mode mode, - MeasurementCallback callback) { +void WebMemoryMeasurer::MeasureMemory(mojom::WebMemoryMeasurement::Mode mode, + MeasurementCallback callback, + base::WeakPtr<FrameNode> frame_node) { + if (!frame_node) { + // Frame was deleted while validating it on the UI sequence. + return; + } + // Can't use make_unique with a private constructor. auto measurer = base::WrapUnique(new WebMemoryMeasurer( frame_node->GetFrameToken(), @@ -138,7 +176,7 @@ void WebMeasureMemorySecurityCheckerImpl::CheckMeasureMemoryIsAllowed( const FrameNode* frame, - base::OnceClosure measure_memory_closure, + MeasureMemoryCallback measure_memory_callback, mojo::ReportBadMessageCallback bad_message_callback) const { DCHECK(frame); DCHECK_ON_GRAPH_SEQUENCE(frame->GetGraph()); @@ -164,10 +202,11 @@ .Run("performance.measureMemory called from cross-origin subframe"); return; } - // TODO(crbug/1085129): Check crossOriginIsolated once this is available in - // the browser. This will need to be done on the UI sequence, and return the - // result to the PM sequence to run the closure. - std::move(measure_memory_closure).Run(); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&CheckIsCrossOriginIsolatedOnUISeq, + frame->GetRenderFrameHostProxy(), + std::move(measure_memory_callback), + std::move(bad_message_callback))); } //////////////////////////////////////////////////////////////////////////////// @@ -187,7 +226,7 @@ // measurement. security_checker->CheckMeasureMemoryIsAllowed( frame_node, - base::BindOnce(&WebMemoryMeasurer::MeasureMemory, frame_node, mode, + base::BindOnce(&WebMemoryMeasurer::MeasureMemory, mode, std::move(result_callback)), std::move(bad_message_callback)); }
diff --git a/components/performance_manager/v8_memory/web_memory_impl.h b/components/performance_manager/v8_memory/web_memory_impl.h index 8d8f22a7..0c1db0ab 100644 --- a/components/performance_manager/v8_memory/web_memory_impl.h +++ b/components/performance_manager/v8_memory/web_memory_impl.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/callback.h" +#include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "components/performance_manager/public/mojom/web_memory.mojom.h" #include "components/performance_manager/public/v8_memory/v8_detailed_memory.h" @@ -32,10 +33,11 @@ base::OnceCallback<void(mojom::WebMemoryMeasurementPtr)>; // Implements WebMeasureMemory (from public/v8_memory/web_memory.h) by - // instantiating a WebMemoryMeasurer. - static void MeasureMemory(const FrameNode* frame_node, - mojom::WebMemoryMeasurement::Mode mode, - MeasurementCallback callback); + // instantiating a WebMemoryMeasurer. |frame_node| must be the last parameter + // so it can be used with base::Bind. + static void MeasureMemory(mojom::WebMemoryMeasurement::Mode mode, + MeasurementCallback callback, + base::WeakPtr<FrameNode> frame_node); ~WebMemoryMeasurer(); @@ -75,7 +77,7 @@ void CheckMeasureMemoryIsAllowed( const FrameNode* frame, - base::OnceClosure measure_memory_closure, + MeasureMemoryCallback measure_memory_callback, mojo::ReportBadMessageCallback bad_message_callback) const override; };
diff --git a/components/performance_manager/v8_memory/web_memory_impl_unittest.cc b/components/performance_manager/v8_memory/web_memory_impl_unittest.cc index 83c3b31..6cd923bf 100644 --- a/components/performance_manager/v8_memory/web_memory_impl_unittest.cc +++ b/components/performance_manager/v8_memory/web_memory_impl_unittest.cc
@@ -45,10 +45,11 @@ void CheckMeasureMemoryIsAllowed( const FrameNode* frame_node, - base::OnceClosure measure_memory_closure, + MeasureMemoryCallback measure_memory_callback, mojo::ReportBadMessageCallback bad_message_callback) const override { if (allowed_) { - std::move(measure_memory_closure).Run(); + std::move(measure_memory_callback) + .Run(FrameNodeImpl::FromNode(frame_node)->GetWeakPtr()); } else { std::move(bad_message_callback).Run("disallowed"); }
diff --git a/components/qr_code_generator/BUILD.gn b/components/qr_code_generator/BUILD.gn new file mode 100644 index 0000000..114cebc --- /dev/null +++ b/components/qr_code_generator/BUILD.gn
@@ -0,0 +1,37 @@ +# Copyright 2020 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. + +declare_args() { + # Enables building a development / debugging binary. + enable_qr_print = false +} + +source_set("qr_code_generator") { + sources = [ + "dino_image.h", + "qr_code_generator.cc", + "qr_code_generator.h", + ] + + deps = [ "//base" ] + + public_deps = [ "//base" ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "qr_code_generator_unittest.cc" ] + deps = [ + ":qr_code_generator", + "//base", + "//testing/gtest", + ] +} + +if (enable_qr_print) { + executable("qr_print") { + sources = [ "qr_print.cc" ] + deps = [ ":qr_code_generator" ] + } +}
diff --git a/chrome/common/qr_code_generator/DIR_METADATA b/components/qr_code_generator/DIR_METADATA similarity index 100% rename from chrome/common/qr_code_generator/DIR_METADATA rename to components/qr_code_generator/DIR_METADATA
diff --git a/chrome/common/qr_code_generator/OWNERS b/components/qr_code_generator/OWNERS similarity index 100% rename from chrome/common/qr_code_generator/OWNERS rename to components/qr_code_generator/OWNERS
diff --git a/components/qr_code_generator/dino_image.h b/components/qr_code_generator/dino_image.h new file mode 100644 index 0000000..66fa7714 --- /dev/null +++ b/components/qr_code_generator/dino_image.h
@@ -0,0 +1,71 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_QR_CODE_GENERATOR_DINO_IMAGE_H_ +#define COMPONENTS_QR_CODE_GENERATOR_DINO_IMAGE_H_ + +// Contains constants clients use to to render a dino on top of a QR image. +namespace dino_image { + +// Width of the dino pixel data. +static constexpr int kDinoWidth = 20; +// Height of the dino pixel data. +static constexpr int kDinoHeight = 22; +// Height of the dino pixel data, head segment. +static constexpr int kDinoHeadHeight = 8; +// Height of the dino image data, body segment. +static constexpr int kDinoBodyHeight = kDinoHeight - kDinoHeadHeight; +// Width of the dino image data. +static constexpr int kDinoWidthBytes = (kDinoWidth + 7) / 8; + +// Pixel data for the dino's head, facing right. +static const unsigned char kDinoHeadRight[kDinoWidthBytes * kDinoHeadHeight] = { + // clang-format off + 0b00000000, 0b00011111, 0b11100000, + 0b00000000, 0b00111111, 0b11110000, + 0b00000000, 0b00110111, 0b11110000, + 0b00000000, 0b00111111, 0b11110000, + 0b00000000, 0b00111111, 0b11110000, + 0b00000000, 0b00111111, 0b11110000, + 0b00000000, 0b00111110, 0b00000000, + 0b00000000, 0b00111111, 0b11000000, + // clang-format on +}; + +// Pixel data for the dino's head, facing left. +static const unsigned char kDinoHeadLeft[kDinoWidthBytes * kDinoHeadHeight] = { + // clang-format off + 0b00000111, 0b11111000, 0b00000000, + 0b00001111, 0b11111100, 0b00000000, + 0b00001111, 0b11101100, 0b00000000, + 0b00001111, 0b11111100, 0b00000000, + 0b00001111, 0b11111100, 0b00000000, + 0b00001111, 0b11111100, 0b00000000, + 0b00000000, 0b01111100, 0b00000000, + 0b00000011, 0b11111100, 0b00000000, + // clang-format on +}; + +// Pixel data for the dino's body. +static const unsigned char kDinoBody[kDinoWidthBytes * kDinoBodyHeight] = { + // clang-format off + 0b10000000, 0b01111100, 0b00000000, + 0b10000001, 0b11111100, 0b00000000, + 0b11000011, 0b11111111, 0b00000000, + 0b11100111, 0b11111101, 0b00000000, + 0b11111111, 0b11111100, 0b00000000, + 0b11111111, 0b11111100, 0b00000000, + 0b01111111, 0b11111000, 0b00000000, + 0b00111111, 0b11111000, 0b00000000, + 0b00011111, 0b11110000, 0b00000000, + 0b00001111, 0b11100000, 0b00000000, + 0b00000111, 0b01100000, 0b00000000, + 0b00000110, 0b00100000, 0b00000000, + 0b00000100, 0b00100000, 0b00000000, + 0b00000110, 0b00110000, 0b00000000, + // clang-format on +}; + +} // namespace dino_image +#endif // COMPONENTS_QR_CODE_GENERATOR_DINO_IMAGE_H_
diff --git a/components/qr_code_generator/qr_code_generator.cc b/components/qr_code_generator/qr_code_generator.cc new file mode 100644 index 0000000..ea79d729 --- /dev/null +++ b/components/qr_code_generator/qr_code_generator.cc
@@ -0,0 +1,981 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/qr_code_generator/qr_code_generator.h" + +#include <math.h> +#include <string.h> + +#include <ostream> +#include <vector> + +#include "base/check_op.h" +#include "base/notreached.h" + +// kMaxVersionWith8BitLength is the maximum QR version that uses an 8 (rather +// than 16) bit length in 8-bit byte mode. See table 3. +static constexpr int kMaxVersionWith8BitLength = 9; + +// A structure containing QR version-specific constants and data. +// All versions currently use error correction at level M. +struct QRVersionInfo { + constexpr QRVersionInfo(const int version, + const uint32_t encoded_version, + const int size, + const size_t group1_bytes, + const size_t group1_num_blocks, + const size_t group1_block_data_bytes, + const size_t group2_bytes, + const size_t group2_num_blocks, + const size_t group2_block_data_bytes, + const std::array<int, 3> alignment_locations) + : version(version), + encoded_version(encoded_version), + size(size), + group1_bytes(group1_bytes), + group1_num_blocks(group1_num_blocks), + group1_block_data_bytes(group1_block_data_bytes), + group2_bytes(group2_bytes), + group2_num_blocks(group2_num_blocks), + group2_block_data_bytes(group2_block_data_bytes), + alignment_locations(alignment_locations) { + if (version < 1 || version > 40 || size < 0 || + !CheckBlockGroupParameters(group1_bytes, group1_num_blocks, + group1_block_data_bytes) || + (group2_num_blocks != 0 && + !CheckBlockGroupParameters(group2_bytes, group2_num_blocks, + group2_block_data_bytes)) || + (version < 7 && encoded_version != 0) || + (version >= 7 && + encoded_version >> 12 != static_cast<uint32_t>(version)) || + (version <= kMaxVersionWith8BitLength && input_bytes() >= 256) || + (group2_num_blocks != 0 && + group2_block_ec_bytes() != group1_block_ec_bytes())) { + __builtin_unreachable(); + } + } + + // The version of the QR code. + const int version; + + // An 18-bit value that contains the version, BCH (18,6)-encoded. Only valid + // for versions seven and above. See table D.1 for values. + const uint32_t encoded_version; + + // The number of "tiles" in each dimension for a QR code of |version|. See + // table 1. (The colored squares in in QR codes are called tiles in the + // spec.) + const int size; + + // Values taken from Table 9, page 38, for a QR code of version |version|. + const size_t group1_bytes; + const size_t group1_num_blocks; + const size_t group1_block_data_bytes; + const size_t group2_bytes; + const size_t group2_num_blocks; + const size_t group2_block_data_bytes; + + const std::array<int, 3> alignment_locations; + + // Total number of tiles for the QR code, size*size. + constexpr int total_size() const { return size * size; } + + constexpr size_t total_bytes() const { return group1_bytes + group2_bytes; } + + constexpr size_t group1_block_bytes() const { + return group1_bytes / group1_num_blocks; + } + + constexpr size_t group1_block_ec_bytes() const { + return group1_block_bytes() - group1_block_data_bytes; + } + + constexpr size_t group1_data_bytes() const { + return group1_block_data_bytes * group1_num_blocks; + } + + constexpr size_t group2_block_bytes() const { + if (group2_num_blocks == 0) + return 0; + return group2_bytes / group2_num_blocks; + } + + constexpr size_t group2_block_ec_bytes() const { + return group2_block_bytes() - group2_block_data_bytes; + } + + constexpr size_t group2_data_bytes() const { + return group2_block_data_bytes * group2_num_blocks; + } + + // Two bytes of overhead are needed for QR framing. + // If extending beyond version 26, framing would need to be updated. + constexpr size_t input_bytes() const { + if (version <= 9) { + return group1_data_bytes() + group2_data_bytes() - 2; + } else { + return group1_data_bytes() + group2_data_bytes() - 3; + } + } + + private: + static constexpr bool CheckBlockGroupParameters( + const size_t bytes, + const size_t num_blocks, + const size_t block_data_bytes) { + if (num_blocks == 0 || bytes % num_blocks != 0 || block_data_bytes == 0 || + block_data_bytes * num_blocks > bytes || + (bytes - block_data_bytes * num_blocks) % num_blocks != 0) { + return false; + } + + return true; + } + + DISALLOW_COPY_AND_ASSIGN(QRVersionInfo); +}; + +namespace { + +constexpr QRVersionInfo version_infos[] = { + // See table 9 in the spec for the source of these numbers. + + // 5-M + // 134 bytes, as 2 blocks of 67. + { + 5, // version + 0, // encoded version (not included in this version) + 37, // size (num tiles in each axis) + + // Block group 1: + 134, // Total bytes in group + 2, // Number of blocks + 43, // Data bytes per block + + // Block group 2: + 0, + 0, + 0, + + // Alignment locations + {6, 30, 0}, + }, + + // 7-M + // 196 bytes, as 4 blocks of 49. + { + 7, // version + 0b000111110010010100, // encoded version + 45, // size (num tiles in each axis) + + // Block group 1: + 196, // Total bytes in group + 4, // Number of blocks + 31, // Data bytes per block + + // Block group 2: + 0, + 0, + 0, + + // Alignment locations + {6, 22, 38}, + }, + + // 9-M + // 292 bytes, as 3 blocks of 58 plus 2 blocks of 59. + { + 9, // version + 0b001001101010011001, // encoded version + 53, // size (num tiles in each axis) + + // Block group 1: + 174, // Total bytes in group + 3, // Number of blocks + 36, // Data bytes per block + + // Block group 2: + 118, + 2, + 37, + + // Alignment locations + {6, 26, 46}, + }, + + // 12-M + // 466 bytes, as 6 blocks of 58 and 2 blocks of 59. + { + 12, // version + 0b001100011101100010, // encoded version + 65, // size (num tiles in each axis) + + // Block group 1: + 348, // Total bytes in group + 6, // Number of blocks + 36, // Data bytes per block + + // Block group 2: + 118, + 2, + 37, + + // Alignment locations + {6, 32, 58}, + }, +}; + +const QRVersionInfo* GetVersionForDataSize(size_t num_data_bytes) { + for (const auto& version : version_infos) { + if (version.input_bytes() >= num_data_bytes) { + return &version; + } + } + return nullptr; +} + +// kMaxMask is the maximum masking function number. See table 10. +constexpr uint8_t kMaxMask = 7; + +// The following functions implement the masks specified in table 10. + +uint8_t MaskFunction0(int x, int y) { + return (x + y) % 2 == 0; +} +uint8_t MaskFunction1(int x, int y) { + return y % 2 == 0; +} +uint8_t MaskFunction2(int x, int y) { + return x % 3 == 0; +} +uint8_t MaskFunction3(int x, int y) { + return (x + y) % 3 == 0; +} +uint8_t MaskFunction4(int x, int y) { + return ((y / 2) + (x / 3)) % 2 == 0; +} +uint8_t MaskFunction5(int x, int y) { + return ((x * y) % 2) + ((x * y) % 3) == 0; +} +uint8_t MaskFunction6(int x, int y) { + return (((x * y) % 2) + ((x * y) % 3)) % 2 == 0; +} +uint8_t MaskFunction7(int x, int y) { + return (((x + y) % 2) + ((x * y) % 3)) % 2 == 0; +} + +static uint8_t (*const kMaskFunctions[kMaxMask + 1])(int x, int y) = { + MaskFunction0, MaskFunction1, MaskFunction2, MaskFunction3, + MaskFunction4, MaskFunction5, MaskFunction6, MaskFunction7, +}; + +// kFormatInformation is taken from table C.1 on page 80 and specifies the +// format value for each masking function, assuming ECC level 'M'. +static const uint16_t kFormatInformation[kMaxMask + 1] = { + 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, +}; + +} // namespace + +QRCodeGenerator::QRCodeGenerator() = default; + +QRCodeGenerator::~QRCodeGenerator() = default; + +QRCodeGenerator::GeneratedCode::GeneratedCode() = default; +QRCodeGenerator::GeneratedCode::GeneratedCode( + QRCodeGenerator::GeneratedCode&&) = default; +QRCodeGenerator::GeneratedCode::~GeneratedCode() = default; + +base::Optional<QRCodeGenerator::GeneratedCode> QRCodeGenerator::Generate( + base::span<const uint8_t> in, + base::Optional<uint8_t> mask) { + CHECK(!mask || *mask <= kMaxMask); + + // We're currently using a minimal set of versions to shrink test surface. + // When expanding, take care to validate across different platforms and + // a selection of QR Scanner apps. + const QRVersionInfo* const version_info = GetVersionForDataSize(in.size()); + if (!version_info) { + return base::nullopt; + } + + if (version_info != version_info_) { + version_info_ = version_info; + d_.resize(version_info_->total_size()); + } + // Previous data and "set" bits must be cleared. + memset(&d_[0], 0, version_info_->total_size()); + + PutVerticalTiming(6); + PutHorizontalTiming(6); + PutFinder(3, 3); + PutFinder(3, version_info_->size - 4); + PutFinder(version_info_->size - 4, 3); + + const auto& alignment_locations = version_info_->alignment_locations; + size_t num_alignment_locations = 0; + for (size_t i = 0; i < alignment_locations.size(); i++) { + if (alignment_locations[i] == 0) { + break; + } + num_alignment_locations++; + } + + for (size_t i = 0; i < num_alignment_locations; i++) { + for (size_t j = 0; j < num_alignment_locations; j++) { + // Three of the corners already have finder symbols. + if ((i == 0 && j == 0) || (i == 0 && j == num_alignment_locations - 1) || + (i == num_alignment_locations - 1 && j == 0)) { + continue; + } + + PutAlignment(alignment_locations[i], alignment_locations[j]); + } + } + + if (version_info_->encoded_version != 0) { + PutVersionBlocks(version_info_->encoded_version); + } + + // Add the mode and character count. + + // QR codes require some framing of the data. This requires: + // Version 1-9: 4 bits for mode + 8 bits for char count = 12 bits + // Version 10-40: 4 bits for mode + 16 bits for char count = 20 bits + // Details are in Table 3. + // Since 12 and 20 are not a multiple of eight, a frame-shift of all + // subsequent bytes is required. + const size_t framed_input_size = + version_info_->group1_data_bytes() + version_info_->group2_data_bytes(); + std::vector<uint8_t> prefixed_data(framed_input_size); + size_t framing_offset_bytes = 0; + if (version_info->version <= kMaxVersionWith8BitLength) { + DCHECK_LT(in.size(), 0x100u) << "in.size() too large for 8-bit length"; + const uint8_t len8 = static_cast<uint8_t>(in.size()); + prefixed_data[0] = 0x40 | (len8 >> 4); + prefixed_data[1] = len8 << 4; + if (!in.empty()) { + prefixed_data[1] |= in[0] >> 4; + } + framing_offset_bytes = 2; + } else { + DCHECK_LT(in.size(), 0x10000u) << "in.size() too large for 16-bit length"; + const uint16_t len16 = static_cast<uint16_t>(in.size()); + prefixed_data[0] = 0x40 | (len16 >> 12); + prefixed_data[1] = len16 >> 4; + prefixed_data[2] = len16 << 4; + if (!in.empty()) { + prefixed_data[2] |= in[0] >> 4; + } + framing_offset_bytes = 3; + } + DCHECK_LE(in.size() + framing_offset_bytes, prefixed_data.size()); + + for (size_t i = 0; i < in.size() - 1; i++) { + prefixed_data[i + framing_offset_bytes] = (in[i] << 4) | (in[i + 1] >> 4); + } + if (!in.empty()) { + prefixed_data[in.size() - 1 + framing_offset_bytes] = in[in.size() - 1] + << 4; + } + + // The QR code looks a little odd with fixed padding. Thus replicate the + // message to fill the input. + for (size_t i = in.size() + framing_offset_bytes; i < framed_input_size; + i++) { + prefixed_data[i] = prefixed_data[i % (in.size() + framing_offset_bytes)]; + } + + // Each block of input data is expanded with error correcting + // information and then interleaved. + + // Error Correction for Group 1, present for all versions. + const size_t group1_num_blocks = version_info_->group1_num_blocks; + const size_t group1_block_bytes = version_info_->group1_block_bytes(); + const size_t group1_block_data_bytes = version_info_->group1_block_data_bytes; + const size_t group1_block_ec_bytes = version_info_->group1_block_ec_bytes(); + std::vector<std::vector<uint8_t>> expanded_blocks(group1_num_blocks); + for (size_t i = 0; i < group1_num_blocks; i++) { + expanded_blocks[i].resize(group1_block_bytes); + AddErrorCorrection( + expanded_blocks[i], + base::span<const uint8_t>(&prefixed_data[group1_block_data_bytes * i], + group1_block_data_bytes), + group1_block_bytes, group1_block_ec_bytes); + } + + // Error Correction for Group 2, present for some versions. + // Factor out the number of bytes written by the prior group. + const size_t group_data_offset = version_info_->group1_data_bytes(); + const size_t group2_num_blocks = version_info_->group2_num_blocks; + const size_t group2_block_bytes = version_info_->group2_block_bytes(); + const size_t group2_block_data_bytes = version_info_->group2_block_data_bytes; + const size_t group2_block_ec_bytes = version_info_->group2_block_ec_bytes(); + + std::vector<std::vector<uint8_t>> expanded_blocks_2; + if (group2_num_blocks > 0) { + expanded_blocks_2.resize(group2_num_blocks); + for (size_t i = 0; i < group2_num_blocks; i++) { + expanded_blocks_2[i].resize(group2_block_bytes); + AddErrorCorrection( + expanded_blocks_2[i], + base::span<const uint8_t>( + &prefixed_data[group_data_offset + group2_block_data_bytes * i], + group2_block_data_bytes), + group2_block_bytes, group2_block_ec_bytes); + } + } + + const size_t total_bytes = version_info_->total_bytes(); + uint8_t interleaved_data[total_bytes]; + CHECK(total_bytes == group1_block_bytes * group1_num_blocks + + group2_block_bytes * group2_num_blocks) + << "internal error"; + + size_t k = 0; + // Interleave data from all blocks. All non-ECC data is written before any ECC + // data. The group two blocks, if any, will be longer than the group one + // blocks. Once group one is exhausted then the interleave considers only + // group two. + DCHECK(group2_num_blocks == 0 || version_info_->group2_block_data_bytes > + version_info_->group1_block_data_bytes); + + size_t j = 0; + for (; j < version_info_->group1_block_data_bytes; j++) { + for (size_t i = 0; i < group1_num_blocks; i++) { + interleaved_data[k++] = expanded_blocks[i][j]; + } + for (size_t i = 0; i < group2_num_blocks; i++) { + interleaved_data[k++] = expanded_blocks_2[i][j]; + } + } + if (group2_num_blocks > 0) { + for (; j < version_info_->group2_block_data_bytes; j++) { + for (size_t i = 0; i < group2_num_blocks; i++) { + interleaved_data[k++] = expanded_blocks_2[i][j]; + } + } + } + + // The number of ECC bytes in each group is the same so the interleave + // considers them uniformly. + DCHECK(version_info_->group2_num_blocks == 0 || + version_info_->group2_block_ec_bytes() == + version_info_->group1_block_ec_bytes()); + for (size_t j = 0; j < version_info_->group1_block_ec_bytes(); j++) { + for (size_t i = 0; i < group1_num_blocks; i++) { + interleaved_data[k++] = + expanded_blocks[i][version_info_->group1_block_data_bytes + j]; + } + for (size_t i = 0; i < group2_num_blocks; i++) { + interleaved_data[k++] = + expanded_blocks_2[i][version_info_->group2_block_data_bytes + j]; + } + } + DCHECK_EQ(k, total_bytes); + + uint8_t best_mask = mask.value_or(0); + base::Optional<unsigned> lowest_penalty; + + // If |mask| was not specified, then evaluate each masking function to find + // the one with the lowest penalty score. + for (uint8_t mask_num = 0; !mask && mask_num <= kMaxMask; mask_num++) { + // kFormatInformation is the encoded formatting word for the QR code that + // this code generates. See tables 10 and 12. For example: + // 00 011 + // --|--- + // error correction M | Mask pattern 3 + // + // It's translated into a 15-bit value using the table on page 80, which is + // stored in |kFormatInformation|. + PutFormatBits(kFormatInformation[mask_num]); + + PutBits(interleaved_data, sizeof(interleaved_data), + kMaskFunctions[mask_num]); + + const unsigned penalty = CountPenaltyPoints(); + if (!lowest_penalty || *lowest_penalty > penalty) { + lowest_penalty = penalty; + best_mask = mask_num; + } + } + + // Repaint with the best mask function. + PutFormatBits(kFormatInformation[best_mask]); + PutBits(interleaved_data, sizeof(interleaved_data), + kMaskFunctions[best_mask]); + + GeneratedCode code; + code.data = base::span<uint8_t>(&d_[0], version_info_->total_size()); + code.qr_size = version_info_->size; + return code; +} + +// PutFinder paints a finder symbol at the given coordinates. +void QRCodeGenerator::PutFinder(int x, int y) { + DCHECK_GE(x, 3); + DCHECK_GE(y, 3); + fillAt(x - 3, y - 3, 7, 0b11); + fillAt(x - 2, y - 2, 5, 0b10); + fillAt(x - 2, y + 2, 5, 0b10); + fillAt(x - 3, y + 3, 7, 0b11); + + static constexpr uint8_t kLine[7] = {0b11, 0b10, 0b11, 0b11, + 0b11, 0b10, 0b11}; + copyTo(x - 3, y - 1, kLine, sizeof(kLine)); + copyTo(x - 3, y, kLine, sizeof(kLine)); + copyTo(x - 3, y + 1, kLine, sizeof(kLine)); + + at(x - 3, y - 2) = 0b11; + at(x + 3, y - 2) = 0b11; + at(x - 3, y + 2) = 0b11; + at(x + 3, y + 2) = 0b11; + + for (int xx = x - 4; xx <= x + 4; xx++) { + clipped(xx, y - 4) = 0b10; + clipped(xx, y + 4) = 0b10; + } + for (int yy = y - 3; yy <= y + 3; yy++) { + clipped(x - 4, yy) = 0b10; + clipped(x + 4, yy) = 0b10; + } +} + +// PutAlignment paints an alignment symbol centered at the given coordinates. +void QRCodeGenerator::PutAlignment(int x, int y) { + fillAt(x - 2, y - 2, 5, 0b11); + fillAt(x - 2, y + 2, 5, 0b11); + static constexpr uint8_t kLine[5] = {0b11, 0b10, 0b10, 0b10, 0b11}; + copyTo(x - 2, y - 1, kLine, sizeof(kLine)); + copyTo(x - 2, y, kLine, sizeof(kLine)); + copyTo(x - 2, y + 1, kLine, sizeof(kLine)); + at(x, y) = 0b11; +} + +// PutVerticalTiming paints the vertical timing signal. +void QRCodeGenerator::PutVerticalTiming(int x) { + for (int y = 0; y < version_info_->size; y++) { + at(x, y) = 0b10 | (1 ^ (y & 1)); + } +} + +// PutVerticalTiming paints the horizontal timing signal. +void QRCodeGenerator::PutHorizontalTiming(int y) { + for (int x = 0; x < version_info_->size; x++) { + at(x, y) = 0b10 | (1 ^ (x & 1)); + } +} + +// PutFormatBits paints the 15-bit, pre-encoded format metadata. See page 56 +// for the location of the format bits. +void QRCodeGenerator::PutFormatBits(const uint16_t format) { + // kRun1 is the location of the initial format bits, where the upper nibble + // is the x coordinate and the lower the y. + static constexpr uint8_t kRun1[15] = { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x87, 0x88, + 0x78, 0x58, 0x48, 0x38, 0x28, 0x18, 0x08, + }; + + uint16_t v = format; + for (size_t i = 0; i < sizeof(kRun1); i++) { + const uint8_t location = kRun1[i]; + at(location >> 4, location & 15) = 0b10 | (v & 1); + v >>= 1; + } + + const int size = version_info_->size; + v = format; + for (int x = size - 1; x >= size - 1 - 7; x--) { + at(x, 8) = 0b10 | (v & 1); + v >>= 1; + } + + at(8, size - 1 - 7) = 0b11; + for (int y = size - 1 - 6; y <= size - 1; y++) { + at(8, y) = 0b10 | (v & 1); + v >>= 1; + } +} + +void QRCodeGenerator::PutVersionBlocks(uint32_t encoded_version) { + // Version 7 and larger require 18-bit version information taking the form + // of 6x3 rectangles above the bottom-left locator and to the left of the + // top-right locator. + const int size = version_info_->size; + + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 3; j++) { + // Bottom-left rectangle is top-to-bottom, left-to-right + at(i, size - 8 - 3 + j) = 0b10 | (encoded_version & 1); + // Top-right rectangle is left-to-right, top-to-bottom + at(size - 8 - 3 + j, i) = 0b10 | (encoded_version & 1); + // Shift to consider the next bit. + encoded_version >>= 1; + } + } +} + +// PutBits writes the given data into the QR code in correct order, avoiding +// structural elements that must have already been painted. See section 7.7.3 +// about the placement algorithm. +void QRCodeGenerator::PutBits(const uint8_t* data, + size_t data_len, + uint8_t (*mask_func)(int, int)) { + // BitStream vends bits from |data| on demand, in the order that QR codes + // expect them. + class BitStream { + public: + BitStream(const uint8_t* data, size_t data_len) + : data_(data), data_len_(data_len), i_(0), bits_in_current_byte_(0) {} + + uint8_t Next() { + if (bits_in_current_byte_ == 0) { + if (i_ >= data_len_) { + byte_ = 0; + } else { + byte_ = data_[i_++]; + } + bits_in_current_byte_ = 8; + } + + const uint8_t ret = byte_ >> 7; + byte_ <<= 1; + bits_in_current_byte_--; + return ret; + } + + private: + const uint8_t* const data_; + const size_t data_len_; + size_t i_; + unsigned bits_in_current_byte_; + uint8_t byte_; + }; + + BitStream stream(data, data_len); + + bool going_up = true; + int x = version_info_->size - 1; + int y = version_info_->size - 1; + + for (;;) { + uint8_t& right = at(x, y); + // Test the current value in the QR code to avoid painting over any + // existing structural elements. + if ((right & 2) == 0) { + right = stream.Next() ^ mask_func(x, y); + } + + uint8_t& left = at(x - 1, y); + if ((left & 2) == 0) { + left = stream.Next() ^ mask_func(x - 1, y); + } + + if ((going_up && y == 0) || (!going_up && y == version_info_->size - 1)) { + if (x == 1) { + break; + } + x -= 2; + // The vertical timing column is skipped over. + if (x == 6) { + x--; + } + going_up = !going_up; + } else { + if (going_up) { + y--; + } else { + y++; + } + } + } +} + +// at returns a reference to the given element of |d_|. +uint8_t& QRCodeGenerator::at(int x, int y) { + DCHECK_LE(0, x); + DCHECK_LT(x, version_info_->size); + DCHECK_LE(0, y); + DCHECK_LT(y, version_info_->size); + return d_[version_info_->size * y + x]; +} + +// fillAt sets the |len| elements at (x, y) to |value|. +void QRCodeGenerator::fillAt(int x, int y, size_t len, uint8_t value) { + DCHECK_LE(0, x); + DCHECK_LE(static_cast<int>(x + len), version_info_->size); + DCHECK_LE(0, y); + DCHECK_LT(y, version_info_->size); + memset(&d_[version_info_->size * y + x], value, len); +} + +// copyTo copies |len| elements from |data| to the elements at (x, y). +void QRCodeGenerator::copyTo(int x, int y, const uint8_t* data, size_t len) { + DCHECK_LE(0, x); + DCHECK_LE(static_cast<int>(x + len), version_info_->size); + DCHECK_LE(0, y); + DCHECK_LT(y, version_info_->size); + memcpy(&d_[version_info_->size * y + x], data, len); +} + +// clipped returns a reference to the given element of |d_|, or to +// |clip_dump_| if the coordinates are out of bounds. +uint8_t& QRCodeGenerator::clipped(int x, int y) { + if (0 <= x && x < version_info_->size && 0 <= y && y < version_info_->size) { + return d_[version_info_->size * y + x]; + } + return clip_dump_; +} + +// GF28Mul returns the product of |a| and |b| (which must be field elements, +// i.e. < 256) in the field GF(2^8) mod x^8 + x^4 + x^3 + x^2 + 1. +// static +uint8_t QRCodeGenerator::GF28Mul(uint16_t a, uint16_t b) { + uint16_t acc = 0; + + // Perform 8-bit, carry-less multiplication of |a| and |b|. + for (int i = 0; i < 8; i++) { + const uint16_t mask = ~((b & 1) - 1); + acc ^= a & mask; + b >>= 1; + a <<= 1; + } + + // Add multiples of the modulus to eliminate all bits past a byte. Note that + // the bits in |modulus| have a one where there's a non-zero power of |x| in + // the field modulus. + uint16_t modulus = 0b100011101 << 7; + for (int i = 15; i >= 8; i--) { + const uint16_t mask = ~((acc >> i) - 1); + acc ^= modulus & mask; + modulus >>= 1; + } + + return acc; +} + +// AddErrorCorrection writes the Reed-Solomon expanded version of |in| to +// |out|. +// |out| should have length block_bytes for the code's version. +// |in| should have length block_data_bytes for the code's version. +void QRCodeGenerator::AddErrorCorrection(base::span<uint8_t> out, + base::span<const uint8_t> in, + size_t block_bytes, + size_t block_ec_bytes) { + // kGenerator is the product of (z - x^i) for 0 <= i < |block_ec_bytes|, + // where x is the term of GF(2^8) and z is the term of a polynomial ring + // over GF(2^8). It's generated with the following Sage script: + // + // F.<x> = GF(2^8, modulus = x^8 + x^4 + x^3 + x^2 + 1) + // R.<z> = PolynomialRing(F, 'z') + // + // def toByte(p): + // return sum([(1<<i) * int(term) for (i, term) in + // enumerate(p.polynomial())]) + // + // def generatorPoly(n): + // acc = (z - F(1)) + // for i in range(1,n): + // acc *= (z - x^i) + // return acc + // + // gen = generatorPoly(24) + // coeffs = list(gen) + // gen = [toByte(x) for x in coeffs] + // print 'uint8_t kGenerator[' + str(len(gen)) + '] = {' + str(gen) + '}' + + // Used for 7-M: 18 error correction codewords per block. + static const uint8_t kGenerator18[] = { + 146, 217, 67, 32, 75, 173, 82, 73, 220, 240, + 215, 199, 175, 149, 113, 183, 251, 239, 1, + }; + + // Used for 9-M and 12-M; 22 error correction codewords per block. + static const uint8_t kGenerator22[] = { + 245, 145, 26, 230, 218, 86, 253, 67, 123, 29, 137, 28, + 40, 69, 189, 19, 244, 182, 176, 131, 179, 89, 1, + }; + + // Used for 5-M, 24 error correction codewords per block. + static const uint8_t kGenerator24[] = { + 117, 144, 217, 127, 247, 237, 1, 206, 43, 61, 72, 130, 73, + 229, 150, 115, 102, 216, 237, 178, 70, 169, 118, 122, 1, + }; + + const uint8_t* generator = nullptr; + switch (block_ec_bytes) { + case 18: + generator = kGenerator18; + break; + case 22: + generator = kGenerator22; + break; + case 24: + generator = kGenerator24; + break; + default: { + NOTREACHED() << "Unsupported Generator Polynomial for block_ec_bytes: " + << block_ec_bytes; + return; + } + } + + // The error-correction bytes are the remainder of dividing |in| * x^k by + // |kGenerator|, where |k| is the number of EC codewords. Polynomials here + // are represented in little-endian order, i.e. the value at index |i| is + // the coefficient of z^i. + + // Multiplication of |in| by x^k thus just involves moving it up. + uint8_t remainder[block_bytes]; + DCHECK_LE(block_ec_bytes, block_bytes); + memset(remainder, 0, block_ec_bytes); + size_t block_data_bytes = block_bytes - block_ec_bytes; + // Reed-Solomon input is backwards. See section 7.5.2. + for (size_t i = 0; i < block_data_bytes; i++) { + remainder[block_ec_bytes + i] = in[block_data_bytes - 1 - i]; + } + + // Progressively eliminate the leading coefficient by subtracting some + // multiple of |generator| until we have a value smaller than |generator|. + for (size_t i = block_bytes - 1; i >= block_ec_bytes; i--) { + // The leading coefficient of |generator| is 1, so the multiple to + // subtract to eliminate the leading term of |remainder| is the value of + // that leading term. The polynomial ring is characteristic two, so + // subtraction is the same as addition, which is XOR. + for (size_t j = 0; j < block_ec_bytes; j++) { + remainder[i - block_ec_bytes + j] ^= GF28Mul(generator[j], remainder[i]); + } + } + + memmove(&out[0], &in[0], block_data_bytes); + // Remove the Reed-Solomon remainder again to match QR's convention. + for (size_t i = 0; i < block_ec_bytes; i++) { + out[block_data_bytes + i] = remainder[block_ec_bytes - 1 - i]; + } +} + +unsigned QRCodeGenerator::CountPenaltyPoints() const { + const int size = version_info_->size; + unsigned penalty = 0; + + // The spec penalises the pattern X.XXX.X with four unpainted tiles to + // the left or right. These are "finder-like" patterns. To catch them, a + // sliding window of 11 tiles is used. + static const unsigned k11Bits = 0x7ff; + static const unsigned kFinderLeft = 0b00001011101; + static const unsigned kFinderRight = 0b10111010000; + + // Count: + // * Horizontal runs of the same color, at least five tiles in a row. + // * The number of horizontal finder-like patterns. + // * Total number of painted tiles, which is used later. + unsigned current_run_length; + int current_color; + unsigned total_painted_tiles = 0; + unsigned window = 0; + + size_t i = 0; + for (int y = 0; y < size; y++) { + current_color = d_[i++] & 1; + current_run_length = 0; + window = current_color; + total_painted_tiles += current_color; + + for (int x = 1; x < size; x++) { + const int color = d_[i++] & 1; + + window = k11Bits & ((window << 1) | color); + if (window == kFinderLeft || window == kFinderRight) { + penalty += 40; + } + + total_painted_tiles += color; + + if (color == current_color) { + current_run_length++; + continue; + } + + if (current_run_length >= 5) { + penalty += current_run_length - 2; + } + current_run_length = 0; + current_color = color; + } + + if (current_run_length >= 5) { + penalty += current_run_length - 2; + } + + window = k11Bits & (window << 4); + if (window == kFinderRight) { + penalty += 40; + } + } + DCHECK_EQ(i, static_cast<size_t>(size * size)); + + // Count: + // * Vertical runs of the same color, at least five tiles in a row. + // * The number of vertical finder-like patterns. + for (int x = 0; x < size; x++) { + i = x; + current_run_length = 0; + current_color = d_[i] & 1; + i += size; + window = current_color; + + for (int y = 1; y < size; y++, i += size) { + const int color = d_[i] & 1; + window = k11Bits & ((window << 1) | color); + if (window == kFinderLeft || window == kFinderRight) { + penalty += 40; + } + + if (color == current_color) { + current_run_length++; + continue; + } + + if (current_run_length >= 5) { + penalty += current_run_length - 2; + } + current_run_length = 0; + current_color = color; + } + + if (current_run_length >= 5) { + penalty += current_run_length - 2; + } + + window = k11Bits & (window << 4); + if (window == kFinderRight) { + penalty += 40; + } + } + DCHECK_EQ(i, static_cast<size_t>(size * size + size - 1)); + + // Count 2x2 blocks of the same color. + i = 0; + for (int y = 0; y < size - 1; y++) { + for (int x = 0; x < size - 1; x++) { + const int color = d_[i++] & 1; + if ((d_[i + 1] & 1) == color && (d_[i + size] & 1) == color && + (d_[i + size + 1] & 1) == color) { + penalty += 3; + } + } + } + + // Each deviation of 5% away from 50%-painted costs five points. + DCHECK_LE(total_painted_tiles, static_cast<unsigned>(size) * size); + double painted_fraction = static_cast<double>(total_painted_tiles) / + (static_cast<double>(size) * size); + if (painted_fraction < 0.5) { + painted_fraction = 1.0 - painted_fraction; + } + const double deviation = (painted_fraction - 0.5) / 0.05; + penalty += 5 * static_cast<unsigned>(floor(deviation)); + + return penalty; +}
diff --git a/components/qr_code_generator/qr_code_generator.h b/components/qr_code_generator/qr_code_generator.h new file mode 100644 index 0000000..ef8bec7 --- /dev/null +++ b/components/qr_code_generator/qr_code_generator.h
@@ -0,0 +1,144 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_ +#define COMPONENTS_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <vector> + +#include "base/containers/span.h" +#include "base/optional.h" + +struct QRVersionInfo; + +// QRCodeGenerator generates class M QR codes of various versions. +// References in the following comments refer to ISO 18004 (3rd edition). +// Supports versions up to 26 by adding constants. +class QRCodeGenerator { + public: + // Contains output data for Generate(). + // The default state contains no data. + struct GeneratedCode { + public: + GeneratedCode(); + GeneratedCode(GeneratedCode&&); + ~GeneratedCode(); + + // Pixel data; pointer to an array of bytes, where the least-significant + // bit of each byte is set if that tile should be "black". + // Clients should ensure four modules of padding when rendering the code. + // On error, will not be populated, and will evaluate to false. + base::span<uint8_t> data; + + // Width and height (which are equal) of the generated data, in tiles. + int qr_size = 0; + + DISALLOW_COPY_AND_ASSIGN(GeneratedCode); + }; + + // Static parameters for V5 QR codes. + // These exist while migrating clients to dynamic sizes. + struct V5 { + static constexpr int kSize = 37; + static constexpr int kTotalSize = kSize * kSize; + static constexpr size_t kNumSegments = 2; + static constexpr size_t kSegmentDataBytes = 43; + static constexpr size_t kDataBytes = kSegmentDataBytes * kNumSegments; + static constexpr size_t kInputBytes = kDataBytes - 2; + }; + + QRCodeGenerator(); + ~QRCodeGenerator(); + + // Generates a QR code containing the given data. + // The generator will attempt to choose a version that fits the data. The + // returned span's length is input-dependent and not known at compile-time in + // this case. The optional |mask| argument specifies the QR mask value to use + // (from 0 to 7). If not specified, the optimal mask is calculated per the + // algorithm specified in the QR standard. + base::Optional<GeneratedCode> Generate( + base::span<const uint8_t> in, + base::Optional<uint8_t> mask = base::nullopt); + + private: + // PutFinder paints a finder symbol at the given coordinates. + void PutFinder(int x, int y); + + // PutAlignment paints an alignment symbol centered at the given coordinates. + void PutAlignment(int x, int y); + + // PutVerticalTiming paints the vertical timing signal. + void PutVerticalTiming(int x); + + // PutVerticalTiming paints the horizontal timing signal. + void PutHorizontalTiming(int y); + + // PutFormatBits paints the 15-bit, pre-encoded format metadata. See page 56 + // for the location of the format bits. + void PutFormatBits(const uint16_t format); + + // PutVersionBlocks writes the two blocks of version information for QR + // versions seven and above. + void PutVersionBlocks(const uint32_t encoded_version); + + // PutBits writes the given data into the QR code in correct order, avoiding + // structural elements that must have already been painted. See section 7.7.3 + // about the placement algorithm. + void PutBits(const uint8_t* data, + size_t data_len, + uint8_t (*mask_func)(int, int)); + + // at returns a reference to the given element of |d_|. + uint8_t& at(int x, int y); + + // fillAt sets the |len| elements at (x, y) to |value|. + void fillAt(int x, int y, size_t len, uint8_t value); + + // copyTo copies |len| elements from |data| to the elements at (x, y). + void copyTo(int x, int y, const uint8_t* data, size_t len); + + // clipped returns a reference to the given element of |d_|, or to + // |clip_dump_| if the coordinates are out of bounds. + uint8_t& clipped(int x, int y); + + // GF28Mul returns the product of |a| and |b| (which must be field elements, + // i.e. < 256) in the field GF(2^8) mod x^8 + x^4 + x^3 + x^2 + 1. + static uint8_t GF28Mul(uint16_t a, uint16_t b); + + // AddErrorCorrection writes the Reed-Solomon expanded version of |in| to + // |out|. + // |out| should have length block_bytes for the code's version. + // |in| should have length block_data_bytes for the code's version. + // |block_bytes| and |block_ec_bytes| must be provided for the current + // version/level/group. + void AddErrorCorrection(base::span<uint8_t> out, + base::span<const uint8_t> in, + size_t block_bytes, + size_t block_ec_bytes); + + // CountPenaltyPoints sums the penalty points for the current, fully drawn, + // code. See table 11. + unsigned CountPenaltyPoints() const; + + // Parameters for the currently-selected version of the QR code. + // Generate() will pick a version that can contain enough data. + // Unowned; nullptr until initialized in Generate(). + const QRVersionInfo* version_info_ = nullptr; + + // d_ represents a QR code with one byte per pixel. Each byte is one pixel. + // The LSB is set if the pixel is "black". The second bit is set if the pixel + // is part of the structure of the QR code, i.e. finder or alignment symbols, + // timing patterns, or format data. + // Initialized and possibly reinitialized in Generate(). + std::vector<uint8_t> d_; + + // clip_dump_ is the target of paints that would otherwise fall outside of the + // QR code. + uint8_t clip_dump_; +}; + +#endif // COMPONENTS_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_
diff --git a/components/qr_code_generator/qr_code_generator_unittest.cc b/components/qr_code_generator/qr_code_generator_unittest.cc new file mode 100644 index 0000000..718af64d6 --- /dev/null +++ b/components/qr_code_generator/qr_code_generator_unittest.cc
@@ -0,0 +1,55 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/qr_code_generator/qr_code_generator.h" + +#include "testing/gtest/include/gtest/gtest.h" + +TEST(QRCodeGenerator, Generate) { + // Without a QR decoder implementation, there's a limit to how much we can + // test the QR encoder. Therefore this test just runs a generation to ensure + // that no DCHECKs are hit and that the output has the correct structure. When + // run under ASan, this will also check that every byte of the output has been + // written to. + QRCodeGenerator qr; + uint8_t input[QRCodeGenerator::V5::kInputBytes]; + memset(input, 'a', sizeof(input)); + base::Optional<QRCodeGenerator::GeneratedCode> qr_code = qr.Generate(input); + ASSERT_NE(qr_code, base::nullopt); + auto& qr_data = qr_code->data; + + int index = 0; + ASSERT_EQ(qr_data.size(), + static_cast<size_t>(QRCodeGenerator::V5::kTotalSize)); + for (int y = 0; y < QRCodeGenerator::V5::kSize; y++) { + for (int x = 0; x < QRCodeGenerator::V5::kSize; x++) { + ASSERT_EQ(0, qr_data[index++] & 0b11111100); + } + } +} + +TEST(QRCodeGenerator, GenerateVersionSelection) { + // Ensure that dynamic version selection works, + // even when reusing the same QR Generator object. + // Longer inputs produce longer codes. + QRCodeGenerator qr; + + uint8_t input_small[10]; + memset(input_small, 'a', sizeof(input_small)); + base::Optional<QRCodeGenerator::GeneratedCode> qr_code_small( + qr.Generate(input_small)); + ASSERT_NE(qr_code_small, base::nullopt); + int size_small = qr_code_small->data.size(); + + uint8_t input_large[100]; + memset(input_large, 'a', sizeof(input_large)); + base::Optional<QRCodeGenerator::GeneratedCode> qr_code_large( + qr.Generate(input_large)); + ASSERT_NE(qr_code_large, base::nullopt); + int size_large = qr_code_large->data.size(); + + ASSERT_GT(size_small, 0); + ASSERT_GT(size_large, 0); + ASSERT_GT(size_large, size_small); +}
diff --git a/components/qr_code_generator/qr_print.cc b/components/qr_code_generator/qr_print.cc new file mode 100644 index 0000000..277f389 --- /dev/null +++ b/components/qr_code_generator/qr_print.cc
@@ -0,0 +1,87 @@ +// Copyright 2020 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. + +// This helper binary can be compiled to aid in development / debugging of the +// QR generation code. It prints a QR code to the console and thus allows much +// faster iteration. It is not built by default, see the BUILD.gn in this +// directory. + +#include <stdio.h> + +#include <utility> + +#include "base/containers/span.h" +#include "base/optional.h" +#include "base/strings/string_number_conversions.h" +#include "components/qr_code_generator/qr_code_generator.h" + +// kTerminalBackgroundIsBright controls the output polarity. Many QR scanners +// will cope with inverted bright / dark but, if you have a bright terminal +// background, you may need to change this. +constexpr bool kTerminalBackgroundIsBright = false; + +// kPaint is a pair of UTF-8 encoded code points for U+2588 ("FULL BLOCK"). +static constexpr char kPaint[] = "\xe2\x96\x88\xe2\x96\x88"; +static constexpr char kNoPaint[] = " "; + +static void PrintHorizontalLine(const char* white, int size) { + for (int x = 0; x < size + 2; x++) { + fputs(white, stdout); + } + fputs("\n", stdout); +} + +int main(int argc, char** argv) { + // Presubmits don't allow fprintf to a variable called |stderr|. + FILE* const STDERR = stderr; + + if (argc < 2 || argc > 3) { + fprintf(STDERR, "Usage: %s <input string> [mask number]\n", argv[0]); + return 1; + } + + const uint8_t* const input = reinterpret_cast<const uint8_t*>(argv[1]); + const size_t input_len = strlen(argv[1]); + + base::Optional<uint8_t> mask; + if (argc == 3) { + unsigned mask_unsigned; + if (!base::StringToUint(argv[2], &mask_unsigned) || mask_unsigned > 7) { + fprintf(STDERR, "Mask numbers run from zero to seven.\n"); + return 1; + } + mask = static_cast<uint8_t>(mask_unsigned); + } + + const char* black = kNoPaint; + const char* white = kPaint; + if (kTerminalBackgroundIsBright) { + std::swap(black, white); + } + + QRCodeGenerator generator; + base::Optional<QRCodeGenerator::GeneratedCode> code = + generator.Generate(base::span<const uint8_t>(input, input_len), mask); + if (!code) { + fprintf(STDERR, "Input too long to be encoded.\n"); + return 2; + } + + const int size = code->qr_size; + PrintHorizontalLine(white, size); + + int i = 0; + for (int y = 0; y < size; y++) { + fputs(white, stdout); + for (int x = 0; x < size; x++) { + fputs((code->data[i++] & 1) ? black : white, stdout); + } + fputs(white, stdout); + fputs("\n", stdout); + } + + PrintHorizontalLine(white, size); + + return 0; +}
diff --git a/components/safe_browsing/OWNERS b/components/safe_browsing/OWNERS index 70e4b68..e2415af 100644 --- a/components/safe_browsing/OWNERS +++ b/components/safe_browsing/OWNERS
@@ -1,3 +1,4 @@ drubery@chromium.org nparker@chromium.org vakh@chromium.org +xinghuilu@chromium.org
diff --git a/components/search/repeatable_queries/repeatable_queries_service.cc b/components/search/repeatable_queries/repeatable_queries_service.cc index 4725521..0564f40 100644 --- a/components/search/repeatable_queries/repeatable_queries_service.cc +++ b/components/search/repeatable_queries/repeatable_queries_service.cc
@@ -184,8 +184,12 @@ } // Delete all the Google search URLs for the given query from history. - history_service_->DeleteMatchingURLsForKeyword( - template_url_service_->GetDefaultSearchProvider()->id(), it->query); + const TemplateURL* default_provider = + template_url_service_->GetDefaultSearchProvider(); + if (default_provider) { + history_service_->DeleteMatchingURLsForKeyword(default_provider->id(), + it->query); + } // Make sure the query is not suggested again. MarkQueryAsDeleted(it->query); @@ -227,10 +231,12 @@ } GURL RepeatableQueriesService::GetQueryDestinationURL( - const base::string16& query) { + const base::string16& query, + const TemplateURL* search_provider) { + DCHECK(search_provider); + TemplateURLRef::SearchTermsArgs search_terms_args(query); - const TemplateURLRef& search_url_ref = - template_url_service_->GetDefaultSearchProvider()->url_ref(); + const TemplateURLRef& search_url_ref = search_provider->url_ref(); const SearchTermsData& search_terms_data = template_url_service_->search_terms_data(); DCHECK(search_url_ref.SupportsReplacement(search_terms_data)); @@ -242,6 +248,8 @@ const std::string& deletion_url) { const auto* default_provider = template_url_service_->GetDefaultSearchProvider(); + if (!default_provider) + return GURL(); const SearchTermsData& search_terms_data = template_url_service_->search_terms_data(); GURL request_url = default_provider->GenerateSearchURL(search_terms_data); @@ -345,6 +353,11 @@ void RepeatableQueriesService::RepeatableQueriesParsed( data_decoder::DataDecoder::ValueOrError result) { + const TemplateURL* default_provider = + template_url_service_->GetDefaultSearchProvider(); + if (!default_provider) + return; + repeatable_queries_.clear(); std::vector<RepeatableQuery> queries; @@ -352,7 +365,8 @@ for (auto& query : queries) { if (IsQueryDeleted(query.query)) continue; - query.destination_url = GetQueryDestinationURL(query.query); + query.destination_url = + GetQueryDestinationURL(query.query, default_provider); repeatable_queries_.push_back(query); if (repeatable_queries_.size() >= kMaxQueries) break; @@ -363,6 +377,11 @@ } void RepeatableQueriesService::GetRepeatableQueriesFromURLDatabase() { + const TemplateURL* default_provider = + template_url_service_->GetDefaultSearchProvider(); + if (!default_provider) + return; + repeatable_queries_.clear(); // Fail if the in-memory URLDatabase is not available. @@ -392,7 +411,7 @@ if (IsQueryDeleted(repeatable_query.query)) continue; repeatable_query.destination_url = - GetQueryDestinationURL(repeatable_query.query); + GetQueryDestinationURL(repeatable_query.query, default_provider); repeatable_queries_.push_back(repeatable_query); if (repeatable_queries_.size() >= kMaxQueries) break; @@ -444,6 +463,9 @@ })"); GURL request_url = GetQueryDeletionURL(deletion_url); + if (!request_url.is_valid()) + return; + auto deletion_request = std::make_unique<network::ResourceRequest>(); variations::AppendVariationsHeaderUnknownSignedIn( request_url, variations::InIncognito::kNo, deletion_request.get());
diff --git a/components/search/repeatable_queries/repeatable_queries_service.h b/components/search/repeatable_queries/repeatable_queries_service.h index 7076d383..3b67a8a 100644 --- a/components/search/repeatable_queries/repeatable_queries_service.h +++ b/components/search/repeatable_queries/repeatable_queries_service.h
@@ -19,6 +19,7 @@ class SearchProviderObserver; class TemplateURLService; +class TemplateURL; namespace base { class SequencedTaskRunner; @@ -119,8 +120,10 @@ // Called when the signin status changes. void SigninStatusChanged(); - // Returns the server destination URL for |query|. - GURL GetQueryDestinationURL(const base::string16& query); + // Returns the server destination URL for |query| with |search_provider|. + // |search_provider| may not be nullptr. + GURL GetQueryDestinationURL(const base::string16& query, + const TemplateURL* search_provider); // Returns the resolved deletion URL for the given relative deletion URL. GURL GetQueryDeletionURL(const std::string& deletion_url);
diff --git a/components/search/repeatable_queries/repeatable_queries_service_unittest.cc b/components/search/repeatable_queries/repeatable_queries_service_unittest.cc index 7629ff6..e2a8f8e 100644 --- a/components/search/repeatable_queries/repeatable_queries_service_unittest.cc +++ b/components/search/repeatable_queries/repeatable_queries_service_unittest.cc
@@ -159,8 +159,10 @@ RepeatableQueriesService::FlushForTesting(std::move(flushed)); } - GURL GetQueryDestinationURL(const base::string16& query) { - return RepeatableQueriesService::GetQueryDestinationURL(query); + GURL GetQueryDestinationURL(const base::string16& query, + const TemplateURL* search_provider) { + return RepeatableQueriesService::GetQueryDestinationURL(query, + search_provider); } GURL GetQueryDeletionURL(const std::string& deletion_url) { @@ -252,7 +254,8 @@ void SignOut() { identity_env_->SetCookieAccounts({}); } GURL GetQueryDestinationURL(const std::string& query) { - return service_->GetQueryDestinationURL(base::ASCIIToUTF16(query)); + return service_->GetQueryDestinationURL(base::ASCIIToUTF16(query), + default_search_provider()); } void RefreshAndMaybeWaitForService() {
diff --git a/components/services/storage/public/mojom/BUILD.gn b/components/services/storage/public/mojom/BUILD.gn index 3fcc139..305f12c 100644 --- a/components/services/storage/public/mojom/BUILD.gn +++ b/components/services/storage/public/mojom/BUILD.gn
@@ -7,10 +7,10 @@ mojom("mojom") { sources = [ "blob_storage_context.mojom", + "file_system_access_context.mojom", "indexed_db_control.mojom", "indexed_db_control_test.mojom", "local_storage_control.mojom", - "native_file_system_context.mojom", "origin_context.mojom", "partition.mojom", "service_worker_database.mojom",
diff --git a/components/services/storage/public/mojom/file_system_access_context.mojom b/components/services/storage/public/mojom/file_system_access_context.mojom new file mode 100644 index 0000000..a8cac2b --- /dev/null +++ b/components/services/storage/public/mojom/file_system_access_context.mojom
@@ -0,0 +1,36 @@ +// Copyright 2020 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. + +module storage.mojom; + +import "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom"; +import "url/mojom/origin.mojom"; + + +// This interface is the primary access point to Chrome's File System Access API +// implementation. This interface lives in the browser process and is used by +// IndexedDB in the storage service to serialize and deserialize Native File +// System handles. +// +// This interface has capabilities that should NOT be accessible to a renderer. +// For example, DeserializeHandle can give access to arbitrary paths on disk. +interface FileSystemAccessContext { + // Serializes a handle represented by |token|. If token is not valid this + // returns an empty array, otherwise this returns a serialization that can + // be stored to disk by for example IndexedDB, and then later read back and + // passed to DeserializeHandle to turn it back into a token. + SerializeHandle( + pending_remote<blink.mojom.FileSystemAccessTransferToken> token) + => (array<uint8> bits); + + // Deserializes a handle. |bits| should be what was returned by + // SerializeHandle earlier. The resulting |token| can be used by renderers for + // |origin| to get access to the underlying file or directory. + // If deserialization fails, |token| is not bound, and attempts to use it will + // fail. + DeserializeHandle( + url.mojom.Origin origin, + array<uint8> bits, + pending_receiver<blink.mojom.FileSystemAccessTransferToken> token); +};
diff --git a/components/services/storage/public/mojom/native_file_system_context.mojom b/components/services/storage/public/mojom/native_file_system_context.mojom deleted file mode 100644 index 76eb755d..0000000 --- a/components/services/storage/public/mojom/native_file_system_context.mojom +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright 2020 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. - -module storage.mojom; - -import "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom"; -import "url/mojom/origin.mojom"; - - -// This interface is the primary access point to Chrome's Native File System API -// implementation. This interface lives in the browser process and is used by -// IndexedDB in the storage service to serialize and deserialize Native File -// System handles. -// -// This interface has capabilities that should NOT be accessible to a renderer. -// For example, DeserializeHandle can give access to arbitrary paths on disk. -interface NativeFileSystemContext { - // Serializes a handle represented by |token|. If token is not valid this - // returns an empty array, otherwise this returns a serialization that can - // be stored to disk by for example IndexedDB, and then later read back and - // passed to DeserializeHandle to turn it back into a token. - SerializeHandle( - pending_remote<blink.mojom.NativeFileSystemTransferToken> token) - => (array<uint8> bits); - - // Deserializes a handle. |bits| should be what was returned by - // SerializeHandle earlier. The resulting |token| can be used by renderers for - // |origin| to get access to the underlying file or directory. - // If deserialization fails, |token| is not bound, and attempts to use it will - // fail. - DeserializeHandle( - url.mojom.Origin origin, - array<uint8> bits, - pending_receiver<blink.mojom.NativeFileSystemTransferToken> token); -};
diff --git a/components/site_engagement/content/BUILD.gn b/components/site_engagement/content/BUILD.gn new file mode 100644 index 0000000..8e82a6d --- /dev/null +++ b/components/site_engagement/content/BUILD.gn
@@ -0,0 +1,34 @@ +# Copyright 2020 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. + +source_set("content") { + sources = [ + "engagement_type.h", + "site_engagement_metrics.cc", + "site_engagement_metrics.h", + "site_engagement_score.cc", + "site_engagement_score.h", + ] + deps = [ + "//base", + "//components/content_settings/core/browser", + "//components/content_settings/core/common", + "//components/security_state/core", + "//components/site_engagement/core/mojom:mojo_bindings", + "//components/variations", + "//third_party/blink/public/mojom:mojom_platform_headers", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "site_engagement_score_unittest.cc" ] + deps = [ + ":content", + "//base", + "//base/test:test_support", + "//components/site_engagement/core/mojom:mojo_bindings", + "//testing/gtest", + ] +}
diff --git a/components/site_engagement/content/DEPS b/components/site_engagement/content/DEPS new file mode 100644 index 0000000..7f2ff9e --- /dev/null +++ b/components/site_engagement/content/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+components/content_settings/core", + "+components/variations", + "+third_party/blink/public/mojom", +]
diff --git a/components/site_engagement/content/engagement_type.h b/components/site_engagement/content/engagement_type.h new file mode 100644 index 0000000..71a51a5 --- /dev/null +++ b/components/site_engagement/content/engagement_type.h
@@ -0,0 +1,31 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SITE_ENGAGEMENT_CONTENT_ENGAGEMENT_TYPE_H_ +#define COMPONENTS_SITE_ENGAGEMENT_CONTENT_ENGAGEMENT_TYPE_H_ + +namespace site_engagement { + +// This is used to back a UMA histogram, so it should be treated as +// append-only. Any new values should be inserted immediately prior to +// kLast and added to SiteEngagementServiceEngagementType in +// tools/metrics/histograms/enums.xml. +// TODO(calamity): Document each of these engagement types. +enum class EngagementType { + kNavigation, + kKeypress, + kMouse, + kTouchGesture, + kScroll, + kMediaHidden, + kMediaVisible, + kWebappShortcutLaunch, + kFirstDailyEngagement, + kNotificationInteraction, + kLast, +}; + +} // namespace site_engagement + +#endif // COMPONENTS_SITE_ENGAGEMENT_CONTENT_ENGAGEMENT_TYPE_H_
diff --git a/components/site_engagement/content/site_engagement_metrics.cc b/components/site_engagement/content/site_engagement_metrics.cc new file mode 100644 index 0000000..23c8974 --- /dev/null +++ b/components/site_engagement/content/site_engagement_metrics.cc
@@ -0,0 +1,135 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/site_engagement/content/site_engagement_metrics.h" + +#include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "components/site_engagement/content/engagement_type.h" +#include "components/site_engagement/content/site_engagement_score.h" + +namespace site_engagement { + +namespace { + +// These numbers are used as suffixes for the +// SiteEngagementService.EngagementScoreBucket_* histogram. If these bases +// change, the EngagementScoreBuckets suffix in histograms.xml should be +// updated. +const int kEngagementBucketHistogramBuckets[] = {0, 10, 20, 30, 40, 50, + 60, 70, 80, 90, 100}; + +} // namespace + +const char SiteEngagementMetrics::kTotalEngagementHistogram[] = + "SiteEngagementService.TotalEngagement"; + +const char SiteEngagementMetrics::kTotalOriginsHistogram[] = + "SiteEngagementService.OriginsEngaged"; + +const char SiteEngagementMetrics::kMeanEngagementHistogram[] = + "SiteEngagementService.MeanEngagement"; + +const char SiteEngagementMetrics::kMedianEngagementHistogram[] = + "SiteEngagementService.MedianEngagement"; + +const char SiteEngagementMetrics::kEngagementScoreHistogram[] = + "SiteEngagementService.EngagementScore"; + +const char SiteEngagementMetrics::kOriginsWithMaxEngagementHistogram[] = + "SiteEngagementService.OriginsWithMaxEngagement"; + +const char SiteEngagementMetrics::kOriginsWithMaxDailyEngagementHistogram[] = + "SiteEngagementService.OriginsWithMaxDailyEngagement"; + +const char SiteEngagementMetrics::kEngagementTypeHistogram[] = + "SiteEngagementService.EngagementType"; + +const char SiteEngagementMetrics::kEngagementBucketHistogramBase[] = + "SiteEngagementService.EngagementScoreBucket_"; + +const char SiteEngagementMetrics::kDaysSinceLastShortcutLaunchHistogram[] = + "SiteEngagementService.DaysSinceLastShortcutLaunch"; + +void SiteEngagementMetrics::RecordTotalSiteEngagement(double total_engagement) { + UMA_HISTOGRAM_COUNTS_10000(kTotalEngagementHistogram, total_engagement); +} + +void SiteEngagementMetrics::RecordTotalOriginsEngaged(int num_origins) { + UMA_HISTOGRAM_COUNTS_10000(kTotalOriginsHistogram, num_origins); +} + +void SiteEngagementMetrics::RecordMeanEngagement(double mean_engagement) { + UMA_HISTOGRAM_COUNTS_100(kMeanEngagementHistogram, mean_engagement); +} + +void SiteEngagementMetrics::RecordMedianEngagement(double median_engagement) { + UMA_HISTOGRAM_COUNTS_100(kMedianEngagementHistogram, median_engagement); +} + +void SiteEngagementMetrics::RecordEngagementScores( + const std::vector<mojom::SiteEngagementDetails>& details) { + if (details.empty()) + return; + + std::map<int, int> score_buckets; + for (size_t i = 0; i < base::size(kEngagementBucketHistogramBuckets); ++i) + score_buckets[kEngagementBucketHistogramBuckets[i]] = 0; + + for (const auto& detail : details) { + double score = detail.total_score; + UMA_HISTOGRAM_COUNTS_100(kEngagementScoreHistogram, score); + + auto bucket = score_buckets.lower_bound(score); + if (bucket == score_buckets.end()) + continue; + + bucket->second++; + } + + for (const auto& b : score_buckets) { + std::string histogram_name = + kEngagementBucketHistogramBase + base::NumberToString(b.first); + + base::LinearHistogram::FactoryGet( + histogram_name, 1, 100, 10, + base::HistogramBase::kUmaTargetedHistogramFlag) + ->Add(b.second * 100 / details.size()); + } +} + +void SiteEngagementMetrics::RecordOriginsWithMaxEngagement(int total_origins) { + UMA_HISTOGRAM_COUNTS_100(kOriginsWithMaxEngagementHistogram, total_origins); +} + +void SiteEngagementMetrics::RecordOriginsWithMaxDailyEngagement( + int total_origins) { + UMA_HISTOGRAM_COUNTS_100(kOriginsWithMaxDailyEngagementHistogram, + total_origins); +} + +void SiteEngagementMetrics::RecordEngagement(EngagementType type) { + UMA_HISTOGRAM_ENUMERATION(kEngagementTypeHistogram, type, + EngagementType::kLast); +} + +void SiteEngagementMetrics::RecordDaysSinceLastShortcutLaunch(int days) { + UMA_HISTOGRAM_COUNTS_100(kDaysSinceLastShortcutLaunchHistogram, days); +} + +// static +std::vector<std::string> +SiteEngagementMetrics::GetEngagementBucketHistogramNames() { + std::vector<std::string> histogram_names; + for (size_t i = 0; i < base::size(kEngagementBucketHistogramBuckets); ++i) { + histogram_names.push_back( + kEngagementBucketHistogramBase + + base::NumberToString(kEngagementBucketHistogramBuckets[i])); + } + + return histogram_names; +} + +} // namespace site_engagement
diff --git a/components/site_engagement/content/site_engagement_metrics.h b/components/site_engagement/content/site_engagement_metrics.h new file mode 100644 index 0000000..28c59a61 --- /dev/null +++ b/components/site_engagement/content/site_engagement_metrics.h
@@ -0,0 +1,55 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_METRICS_H_ +#define COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_METRICS_H_ + +#include <vector> + +#include "base/gtest_prod_util.h" +#include "components/site_engagement/core/mojom/site_engagement_details.mojom.h" +#include "url/gurl.h" + +namespace site_engagement { + +enum class EngagementType; + +// Helper class managing the UMA histograms for the Site Engagement Service. +class SiteEngagementMetrics { + public: + static void RecordTotalSiteEngagement(double total_engagement); + static void RecordTotalOriginsEngaged(int total_origins); + static void RecordMeanEngagement(double mean_engagement); + static void RecordMedianEngagement(double median_engagement); + static void RecordEngagementScores( + const std::vector<mojom::SiteEngagementDetails>& details); + static void RecordOriginsWithMaxEngagement(int total_origins); + static void RecordOriginsWithMaxDailyEngagement(int total_origins); + static void RecordEngagement(EngagementType type); + static void RecordDaysSinceLastShortcutLaunch(int days); + + private: + FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, CheckHistograms); + FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, + GetTotalNotificationPoints); + FRIEND_TEST_ALL_PREFIXES(SiteEngagementServiceTest, LastShortcutLaunch); + FRIEND_TEST_ALL_PREFIXES(SiteEngagementHelperTest, + MixedInputEngagementAccumulation); + static const char kTotalEngagementHistogram[]; + static const char kTotalOriginsHistogram[]; + static const char kMeanEngagementHistogram[]; + static const char kMedianEngagementHistogram[]; + static const char kEngagementScoreHistogram[]; + static const char kOriginsWithMaxEngagementHistogram[]; + static const char kOriginsWithMaxDailyEngagementHistogram[]; + static const char kEngagementTypeHistogram[]; + static const char kEngagementBucketHistogramBase[]; + static const char kDaysSinceLastShortcutLaunchHistogram[]; + + static std::vector<std::string> GetEngagementBucketHistogramNames(); +}; + +} // namespace site_engagement + +#endif // COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_METRICS_H_
diff --git a/components/site_engagement/content/site_engagement_score.cc b/components/site_engagement/content/site_engagement_score.cc new file mode 100644 index 0000000..fb9c170d --- /dev/null +++ b/components/site_engagement/content/site_engagement_score.cc
@@ -0,0 +1,407 @@ +// 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 "components/site_engagement/content/site_engagement_score.h" + +#include <algorithm> +#include <cmath> +#include <utility> + +#include "base/no_destructor.h" +#include "base/strings/string_number_conversions.h" +#include "base/time/clock.h" +#include "base/time/time.h" +#include "base/values.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_types.h" +#include "components/site_engagement/content/engagement_type.h" +#include "components/site_engagement/content/site_engagement_metrics.h" +#include "components/variations/variations_associated_data.h" +#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h" + +namespace site_engagement { + +namespace { + +// Delta within which to consider scores equal. +const double kScoreDelta = 0.001; + +// Delta within which to consider internal time values equal. Internal time +// values are in microseconds, so this delta comes out at one second. +const double kTimeDelta = 1000000; + +// Number of days after the last launch of an origin from an installed shortcut +// for which WEB_APP_INSTALLED_POINTS will be added to the engagement score. +const int kMaxDaysSinceShortcutLaunch = 10; + +bool DoublesConsideredDifferent(double value1, double value2, double delta) { + double abs_difference = fabs(value1 - value2); + return abs_difference > delta; +} + +std::unique_ptr<base::DictionaryValue> GetSiteEngagementScoreDictForSettings( + const HostContentSettingsMap* settings, + const GURL& origin_url) { + if (!settings) + return std::make_unique<base::DictionaryValue>(); + + std::unique_ptr<base::DictionaryValue> value = + base::DictionaryValue::From(settings->GetWebsiteSetting( + origin_url, origin_url, ContentSettingsType::SITE_ENGAGEMENT, NULL)); + + if (value.get()) + return value; + + return std::make_unique<base::DictionaryValue>(); +} + +} // namespace + +const double SiteEngagementScore::kMaxPoints = 100; + +const char SiteEngagementScore::kRawScoreKey[] = "rawScore"; +const char SiteEngagementScore::kPointsAddedTodayKey[] = "pointsAddedToday"; +const char SiteEngagementScore::kLastEngagementTimeKey[] = "lastEngagementTime"; +const char SiteEngagementScore::kLastShortcutLaunchTimeKey[] = + "lastShortcutLaunchTime"; + +// static +SiteEngagementScore::ParamValues& SiteEngagementScore::GetParamValues() { + static base::NoDestructor<ParamValues> param_values([]() { + SiteEngagementScore::ParamValues param_values; + param_values[MAX_POINTS_PER_DAY] = {"max_points_per_day", 15}; + param_values[DECAY_PERIOD_IN_HOURS] = {"decay_period_in_hours", 2}; + param_values[DECAY_POINTS] = {"decay_points", 0}; + param_values[DECAY_PROPORTION] = {"decay_proportion", 0.984}; + param_values[SCORE_CLEANUP_THRESHOLD] = {"score_cleanup_threshold", 0.5}; + param_values[NAVIGATION_POINTS] = {"navigation_points", 1.5}; + param_values[USER_INPUT_POINTS] = {"user_input_points", 0.6}; + param_values[VISIBLE_MEDIA_POINTS] = {"visible_media_playing_points", 0.06}; + param_values[HIDDEN_MEDIA_POINTS] = {"hidden_media_playing_points", 0.01}; + param_values[WEB_APP_INSTALLED_POINTS] = {"web_app_installed_points", 5}; + param_values[FIRST_DAILY_ENGAGEMENT] = {"first_daily_engagement_points", + 1.5}; + param_values[BOOTSTRAP_POINTS] = {"bootstrap_points", 24}; + param_values[MEDIUM_ENGAGEMENT_BOUNDARY] = {"medium_engagement_boundary", + 15}; + param_values[HIGH_ENGAGEMENT_BOUNDARY] = {"high_engagement_boundary", 50}; + param_values[MAX_DECAYS_PER_SCORE] = {"max_decays_per_score", 4}; + param_values[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS] = { + "last_engagement_grace_period_in_hours", 1}; + param_values[NOTIFICATION_INTERACTION_POINTS] = { + "notification_interaction_points", 1}; + return param_values; + }()); + return *param_values; +} + +double SiteEngagementScore::GetMaxPointsPerDay() { + return GetParamValues()[MAX_POINTS_PER_DAY].second; +} + +double SiteEngagementScore::GetDecayPeriodInHours() { + return GetParamValues()[DECAY_PERIOD_IN_HOURS].second; +} + +double SiteEngagementScore::GetDecayPoints() { + return GetParamValues()[DECAY_POINTS].second; +} + +double SiteEngagementScore::GetDecayProportion() { + return GetParamValues()[DECAY_PROPORTION].second; +} + +double SiteEngagementScore::GetScoreCleanupThreshold() { + return GetParamValues()[SCORE_CLEANUP_THRESHOLD].second; +} + +double SiteEngagementScore::GetNavigationPoints() { + return GetParamValues()[NAVIGATION_POINTS].second; +} + +double SiteEngagementScore::GetUserInputPoints() { + return GetParamValues()[USER_INPUT_POINTS].second; +} + +double SiteEngagementScore::GetVisibleMediaPoints() { + return GetParamValues()[VISIBLE_MEDIA_POINTS].second; +} + +double SiteEngagementScore::GetHiddenMediaPoints() { + return GetParamValues()[HIDDEN_MEDIA_POINTS].second; +} + +double SiteEngagementScore::GetWebAppInstalledPoints() { + return GetParamValues()[WEB_APP_INSTALLED_POINTS].second; +} + +double SiteEngagementScore::GetFirstDailyEngagementPoints() { + return GetParamValues()[FIRST_DAILY_ENGAGEMENT].second; +} + +double SiteEngagementScore::GetBootstrapPoints() { + return GetParamValues()[BOOTSTRAP_POINTS].second; +} + +double SiteEngagementScore::GetMediumEngagementBoundary() { + return GetParamValues()[MEDIUM_ENGAGEMENT_BOUNDARY].second; +} + +double SiteEngagementScore::GetHighEngagementBoundary() { + return GetParamValues()[HIGH_ENGAGEMENT_BOUNDARY].second; +} + +double SiteEngagementScore::GetMaxDecaysPerScore() { + return GetParamValues()[MAX_DECAYS_PER_SCORE].second; +} + +double SiteEngagementScore::GetLastEngagementGracePeriodInHours() { + return GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second; +} + +double SiteEngagementScore::GetNotificationInteractionPoints() { + return GetParamValues()[NOTIFICATION_INTERACTION_POINTS].second; +} + +void SiteEngagementScore::SetParamValuesForTesting() { + GetParamValues()[MAX_POINTS_PER_DAY].second = 5; + GetParamValues()[DECAY_PERIOD_IN_HOURS].second = 7 * 24; + GetParamValues()[DECAY_POINTS].second = 5; + GetParamValues()[NAVIGATION_POINTS].second = 0.5; + GetParamValues()[USER_INPUT_POINTS].second = 0.05; + GetParamValues()[VISIBLE_MEDIA_POINTS].second = 0.02; + GetParamValues()[HIDDEN_MEDIA_POINTS].second = 0.01; + GetParamValues()[WEB_APP_INSTALLED_POINTS].second = 5; + GetParamValues()[BOOTSTRAP_POINTS].second = 8; + GetParamValues()[MEDIUM_ENGAGEMENT_BOUNDARY].second = 5; + GetParamValues()[HIGH_ENGAGEMENT_BOUNDARY].second = 50; + GetParamValues()[MAX_DECAYS_PER_SCORE].second = 1; + GetParamValues()[LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS].second = 72; + GetParamValues()[NOTIFICATION_INTERACTION_POINTS].second = 1; + + // This is set to values that avoid interference with tests and are set when + // testing these features. + GetParamValues()[FIRST_DAILY_ENGAGEMENT].second = 0; + GetParamValues()[DECAY_PROPORTION].second = 1; + GetParamValues()[SCORE_CLEANUP_THRESHOLD].second = 0; +} +// static +void SiteEngagementScore::UpdateFromVariations(const char* param_name) { + double param_vals[MAX_VARIATION]; + + for (int i = 0; i < MAX_VARIATION; ++i) { + std::string param_string = variations::GetVariationParamValue( + param_name, GetParamValues()[i].first); + + // Bail out if we didn't get a param string for the key, or if we couldn't + // convert the param string to a double, or if we get a negative value. + if (param_string.empty() || + !base::StringToDouble(param_string, ¶m_vals[i]) || + param_vals[i] < 0) { + return; + } + } + + // Once we're sure everything is valid, assign the variation to the param + // values array. + for (int i = 0; i < MAX_VARIATION; ++i) + SiteEngagementScore::GetParamValues()[i].second = param_vals[i]; +} + +SiteEngagementScore::SiteEngagementScore(base::Clock* clock, + const GURL& origin, + HostContentSettingsMap* settings) + : SiteEngagementScore( + clock, + origin, + GetSiteEngagementScoreDictForSettings(settings, origin)) { + settings_map_ = settings; +} + +SiteEngagementScore::SiteEngagementScore(SiteEngagementScore&& other) = default; + +SiteEngagementScore::~SiteEngagementScore() {} + +SiteEngagementScore& SiteEngagementScore::operator=( + SiteEngagementScore&& other) = default; + +void SiteEngagementScore::AddPoints(double points) { + DCHECK_NE(0, points); + + // As the score is about to be updated, commit any decay that has happened + // since the last update. + raw_score_ = DecayedScore(); + + base::Time now = clock_->Now(); + if (!last_engagement_time_.is_null() && + now.LocalMidnight() != last_engagement_time_.LocalMidnight()) { + points_added_today_ = 0; + } + + if (points_added_today_ == 0) { + // Award bonus engagement for the first engagement of the day for a site. + points += GetFirstDailyEngagementPoints(); + SiteEngagementMetrics::RecordEngagement( + EngagementType::kFirstDailyEngagement); + } + + double to_add = std::min(kMaxPoints - raw_score_, + GetMaxPointsPerDay() - points_added_today_); + to_add = std::min(to_add, points); + + points_added_today_ += to_add; + raw_score_ += to_add; + + last_engagement_time_ = now; +} + +double SiteEngagementScore::GetTotalScore() const { + return std::min(DecayedScore() + BonusIfShortcutLaunched(), kMaxPoints); +} + +mojom::SiteEngagementDetails SiteEngagementScore::GetDetails() const { + mojom::SiteEngagementDetails engagement; + engagement.origin = origin_; + engagement.base_score = DecayedScore(); + engagement.installed_bonus = BonusIfShortcutLaunched(); + engagement.total_score = GetTotalScore(); + return engagement; +} + +void SiteEngagementScore::Commit() { + DCHECK(settings_map_); + if (!UpdateScoreDict(score_dict_.get())) + return; + + settings_map_->SetWebsiteSettingDefaultScope( + origin_, GURL(), ContentSettingsType::SITE_ENGAGEMENT, + std::move(score_dict_)); +} + +blink::mojom::EngagementLevel SiteEngagementScore::GetEngagementLevel() const { + DCHECK_LT(GetMediumEngagementBoundary(), GetHighEngagementBoundary()); + + double score = GetTotalScore(); + if (score == 0) + return blink::mojom::EngagementLevel::NONE; + + if (score < 1) + return blink::mojom::EngagementLevel::MINIMAL; + + if (score < GetMediumEngagementBoundary()) + return blink::mojom::EngagementLevel::LOW; + + if (score < GetHighEngagementBoundary()) + return blink::mojom::EngagementLevel::MEDIUM; + + if (score < SiteEngagementScore::kMaxPoints) + return blink::mojom::EngagementLevel::HIGH; + + return blink::mojom::EngagementLevel::MAX; +} + +bool SiteEngagementScore::MaxPointsPerDayAdded() const { + if (!last_engagement_time_.is_null() && + clock_->Now().LocalMidnight() != last_engagement_time_.LocalMidnight()) { + return false; + } + + return points_added_today_ == GetMaxPointsPerDay(); +} + +void SiteEngagementScore::Reset(double points, + const base::Time last_engagement_time) { + raw_score_ = points; + points_added_today_ = 0; + + // This must be set in order to prevent the score from decaying when read. + last_engagement_time_ = last_engagement_time; +} + +bool SiteEngagementScore::UpdateScoreDict(base::DictionaryValue* score_dict) { + double raw_score_orig = 0; + double points_added_today_orig = 0; + double last_engagement_time_internal_orig = 0; + double last_shortcut_launch_time_internal_orig = 0; + + score_dict->GetDouble(kRawScoreKey, &raw_score_orig); + score_dict->GetDouble(kPointsAddedTodayKey, &points_added_today_orig); + score_dict->GetDouble(kLastEngagementTimeKey, + &last_engagement_time_internal_orig); + score_dict->GetDouble(kLastShortcutLaunchTimeKey, + &last_shortcut_launch_time_internal_orig); + bool changed = + DoublesConsideredDifferent(raw_score_orig, raw_score_, kScoreDelta) || + DoublesConsideredDifferent(points_added_today_orig, points_added_today_, + kScoreDelta) || + DoublesConsideredDifferent(last_engagement_time_internal_orig, + last_engagement_time_.ToInternalValue(), + kTimeDelta) || + DoublesConsideredDifferent(last_shortcut_launch_time_internal_orig, + last_shortcut_launch_time_.ToInternalValue(), + kTimeDelta); + + if (!changed) + return false; + + score_dict->SetDouble(kRawScoreKey, raw_score_); + score_dict->SetDouble(kPointsAddedTodayKey, points_added_today_); + score_dict->SetDouble(kLastEngagementTimeKey, + last_engagement_time_.ToInternalValue()); + score_dict->SetDouble(kLastShortcutLaunchTimeKey, + last_shortcut_launch_time_.ToInternalValue()); + + return true; +} + +SiteEngagementScore::SiteEngagementScore( + base::Clock* clock, + const GURL& origin, + std::unique_ptr<base::DictionaryValue> score_dict) + : clock_(clock), + raw_score_(0), + points_added_today_(0), + last_engagement_time_(), + last_shortcut_launch_time_(), + score_dict_(score_dict.release()), + origin_(origin), + settings_map_(nullptr) { + if (!score_dict_) + return; + + score_dict_->GetDouble(kRawScoreKey, &raw_score_); + score_dict_->GetDouble(kPointsAddedTodayKey, &points_added_today_); + + double internal_time; + if (score_dict_->GetDouble(kLastEngagementTimeKey, &internal_time)) + last_engagement_time_ = base::Time::FromInternalValue(internal_time); + if (score_dict_->GetDouble(kLastShortcutLaunchTimeKey, &internal_time)) + last_shortcut_launch_time_ = base::Time::FromInternalValue(internal_time); +} + +double SiteEngagementScore::DecayedScore() const { + // Note that users can change their clock, so from this system's perspective + // time can go backwards. If that does happen and the system detects that the + // current day is earlier than the last engagement, no decay (or growth) is + // applied. + int hours_since_engagement = + (clock_->Now() - last_engagement_time_).InHours(); + if (hours_since_engagement < 0) + return raw_score_; + + int periods = hours_since_engagement / GetDecayPeriodInHours(); + return std::max(0.0, raw_score_ * pow(GetDecayProportion(), periods) - + periods * GetDecayPoints()); +} + +double SiteEngagementScore::BonusIfShortcutLaunched() const { + int days_since_shortcut_launch = + (clock_->Now() - last_shortcut_launch_time_).InDays(); + if (days_since_shortcut_launch <= kMaxDaysSinceShortcutLaunch) + return GetWebAppInstalledPoints(); + return 0; +} + +} // namespace site_engagement
diff --git a/components/site_engagement/content/site_engagement_score.h b/components/site_engagement/content/site_engagement_score.h new file mode 100644 index 0000000..2631c85 --- /dev/null +++ b/components/site_engagement/content/site_engagement_score.h
@@ -0,0 +1,246 @@ +// 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. + +#ifndef COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_SCORE_H_ +#define COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_SCORE_H_ + +#include <array> +#include <memory> +#include <string> +#include <utility> + +#include "base/gtest_prod_util.h" +#include "base/macros.h" +#include "base/time/time.h" +#include "base/values.h" +#include "components/site_engagement/core/mojom/site_engagement_details.mojom-forward.h" +#include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom-forward.h" +#include "url/gurl.h" + +namespace base { +class Clock; +} + +class HostContentSettingsMap; + +namespace site_engagement { + +class SiteEngagementScore { + public: + // The parameters which can be varied via field trial. + enum Variation { + // The maximum number of points that can be accrued in one day. + MAX_POINTS_PER_DAY = 0, + + // The period over which site engagement decays. + DECAY_PERIOD_IN_HOURS, + + // The number of points to decay per period. + DECAY_POINTS, + + // The proportion [0-1] which the current engagement value is multiplied by + // at each decay period, before subtracting DECAY_POINTS. + DECAY_PROPORTION, + + // A score will be erased from the engagement system if it's less than this + // value. + SCORE_CLEANUP_THRESHOLD, + + // The number of points given for navigations. + NAVIGATION_POINTS, + + // The number of points given for user input. + USER_INPUT_POINTS, + + // The number of points given for media playing. Initially calibrated such + // that at least 30 minutes of foreground media would be required to allow a + // site to reach the daily engagement maximum. + VISIBLE_MEDIA_POINTS, + HIDDEN_MEDIA_POINTS, + + // The number of points added to engagement when a site is launched from + // homescreen or added as a bookmark app. This bonus will apply for ten days + // following a launch; each new launch resets the ten days. + WEB_APP_INSTALLED_POINTS, + + // The number of points given for the first engagement event of the day for + // each site. + FIRST_DAILY_ENGAGEMENT, + + // The number of points that the engagement service must accumulate to be + // considered 'useful'. + BOOTSTRAP_POINTS, + + // The boundaries between low/medium and medium/high engagement as returned + // by GetEngagementLevel(). + MEDIUM_ENGAGEMENT_BOUNDARY, + HIGH_ENGAGEMENT_BOUNDARY, + + // The maximum number of decays that a SiteEngagementScore can incur before + // entering a grace period. MAX_DECAYS_PER_SCORE * DECAY_PERIOD_IN_DAYS is + // the max decay period, i.e. the maximum duration permitted for + // (clock_->Now() - score.last_engagement_time()). + MAX_DECAYS_PER_SCORE, + + // If a SiteEngagamentScore has not been accessed or updated for a period + // longer than the max decay period + LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS + // (see above), its last engagement time will be reset to be max decay + // period prior to clock_->Now(). + LAST_ENGAGEMENT_GRACE_PERIOD_IN_HOURS, + + // The number of points given for interacting with a displayed notification. + NOTIFICATION_INTERACTION_POINTS, + + MAX_VARIATION + }; + + // The maximum number of points that are allowed. + static const double kMaxPoints; + + static double GetMaxPointsPerDay(); + static double GetDecayPeriodInHours(); + static double GetDecayPoints(); + static double GetDecayProportion(); + static double GetScoreCleanupThreshold(); + static double GetNavigationPoints(); + static double GetUserInputPoints(); + static double GetVisibleMediaPoints(); + static double GetHiddenMediaPoints(); + static double GetWebAppInstalledPoints(); + static double GetFirstDailyEngagementPoints(); + static double GetBootstrapPoints(); + static double GetMediumEngagementBoundary(); + static double GetHighEngagementBoundary(); + static double GetMaxDecaysPerScore(); + static double GetLastEngagementGracePeriodInHours(); + static double GetNotificationInteractionPoints(); + + // Sets fixed parameter values for testing site engagement. Ensure that any + // newly added parameters receive a fixed value here. + static void SetParamValuesForTesting(); + + // Update the default engagement settings via variations. + static void UpdateFromVariations(const char* param_name); + + // The SiteEngagementScore does not take ownership of |clock|. It is the + // responsibility of the caller to make sure |clock| outlives this + // SiteEngagementScore. + SiteEngagementScore(base::Clock* clock, + const GURL& origin, + HostContentSettingsMap* settings); + SiteEngagementScore(SiteEngagementScore&& other); + ~SiteEngagementScore(); + + SiteEngagementScore& operator=(SiteEngagementScore&& other); + + // Adds |points| to this score, respecting daily limits and the maximum + // possible score. Decays the score if it has not been updated recently + // enough. + void AddPoints(double points); + + // Returns the total score, taking into account the base, bonus and maximum + // values. + double GetTotalScore() const; + + // Returns a structure containing the origin URL and score, and details + // of the base and bonus scores. Note that the |score| is limited to + // kMaxPoints, while the detailed scores are returned raw. + mojom::SiteEngagementDetails GetDetails() const; + + // Writes the values in this score into |settings_map_|. + void Commit(); + + // Returns the discrete engagement level for this score. + blink::mojom::EngagementLevel GetEngagementLevel() const; + + // Returns true if the maximum number of points today has been added. + bool MaxPointsPerDayAdded() const; + + // Resets the score to |points| and resets the daily point limit. If + // |updated_time| is non-null, sets the last engagement time to that value. + void Reset(double points, const base::Time updated_time); + + // Get/set the last time this origin was launched from an installed shortcut. + base::Time last_shortcut_launch_time() const { + return last_shortcut_launch_time_; + } + void set_last_shortcut_launch_time(const base::Time& time) { + last_shortcut_launch_time_ = time; + } + + // Get/set the last time this origin recorded an engagement change. + base::Time last_engagement_time() const { return last_engagement_time_; } + void set_last_engagement_time(const base::Time& time) { + last_engagement_time_ = time; + } + + private: + FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, FirstDailyEngagementBonus); + FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, PartiallyEmptyDictionary); + FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, PopulatedDictionary); + FRIEND_TEST_ALL_PREFIXES(SiteEngagementScoreTest, Reset); + friend class SiteEngagementScoreTest; + friend class SiteEngagementServiceTest; + + using ParamValues = std::array<std::pair<std::string, double>, MAX_VARIATION>; + + // Array holding the values corresponding to each item in Variation array. + static ParamValues& GetParamValues(); + + // Keys used in the content settings dictionary. + static const char kRawScoreKey[]; + static const char kPointsAddedTodayKey[]; + static const char kLastEngagementTimeKey[]; + static const char kLastShortcutLaunchTimeKey[]; + + // This version of the constructor is used in unit tests. + SiteEngagementScore(base::Clock* clock, + const GURL& origin, + std::unique_ptr<base::DictionaryValue> score_dict); + + // Determine the score, accounting for any decay. + double DecayedScore() const; + + // Determine bonus from being installed, and having been launched recently.. + double BonusIfShortcutLaunched() const; + + // Updates the content settings dictionary |score_dict| with the current score + // fields. Returns true if |score_dict| changed, otherwise return false. + bool UpdateScoreDict(base::DictionaryValue* score_dict); + + // The clock used to vend times. Enables time travelling in tests. Owned by + // the SiteEngagementService. + base::Clock* clock_; + + // |raw_score_| is the score before any decay is applied. + double raw_score_; + + // The points added 'today' are tracked to avoid adding more than + // kMaxPointsPerDay on any one day. 'Today' is defined in local time. + double points_added_today_; + + // The last time the score was updated for engagement. Used in conjunction + // with |points_added_today_| to avoid adding more than kMaxPointsPerDay on + // any one day. + base::Time last_engagement_time_; + + // The last time the site with this score was launched from an installed + // shortcut. + base::Time last_shortcut_launch_time_; + + // The dictionary that represents this engagement score. + std::unique_ptr<base::DictionaryValue> score_dict_; + + // The origin this score represents. + GURL origin_; + + // The settings to write this score to when Commit() is called. + HostContentSettingsMap* settings_map_; + + DISALLOW_COPY_AND_ASSIGN(SiteEngagementScore); +}; + +} // namespace site_engagement + +#endif // COMPONENTS_SITE_ENGAGEMENT_CONTENT_SITE_ENGAGEMENT_SCORE_H_
diff --git a/components/site_engagement/content/site_engagement_score_unittest.cc b/components/site_engagement/content/site_engagement_score_unittest.cc new file mode 100644 index 0000000..09cae4d --- /dev/null +++ b/components/site_engagement/content/site_engagement_score_unittest.cc
@@ -0,0 +1,480 @@ +// 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 "components/site_engagement/content/site_engagement_score.h" + +#include <utility> + +#include "base/macros.h" +#include "base/test/simple_test_clock.h" +#include "base/values.h" +#include "components/site_engagement/core/mojom/site_engagement_details.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace site_engagement { + +namespace { + +const int kLessAccumulationsThanNeededToMaxDailyEngagement = 2; +const int kMoreAccumulationsThanNeededToMaxDailyEngagement = 40; +const int kMoreAccumulationsThanNeededToMaxTotalEngagement = 200; +const int kLessDaysThanNeededToMaxTotalEngagement = 4; +const int kMoreDaysThanNeededToMaxTotalEngagement = 40; +const int kLessPeriodsThanNeededToDecayMaxScore = 2; +const int kMorePeriodsThanNeededToDecayMaxScore = 40; +const double kMaxRoundingDeviation = 0.0001; + +base::Time GetReferenceTime() { + base::Time::Exploded exploded_reference_time; + exploded_reference_time.year = 2015; + exploded_reference_time.month = 1; + exploded_reference_time.day_of_month = 30; + exploded_reference_time.day_of_week = 5; + exploded_reference_time.hour = 11; + exploded_reference_time.minute = 0; + exploded_reference_time.second = 0; + exploded_reference_time.millisecond = 0; + + base::Time out_time; + EXPECT_TRUE( + base::Time::FromLocalExploded(exploded_reference_time, &out_time)); + return out_time; +} + +} // namespace + +class SiteEngagementScoreTest : public testing::Test { + public: + SiteEngagementScoreTest() : score_(&test_clock_, GURL(), nullptr) {} + + void SetUp() override { + // Disable the first engagement bonus for tests. + SiteEngagementScore::SetParamValuesForTesting(); + } + + protected: + void VerifyScore(const SiteEngagementScore& score, + double expected_raw_score, + double expected_points_added_today, + base::Time expected_last_engagement_time) { + EXPECT_EQ(expected_raw_score, score.raw_score_); + EXPECT_EQ(expected_points_added_today, score.points_added_today_); + EXPECT_EQ(expected_last_engagement_time, score.last_engagement_time_); + } + + void UpdateScore(SiteEngagementScore* score, + double raw_score, + double points_added_today, + base::Time last_engagement_time) { + score->raw_score_ = raw_score; + score->points_added_today_ = points_added_today; + score->last_engagement_time_ = last_engagement_time; + } + + void TestScoreInitializesAndUpdates( + std::unique_ptr<base::DictionaryValue> score_dict, + double expected_raw_score, + double expected_points_added_today, + base::Time expected_last_engagement_time) { + std::unique_ptr<base::DictionaryValue> copy(score_dict->DeepCopy()); + SiteEngagementScore initial_score(&test_clock_, GURL(), + std::move(score_dict)); + VerifyScore(initial_score, expected_raw_score, expected_points_added_today, + expected_last_engagement_time); + + // Updating the score dict should return false, as the score shouldn't + // have changed at this point. + EXPECT_FALSE(initial_score.UpdateScoreDict(copy.get())); + + // Update the score to new values and verify it updates the score dict + // correctly. + base::Time different_day = + GetReferenceTime() + base::TimeDelta::FromDays(1); + UpdateScore(&initial_score, 5, 10, different_day); + EXPECT_TRUE(initial_score.UpdateScoreDict(copy.get())); + SiteEngagementScore updated_score(&test_clock_, GURL(), std::move(copy)); + VerifyScore(updated_score, 5, 10, different_day); + } + + void SetParamValue(SiteEngagementScore::Variation variation, double value) { + SiteEngagementScore::GetParamValues()[variation].second = value; + } + + base::SimpleTestClock test_clock_; + SiteEngagementScore score_; +}; + +// Accumulate score many times on the same day. Ensure each time the score goes +// up, but not more than the maximum per day. +TEST_F(SiteEngagementScoreTest, AccumulateOnSameDay) { + base::Time reference_time = GetReferenceTime(); + + test_clock_.SetNow(reference_time); + for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + EXPECT_EQ(std::min(SiteEngagementScore::GetMaxPointsPerDay(), + (i + 1) * SiteEngagementScore::GetNavigationPoints()), + score_.GetTotalScore()); + } + + EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.GetTotalScore()); +} + +// Accumulate on the first day to max that day's engagement, then accumulate on +// a different day. +TEST_F(SiteEngagementScoreTest, AccumulateOnTwoDays) { + base::Time reference_time = GetReferenceTime(); + base::Time later_date = reference_time + base::TimeDelta::FromDays(2); + + test_clock_.SetNow(reference_time); + for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + + EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.GetTotalScore()); + + test_clock_.SetNow(later_date); + for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + double day_score = + std::min(SiteEngagementScore::GetMaxPointsPerDay(), + (i + 1) * SiteEngagementScore::GetNavigationPoints()); + EXPECT_EQ(day_score + SiteEngagementScore::GetMaxPointsPerDay(), + score_.GetTotalScore()); + } + + EXPECT_EQ(2 * SiteEngagementScore::GetMaxPointsPerDay(), + score_.GetTotalScore()); +} + +// Accumulate score on many consecutive days and ensure the score doesn't exceed +// the maximum allowed. +TEST_F(SiteEngagementScoreTest, AccumulateALotOnManyDays) { + base::Time current_day = GetReferenceTime(); + + for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) { + current_day += base::TimeDelta::FromDays(1); + test_clock_.SetNow(current_day); + for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + + EXPECT_EQ(std::min(SiteEngagementScore::kMaxPoints, + (i + 1) * SiteEngagementScore::GetMaxPointsPerDay()), + score_.GetTotalScore()); + } + + EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); +} + +// Accumulate a little on many consecutive days and ensure the score doesn't +// exceed the maximum allowed. +TEST_F(SiteEngagementScoreTest, AccumulateALittleOnManyDays) { + base::Time current_day = GetReferenceTime(); + + for (int i = 0; i < kMoreAccumulationsThanNeededToMaxTotalEngagement; ++i) { + current_day += base::TimeDelta::FromDays(1); + test_clock_.SetNow(current_day); + + for (int j = 0; j < kLessAccumulationsThanNeededToMaxDailyEngagement; ++j) + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + + EXPECT_EQ( + std::min(SiteEngagementScore::kMaxPoints, + (i + 1) * kLessAccumulationsThanNeededToMaxDailyEngagement * + SiteEngagementScore::GetNavigationPoints()), + score_.GetTotalScore()); + } + + EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); +} + +// Accumulate a bit, then check the score decays properly for a range of times. +TEST_F(SiteEngagementScoreTest, ScoresDecayOverTime) { + base::Time current_day = GetReferenceTime(); + + // First max the score. + for (int i = 0; i < kMoreDaysThanNeededToMaxTotalEngagement; ++i) { + current_day += base::TimeDelta::FromDays(1); + test_clock_.SetNow(current_day); + + for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + } + + EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); + + // The score should not have decayed before the first decay period has + // elapsed. + test_clock_.SetNow(current_day + + base::TimeDelta::FromHours( + SiteEngagementScore::GetDecayPeriodInHours() - 1)); + EXPECT_EQ(SiteEngagementScore::kMaxPoints, score_.GetTotalScore()); + + // The score should have decayed by one chunk after one decay period has + // elapsed. + test_clock_.SetNow( + current_day + + base::TimeDelta::FromHours(SiteEngagementScore::GetDecayPeriodInHours())); + EXPECT_EQ( + SiteEngagementScore::kMaxPoints - SiteEngagementScore::GetDecayPoints(), + score_.GetTotalScore()); + + // The score should have decayed by the right number of chunks after a few + // decay periods have elapsed. + test_clock_.SetNow( + current_day + + base::TimeDelta::FromHours(kLessPeriodsThanNeededToDecayMaxScore * + SiteEngagementScore::GetDecayPeriodInHours())); + EXPECT_EQ(SiteEngagementScore::kMaxPoints - + kLessPeriodsThanNeededToDecayMaxScore * + SiteEngagementScore::GetDecayPoints(), + score_.GetTotalScore()); + + // The score should not decay below zero. + test_clock_.SetNow( + current_day + + base::TimeDelta::FromHours(kMorePeriodsThanNeededToDecayMaxScore * + SiteEngagementScore::GetDecayPeriodInHours())); + EXPECT_EQ(0, score_.GetTotalScore()); +} + +// Test that any expected decays are applied before adding points. +TEST_F(SiteEngagementScoreTest, DecaysAppliedBeforeAdd) { + base::Time current_day = GetReferenceTime(); + + // Get the score up to something that can handle a bit of decay before + for (int i = 0; i < kLessDaysThanNeededToMaxTotalEngagement; ++i) { + current_day += base::TimeDelta::FromDays(1); + test_clock_.SetNow(current_day); + + for (int j = 0; j < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++j) + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + } + + double initial_score = kLessDaysThanNeededToMaxTotalEngagement * + SiteEngagementScore::GetMaxPointsPerDay(); + EXPECT_EQ(initial_score, score_.GetTotalScore()); + + // Go forward a few decay periods. + test_clock_.SetNow( + current_day + + base::TimeDelta::FromHours(kLessPeriodsThanNeededToDecayMaxScore * + SiteEngagementScore::GetDecayPeriodInHours())); + + double decayed_score = + initial_score - kLessPeriodsThanNeededToDecayMaxScore * + SiteEngagementScore::GetDecayPoints(); + EXPECT_EQ(decayed_score, score_.GetTotalScore()); + + // Now add some points. + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + EXPECT_EQ(decayed_score + SiteEngagementScore::GetNavigationPoints(), + score_.GetTotalScore()); +} + +// Test that going back in time is handled properly. +TEST_F(SiteEngagementScoreTest, GoBackInTime) { + base::Time current_day = GetReferenceTime(); + + test_clock_.SetNow(current_day); + for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + + EXPECT_EQ(SiteEngagementScore::GetMaxPointsPerDay(), score_.GetTotalScore()); + + // Adding to the score on an earlier date should be treated like another day, + // and should not cause any decay. + test_clock_.SetNow(current_day - base::TimeDelta::FromDays( + kMorePeriodsThanNeededToDecayMaxScore * + SiteEngagementScore::GetDecayPoints())); + for (int i = 0; i < kMoreAccumulationsThanNeededToMaxDailyEngagement; ++i) { + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + double day_score = + std::min(SiteEngagementScore::GetMaxPointsPerDay(), + (i + 1) * SiteEngagementScore::GetNavigationPoints()); + EXPECT_EQ(day_score + SiteEngagementScore::GetMaxPointsPerDay(), + score_.GetTotalScore()); + } + + EXPECT_EQ(2 * SiteEngagementScore::GetMaxPointsPerDay(), + score_.GetTotalScore()); +} + +// Test that scores are read / written correctly from / to empty score +// dictionaries. +TEST_F(SiteEngagementScoreTest, EmptyDictionary) { + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + TestScoreInitializesAndUpdates(std::move(dict), 0, 0, base::Time()); +} + +// Test that scores are read / written correctly from / to partially empty +// score dictionaries. +TEST_F(SiteEngagementScoreTest, PartiallyEmptyDictionary) { + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + dict->SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2); + + TestScoreInitializesAndUpdates(std::move(dict), 0, 2, base::Time()); +} + +// Test that scores are read / written correctly from / to populated score +// dictionaries. +TEST_F(SiteEngagementScoreTest, PopulatedDictionary) { + std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + dict->SetDouble(SiteEngagementScore::kRawScoreKey, 1); + dict->SetDouble(SiteEngagementScore::kPointsAddedTodayKey, 2); + dict->SetDouble(SiteEngagementScore::kLastEngagementTimeKey, + GetReferenceTime().ToInternalValue()); + + TestScoreInitializesAndUpdates(std::move(dict), 1, 2, GetReferenceTime()); +} + +// Ensure bonus engagement is awarded for the first engagement of a day. +TEST_F(SiteEngagementScoreTest, FirstDailyEngagementBonus) { + SetParamValue(SiteEngagementScore::FIRST_DAILY_ENGAGEMENT, 0.5); + + SiteEngagementScore score1(&test_clock_, GURL(), + std::unique_ptr<base::DictionaryValue>()); + SiteEngagementScore score2(&test_clock_, GURL(), + std::unique_ptr<base::DictionaryValue>()); + base::Time current_day = GetReferenceTime(); + + test_clock_.SetNow(current_day); + + // The first engagement event gets the bonus. + score1.AddPoints(0.5); + EXPECT_EQ(1.0, score1.GetTotalScore()); + + // Subsequent events do not. + score1.AddPoints(0.5); + EXPECT_EQ(1.5, score1.GetTotalScore()); + + // Bonuses are awarded independently between scores. + score2.AddPoints(1.0); + EXPECT_EQ(1.5, score2.GetTotalScore()); + score2.AddPoints(1.0); + EXPECT_EQ(2.5, score2.GetTotalScore()); + + test_clock_.SetNow(current_day + base::TimeDelta::FromDays(1)); + + // The first event for the next day gets the bonus. + score1.AddPoints(0.5); + EXPECT_EQ(2.5, score1.GetTotalScore()); + + // Subsequent events do not. + score1.AddPoints(0.5); + EXPECT_EQ(3.0, score1.GetTotalScore()); + + score2.AddPoints(1.0); + EXPECT_EQ(4.0, score2.GetTotalScore()); + score2.AddPoints(1.0); + EXPECT_EQ(5.0, score2.GetTotalScore()); +} + +// Test that resetting a score has the correct properties. +TEST_F(SiteEngagementScoreTest, Reset) { + base::Time current_day = GetReferenceTime(); + + test_clock_.SetNow(current_day); + score_.AddPoints(SiteEngagementScore::GetNavigationPoints()); + EXPECT_EQ(SiteEngagementScore::GetNavigationPoints(), score_.GetTotalScore()); + + current_day += base::TimeDelta::FromDays(7); + test_clock_.SetNow(current_day); + + score_.Reset(20.0, current_day); + EXPECT_DOUBLE_EQ(20.0, score_.GetTotalScore()); + EXPECT_DOUBLE_EQ(0, score_.points_added_today_); + EXPECT_EQ(current_day, score_.last_engagement_time_); + EXPECT_TRUE(score_.last_shortcut_launch_time_.is_null()); + + // Adding points after the reset should work as normal. + score_.AddPoints(5); + EXPECT_EQ(25.0, score_.GetTotalScore()); + + // The decay should happen one decay period from the current time. + test_clock_.SetNow(current_day + + base::TimeDelta::FromHours( + SiteEngagementScore::GetDecayPeriodInHours() + 1)); + EXPECT_EQ(25.0 - SiteEngagementScore::GetDecayPoints(), + score_.GetTotalScore()); + + // Ensure that manually setting a time works as expected. + score_.AddPoints(5); + test_clock_.SetNow(GetReferenceTime()); + base::Time now = test_clock_.Now(); + score_.Reset(10.0, now); + + EXPECT_DOUBLE_EQ(10.0, score_.GetTotalScore()); + EXPECT_DOUBLE_EQ(0, score_.points_added_today_); + EXPECT_EQ(now, score_.last_engagement_time_); + EXPECT_TRUE(score_.last_shortcut_launch_time_.is_null()); + + base::Time old_now = test_clock_.Now(); + + score_.set_last_shortcut_launch_time(test_clock_.Now()); + test_clock_.SetNow(GetReferenceTime() + base::TimeDelta::FromDays(3)); + now = test_clock_.Now(); + score_.Reset(15.0, now); + + // 5 bonus from the last shortcut launch. + EXPECT_DOUBLE_EQ(20.0, score_.GetTotalScore()); + EXPECT_DOUBLE_EQ(0, score_.points_added_today_); + EXPECT_EQ(now, score_.last_engagement_time_); + EXPECT_EQ(old_now, score_.last_shortcut_launch_time_); +} + +// Test proportional decay. +TEST_F(SiteEngagementScoreTest, ProportionalDecay) { + SetParamValue(SiteEngagementScore::DECAY_PROPORTION, 0.5); + SetParamValue(SiteEngagementScore::DECAY_POINTS, 0); + SetParamValue(SiteEngagementScore::MAX_POINTS_PER_DAY, 20); + base::Time current_day = GetReferenceTime(); + test_clock_.SetNow(current_day); + + // Single decay period, expect the score to be halved once. + score_.AddPoints(2.0); + current_day += base::TimeDelta::FromDays(7); + test_clock_.SetNow(current_day); + EXPECT_DOUBLE_EQ(1.0, score_.GetTotalScore()); + + // 3 decay periods, expect the score to be halved 3 times. + score_.AddPoints(15.0); + current_day += base::TimeDelta::FromDays(21); + test_clock_.SetNow(current_day); + EXPECT_DOUBLE_EQ(2.0, score_.GetTotalScore()); + + // Ensure point removal happens after proportional decay. + score_.AddPoints(4.0); + EXPECT_DOUBLE_EQ(6.0, score_.GetTotalScore()); + SetParamValue(SiteEngagementScore::DECAY_POINTS, 2.0); + current_day += base::TimeDelta::FromDays(7); + test_clock_.SetNow(current_day); + EXPECT_NEAR(1.0, score_.GetTotalScore(), kMaxRoundingDeviation); +} + +// Verify that GetDetails fills out all fields correctly. +TEST_F(SiteEngagementScoreTest, GetDetails) { + // Advance the clock, otherwise Now() is the same as the null Time value. + test_clock_.Advance(base::TimeDelta::FromDays(365)); + + GURL url("http://www.google.com/"); + + // Replace |score_| with one with an actual URL. + score_ = SiteEngagementScore(&test_clock_, url, nullptr); + + // Initially all component scores should be zero. + mojom::SiteEngagementDetails details = score_.GetDetails(); + EXPECT_DOUBLE_EQ(0.0, details.total_score); + EXPECT_DOUBLE_EQ(0.0, details.installed_bonus); + EXPECT_DOUBLE_EQ(0.0, details.base_score); + EXPECT_EQ(url, details.origin); + + // Simulate the app having been launched. + score_.set_last_shortcut_launch_time(test_clock_.Now()); + details = score_.GetDetails(); + EXPECT_DOUBLE_EQ(details.installed_bonus, details.total_score); + EXPECT_LT(0.0, details.installed_bonus); + EXPECT_DOUBLE_EQ(0.0, details.base_score); +} + +} // namespace site_engagement
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc index f13f837..211d685 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -18,7 +18,6 @@ #include "components/subresource_filter/content/browser/activation_state_computing_navigation_throttle.h" #include "components/subresource_filter/content/browser/async_document_subresource_filter.h" #include "components/subresource_filter/content/browser/page_load_statistics.h" -#include "components/subresource_filter/content/browser/profile_interaction_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h" #include "components/subresource_filter/content/common/subresource_filter_messages.h" @@ -439,7 +438,7 @@ client_->GetSafeBrowsingDatabaseManager()) { throttles->push_back( std::make_unique<SubresourceFilterSafeBrowsingActivationThrottle>( - navigation_handle, client_->GetProfileInteractionManager(), + navigation_handle, client_.get(), content::GetIOThreadTaskRunner({}), client_->GetSafeBrowsingDatabaseManager())); }
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc index a3e338e..2c725f2b 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -183,6 +183,12 @@ // SubresourceFilterClient: void ShowNotification() override { ++disallowed_notification_count_; } + mojom::ActivationLevel OnPageActivationComputed( + content::NavigationHandle* navigation_handle, + mojom::ActivationLevel effective_activation_level, + ActivationDecision* decision) override { + return effective_activation_level; + } void OnAdsViolationTriggered( content::RenderFrameHost* rfh, mojom::AdsViolation triggered_violation) override {} @@ -190,10 +196,6 @@ GetSafeBrowsingDatabaseManager() override { return database_manager_; } - subresource_filter::ProfileInteractionManager* GetProfileInteractionManager() - override { - return nullptr; - } void OnReloadRequested() override {} void CreateSafeBrowsingDatabaseManager() {
diff --git a/components/subresource_filter/content/browser/profile_interaction_manager.h b/components/subresource_filter/content/browser/profile_interaction_manager.h index 8081870c..015ecf4 100644 --- a/components/subresource_filter/content/browser/profile_interaction_manager.h +++ b/components/subresource_filter/content/browser/profile_interaction_manager.h
@@ -5,7 +5,6 @@ #ifndef COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_ #define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_PROFILE_INTERACTION_MANAGER_H_ -#include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h" #include "components/subresource_filter/core/common/activation_decision.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" #include "content/public/browser/web_contents_observer.h" @@ -22,9 +21,7 @@ // Class that manages interaction between interaction between the // per-navigation/per-tab subresource filter objects (i.e., the throttles and // throttle manager) and the per-profile objects (e.g., content settings). -class ProfileInteractionManager - : public content::WebContentsObserver, - public SubresourceFilterSafeBrowsingActivationThrottle::Delegate { +class ProfileInteractionManager : public content::WebContentsObserver { public: ProfileInteractionManager(content::WebContents* web_contents, SubresourceFilterProfileContext* profile_context); @@ -46,11 +43,19 @@ void OnAdsViolationTriggered(content::RenderFrameHost* rfh, mojom::AdsViolation triggered_violation); - // SubresourceFilterSafeBrowsingActivationThrottle::Delegate: + // Called when the initial activation decision has been computed by the + // safe browsing activation throttle. This object then applies any adjustments + // based on relevant state of the Profile (e.g., content settings). Returns + // the effective activation for this navigation. + // + // Note: |decision| is guaranteed to be non-nullptr, and can be modified by + // this method if any decision changes. + // + // Precondition: The navigation must be a main frame navigation. mojom::ActivationLevel OnPageActivationComputed( content::NavigationHandle* navigation_handle, mojom::ActivationLevel initial_activation_level, - ActivationDecision* decision) override; + ActivationDecision* decision); private: // Unowned and must outlive this object.
diff --git a/components/subresource_filter/content/browser/subresource_filter_client.h b/components/subresource_filter/content/browser/subresource_filter_client.h index cdd3b9e..2b4e80d 100644 --- a/components/subresource_filter/content/browser/subresource_filter_client.h +++ b/components/subresource_filter/content/browser/subresource_filter_client.h
@@ -6,8 +6,15 @@ #define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBRESOURCE_FILTER_CLIENT_H_ #include "base/memory/scoped_refptr.h" +#include "components/subresource_filter/content/browser/verified_ruleset_dealer.h" +#include "components/subresource_filter/core/common/activation_decision.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" #include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" + +namespace content { +class NavigationHandle; +} // namespace content namespace safe_browsing { class SafeBrowsingDatabaseManager; @@ -15,8 +22,6 @@ namespace subresource_filter { -class ProfileInteractionManager; - class SubresourceFilterClient { public: virtual ~SubresourceFilterClient() = default; @@ -25,6 +30,20 @@ // blocked. This method will be called at most once per main-frame navigation. virtual void ShowNotification() = 0; + // Called when the activation decision is otherwise completely computed by the + // subresource filter. At this point, the embedder still has a chance to + // alter the effective activation. Returns the effective activation for this + // navigation. + // + // Note: |decision| is guaranteed to be non-nullptr, and can be modified by + // the embedder if any decision changes. + // + // Precondition: The navigation must be a main frame navigation. + virtual mojom::ActivationLevel OnPageActivationComputed( + content::NavigationHandle* navigation_handle, + mojom::ActivationLevel initial_activation_level, + subresource_filter::ActivationDecision* decision) = 0; + // Called on the subresource filter client when an ads violation is detected. virtual void OnAdsViolationTriggered( content::RenderFrameHost* rfh, @@ -35,14 +54,6 @@ virtual const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> GetSafeBrowsingDatabaseManager() = 0; - // Returns the ProfileInteractionManager instance associated with this - // client, or null if there is no such instance. - // TODO(crbug.com/1116095): Have ContentSubresourceFilterThrottleManager - // create and own this object internally once ChromeSubresourceFilterClient no - // longer calls into it, replacing this method with a getter for - // SubresourceFilterProfileContext. - virtual ProfileInteractionManager* GetProfileInteractionManager() = 0; - // Invoked when the user has requested a reload of a page with blocked ads // (e.g., via an infobar). virtual void OnReloadRequested() = 0;
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc index 6a6d09b..3f444aa 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -17,6 +17,7 @@ #include "components/subresource_filter/content/browser/content_activation_list_utils.h" #include "components/subresource_filter/content/browser/devtools_interaction_tracker.h" #include "components/subresource_filter/content/browser/navigation_console_logger.h" +#include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h" #include "components/subresource_filter/core/browser/subresource_filter_constants.h" @@ -63,7 +64,7 @@ SubresourceFilterSafeBrowsingActivationThrottle:: SubresourceFilterSafeBrowsingActivationThrottle( content::NavigationHandle* handle, - Delegate* delegate, + SubresourceFilterClient* client, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager) @@ -75,7 +76,7 @@ io_task_runner_, base::ThreadTaskRunnerHandle::Get()), base::OnTaskRunnerDeleter(io_task_runner_)), - delegate_(delegate) { + client_(client) { DCHECK(handle->IsInMainFrame()); CheckCurrentUrl(); @@ -204,11 +205,9 @@ activation_decision = ActivationDecision::FORCED_ACTIVATION; } - // Let the delegate adjust the activation decision if present. - if (delegate_) { - activation_level = delegate_->OnPageActivationComputed( - navigation_handle(), activation_level, &activation_decision); - } + // Let the embedder get the last word when it comes to activation level. + activation_level = client_->OnPageActivationComputed( + navigation_handle(), activation_level, &activation_decision); LogMetricsOnChecksComplete(selection.matched_list, activation_decision, activation_level);
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h index 43e42b8..b3fc830 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.h
@@ -26,6 +26,8 @@ namespace subresource_filter { +class SubresourceFilterClient; + // Enum representing a position in the redirect chain. These values are // persisted to logs. Entries should not be renumbered and numeric values should // never be reused. @@ -44,32 +46,9 @@ public base::SupportsWeakPtr< SubresourceFilterSafeBrowsingActivationThrottle> { public: - // Interface that allows the client of this class to adjust activation - // decisions if/as desired. - class Delegate { - public: - virtual ~Delegate() = default; - - // Called when the initial activation decision has been computed by the - // safe browsing activation throttle. Returns - // the effective activation for this navigation. - // - // Note: |decision| is guaranteed to be non-nullptr, and can be modified by - // this method if any decision changes. - // - // Precondition: The navigation must be a main frame navigation. - virtual mojom::ActivationLevel OnPageActivationComputed( - content::NavigationHandle* navigation_handle, - mojom::ActivationLevel initial_activation_level, - ActivationDecision* decision) = 0; - }; - - // |delegate| is allowed to be null, in which case the client creating this - // throttle will not be able to adjust activation decisions made by the - // throttle. SubresourceFilterSafeBrowsingActivationThrottle( content::NavigationHandle* handle, - Delegate* delegate, + SubresourceFilterClient* client, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager); @@ -131,8 +110,8 @@ base::OnTaskRunnerDeleter> database_client_; - // May be null. If non-null, must outlive this class. - Delegate* delegate_; + // Must outlive this class. + SubresourceFilterClient* client_; // Set to TimeTicks::Now() when the navigation is deferred in // WillProcessResponse. If deferral was not necessary, will remain null.
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc index a86533d..08f1cc5 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -24,7 +24,6 @@ #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" #include "components/subresource_filter/content/browser/devtools_interaction_tracker.h" #include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" -#include "components/subresource_filter/content/browser/profile_interaction_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h" #include "components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.h" @@ -70,17 +69,11 @@ "SubresourceFilter.PageLoad.ActivationList"; const char kSubresourceFilterActionsHistogram[] = "SubresourceFilter.Actions2"; -class TestSafeBrowsingActivationThrottleDelegate - : public SubresourceFilterSafeBrowsingActivationThrottle::Delegate { +class MockSubresourceFilterClient : public SubresourceFilterClient { public: - TestSafeBrowsingActivationThrottleDelegate() = default; - ~TestSafeBrowsingActivationThrottleDelegate() override = default; - TestSafeBrowsingActivationThrottleDelegate( - const TestSafeBrowsingActivationThrottleDelegate&) = delete; - TestSafeBrowsingActivationThrottleDelegate& operator=( - const TestSafeBrowsingActivationThrottleDelegate&) = delete; + MockSubresourceFilterClient() = default; + ~MockSubresourceFilterClient() override = default; - // SubresourceFilterSafeBrowsingActivationThrottle::Delegate: mojom::ActivationLevel OnPageActivationComputed( content::NavigationHandle* handle, mojom::ActivationLevel effective_level, @@ -95,6 +88,15 @@ return effective_level; } + MOCK_METHOD0(ShowNotification, void()); + MOCK_METHOD2(OnAdsViolationTriggered, + void(content::RenderFrameHost*, + subresource_filter::mojom::AdsViolation)); + MOCK_METHOD0( + GetSafeBrowsingDatabaseManager, + const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>()); + MOCK_METHOD0(OnReloadRequested, void()); + void AllowlistInCurrentWebContents(const GURL& url) { ASSERT_TRUE(url.SchemeIsHTTPOrHTTPS()); allowlisted_hosts_.insert(url.host()); @@ -104,25 +106,7 @@ private: std::set<std::string> allowlisted_hosts_; -}; -class MockSubresourceFilterClient : public SubresourceFilterClient { - public: - MockSubresourceFilterClient() = default; - ~MockSubresourceFilterClient() override = default; - - MOCK_METHOD0(ShowNotification, void()); - MOCK_METHOD2(OnAdsViolationTriggered, - void(content::RenderFrameHost*, - subresource_filter::mojom::AdsViolation)); - MOCK_METHOD0( - GetSafeBrowsingDatabaseManager, - const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>()); - MOCK_METHOD0(GetProfileInteractionManager, - subresource_filter::ProfileInteractionManager*()); - MOCK_METHOD0(OnReloadRequested, void()); - - private: DISALLOW_COPY_AND_ASSIGN(MockSubresourceFilterClient); }; @@ -229,7 +213,7 @@ if (navigation_handle->IsInMainFrame()) { navigation_handle->RegisterThrottleForTesting( std::make_unique<SubresourceFilterSafeBrowsingActivationThrottle>( - navigation_handle, delegate(), test_io_task_runner_, + navigation_handle, client(), test_io_task_runner_, fake_safe_browsing_database_)); } std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; @@ -353,7 +337,6 @@ MockSubresourceFilterClient* client() { return client_; } - TestSafeBrowsingActivationThrottleDelegate* delegate() { return &delegate_; } base::TestMockTimeTaskRunner* test_io_task_runner() const { return test_io_task_runner_.get(); } @@ -369,7 +352,6 @@ testing::TestRulesetCreator test_ruleset_creator_; testing::TestRulesetPair test_ruleset_pair_; - TestSafeBrowsingActivationThrottleDelegate delegate_; std::unique_ptr<VerifiedRulesetDealer::Handle> ruleset_dealer_; std::unique_ptr<ContentSubresourceFilterThrottleManager> throttle_manager_; @@ -537,7 +519,7 @@ *observer()->GetPageActivationForLastCommittedLoad()); // Allowlisting occurs last, so the decision should still be DISABLED. - delegate()->AllowlistInCurrentWebContents(url); + client()->AllowlistInCurrentWebContents(url); SimulateNavigateAndCommit({url}, main_rfh()); EXPECT_EQ(mojom::ActivationLevel::kDisabled, *observer()->GetPageActivationForLastCommittedLoad()); @@ -810,7 +792,7 @@ EXPECT_EQ(test_data.expected_activation_level, *observer()->GetPageActivationForLastCommittedLoad()); if (test_data.url_matches_activation_list) { - delegate()->AllowlistInCurrentWebContents(test_url); + client()->AllowlistInCurrentWebContents(test_url); SimulateNavigateAndCommit({test_url}, main_rfh()); EXPECT_EQ(mojom::ActivationLevel::kDisabled, *observer()->GetPageActivationForLastCommittedLoad());
diff --git a/components/translate/DEPS b/components/translate/DEPS index 3825a03..70e632f 100644 --- a/components/translate/DEPS +++ b/components/translate/DEPS
@@ -2,7 +2,6 @@ "+components/grit/components_resources.h", "+components/infobars", "+components/language", - "+components/language_usage_metrics", "+components/pref_registry", "+components/prefs", "+components/strings/grit/components_locale_settings.h",
diff --git a/components/translate/core/browser/BUILD.gn b/components/translate/core/browser/BUILD.gn index c971cec..1cfd0b7 100644 --- a/components/translate/core/browser/BUILD.gn +++ b/components/translate/core/browser/BUILD.gn
@@ -58,7 +58,6 @@ "//components/keyed_service/core", "//components/language/core/browser", "//components/language/core/common", - "//components/language_usage_metrics", "//components/metrics", "//components/pref_registry", "//components/prefs",
diff --git a/components/translate/core/browser/mock_translate_metrics_logger.h b/components/translate/core/browser/mock_translate_metrics_logger.h index fa80a3a..792228e7 100644 --- a/components/translate/core/browser/mock_translate_metrics_logger.h +++ b/components/translate/core/browser/mock_translate_metrics_logger.h
@@ -42,6 +42,7 @@ MOCK_METHOD2(LogInitialSourceLanguage, void(const std::string&, bool)); MOCK_METHOD1(LogSourceLanguage, void(const std::string&)); MOCK_METHOD1(LogTargetLanguage, void(const std::string&)); + MOCK_METHOD1(LogUIInteraction, void(UIInteraction)); private: base::WeakPtrFactory<MockTranslateMetricsLogger> weak_method_factory_{this};
diff --git a/components/translate/core/browser/translate_browser_metrics.cc b/components/translate/core/browser/translate_browser_metrics.cc index 46a8d7c8..fcfd7678 100644 --- a/components/translate/core/browser/translate_browser_metrics.cc +++ b/components/translate/core/browser/translate_browser_metrics.cc
@@ -7,7 +7,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/metrics_hashes.h" -#include "components/language_usage_metrics/language_usage_metrics.h" +#include "components/language/core/browser/language_usage_metrics.h" namespace translate { @@ -62,18 +62,16 @@ void ReportLocalesOnDisabledByPrefs(base::StringPiece locale) { base::UmaHistogramSparse( kTranslateLocalesOnDisabledByPrefs, - language_usage_metrics::LanguageUsageMetrics::ToLanguageCode(locale)); + language::LanguageUsageMetrics::ToLanguageCode(locale)); } void ReportUndisplayableLanguage(base::StringPiece language) { - int language_code = - language_usage_metrics::LanguageUsageMetrics::ToLanguageCode(language); + int language_code = language::LanguageUsageMetrics::ToLanguageCode(language); base::UmaHistogramSparse(kTranslateUndisplayableLanguage, language_code); } void ReportUnsupportedLanguageAtInitiation(base::StringPiece language) { - int language_code = - language_usage_metrics::LanguageUsageMetrics::ToLanguageCode(language); + int language_code = language::LanguageUsageMetrics::ToLanguageCode(language); base::UmaHistogramSparse(kTranslateUnsupportedLanguageAtInitiation, language_code); }
diff --git a/components/translate/core/browser/translate_infobar_delegate.cc b/components/translate/core/browser/translate_infobar_delegate.cc index bca1cb7..24677a70 100644 --- a/components/translate/core/browser/translate_infobar_delegate.cc +++ b/components/translate/core/browser/translate_infobar_delegate.cc
@@ -430,6 +430,7 @@ void TranslateInfoBarDelegate::InfoBarDismissed() { OnInfoBarClosedByUser(); + ReportUIInteraction(UIInteraction::kCloseUIExplicitly); bool declined = false; bool has_observer = false; @@ -482,4 +483,9 @@ ui_delegate_.OnUIClosedByUser(); } +void TranslateInfoBarDelegate::ReportUIInteraction( + UIInteraction ui_interaction) { + ui_delegate_.ReportUIInteraction(ui_interaction); +} + } // namespace translate
diff --git a/components/translate/core/browser/translate_infobar_delegate.h b/components/translate/core/browser/translate_infobar_delegate.h index 55a15e5..e93cf44c5 100644 --- a/components/translate/core/browser/translate_infobar_delegate.h +++ b/components/translate/core/browser/translate_infobar_delegate.h
@@ -19,6 +19,7 @@ #include "base/observer_list_types.h" #include "build/build_config.h" #include "components/infobars/core/infobar_delegate.h" +#include "components/translate/core/browser/translate_metrics_logger.h" #include "components/translate/core/browser/translate_prefs.h" #include "components/translate/core/browser/translate_step.h" #include "components/translate/core/browser/translate_ui_delegate.h" @@ -227,6 +228,9 @@ // and the user selects to never translate the language. void OnInfoBarClosedByUser(); + // Records a high level UI interaction. + void ReportUIInteraction(UIInteraction ui_interaction); + // InfoBarDelegate: infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; int GetIconId() const override;
diff --git a/components/translate/core/browser/translate_metrics_logger.h b/components/translate/core/browser/translate_metrics_logger.h index f249bb1..8d599c9 100644 --- a/components/translate/core/browser/translate_metrics_logger.h +++ b/components/translate/core/browser/translate_metrics_logger.h
@@ -57,6 +57,20 @@ kMaxValue = kAutomaticTranslationByPref, }; +enum class UIInteraction { + kUninitialized = 0, + kTranslate = 1, + kRevert = 2, + kAlwaysTranslateLanguage = 3, + kChangeSourceLanguage = 4, + kChangeTargetLanguage = 5, + kNeverTranslateLanguage = 6, + kNeverTranslateSite = 7, + kCloseUIExplicitly = 8, + kCloseUILostFocus = 9, + kMaxValue = kCloseUILostFocus, +}; + // TranslateMetricsLogger tracks and logs various UKM and UMA metrics for Chrome // Translate over the course of a page load. class TranslateMetricsLogger { @@ -98,6 +112,9 @@ bool is_in_users_content_language) = 0; virtual void LogSourceLanguage(const std::string& source_language_code) = 0; virtual void LogTargetLanguage(const std::string& target_language_code) = 0; + + // Records the user's high level interactions with the Translate UI. + virtual void LogUIInteraction(UIInteraction ui_interaction) = 0; }; } // namespace translate
diff --git a/components/translate/core/browser/translate_metrics_logger_impl.cc b/components/translate/core/browser/translate_metrics_logger_impl.cc index 195438f..3792f9ee 100644 --- a/components/translate/core/browser/translate_metrics_logger_impl.cc +++ b/components/translate/core/browser/translate_metrics_logger_impl.cc
@@ -244,6 +244,14 @@ current_target_language_ = target_language_code; } +void TranslateMetricsLoggerImpl::LogUIInteraction( + UIInteraction ui_interaction) { + if (first_ui_interaction_ == UIInteraction::kUninitialized) + first_ui_interaction_ = ui_interaction; + + num_ui_interactions_++; +} + TranslateState TranslateMetricsLoggerImpl::ConvertToTranslateState( bool is_translated, bool is_ui_shown,
diff --git a/components/translate/core/browser/translate_metrics_logger_impl.h b/components/translate/core/browser/translate_metrics_logger_impl.h index b4033b37..7559ed7 100644 --- a/components/translate/core/browser/translate_metrics_logger_impl.h +++ b/components/translate/core/browser/translate_metrics_logger_impl.h
@@ -55,6 +55,7 @@ bool is_in_users_content_languages) override {} void LogSourceLanguage(const std::string& source_language_code) override {} void LogTargetLanguage(const std::string& target_language_code) override {} + void LogUIInteraction(UIInteraction ui_interaction) override {} }; class TranslateManager; @@ -97,6 +98,7 @@ bool is_in_users_content_languages) override; void LogSourceLanguage(const std::string& source_language_code) override; void LogTargetLanguage(const std::string& target_language_code) override; + void LogUIInteraction(UIInteraction ui_interaction) override; // TODO(curranmax): Add appropriate functions for the Translate code to log // relevant events. https://crbug.com/1114868. @@ -186,6 +188,11 @@ TranslateErrors::Type first_translate_error_type_ = TranslateErrors::NONE; int num_translate_errors_ = 0; + // Tracks the user's high level interaction with the Translate UI over the + // course of a page load. + UIInteraction first_ui_interaction_ = UIInteraction::kUninitialized; + int num_ui_interactions_ = 0; + base::WeakPtrFactory<TranslateMetricsLoggerImpl> weak_method_factory_{this}; };
diff --git a/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc b/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc index 2945ba1..e496f709 100644 --- a/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc +++ b/components/translate/core/browser/translate_metrics_logger_impl_unittest.cc
@@ -67,6 +67,14 @@ expected_max_time_to_translate); } + void CheckUIInteractions(UIInteraction expected_first_ui_interaction, + int expected_num_ui_interactions) { + EXPECT_EQ(translate_metrics_logger_->first_ui_interaction_, + expected_first_ui_interaction); + EXPECT_EQ(translate_metrics_logger_->num_ui_interactions_, + expected_num_ui_interactions); + } + private: // Test target. std::unique_ptr<TranslateMetricsLoggerImpl> translate_metrics_logger_; @@ -540,6 +548,26 @@ CheckMaxTimeToTranslate(base::TimeDelta::FromSeconds(400)); } +TEST_F(TranslateMetricsLoggerImplTest, LogUIInteraction) { + const UIInteraction kUIInteractions[] = { + UIInteraction::kTranslate, + UIInteraction::kRevert, + UIInteraction::kAlwaysTranslateLanguage, + UIInteraction::kChangeSourceLanguage, + UIInteraction::kChangeTargetLanguage, + UIInteraction::kNeverTranslateLanguage, + UIInteraction::kNeverTranslateSite, + UIInteraction::kCloseUIExplicitly, + UIInteraction::kCloseUILostFocus}; + for (auto ui_interaction : kUIInteractions) { + translate_metrics_logger()->LogUIInteraction(ui_interaction); + } + + translate_metrics_logger()->RecordMetrics(true); + + CheckUIInteractions(kUIInteractions[0], 9); +} + } // namespace testing } // namespace translate
diff --git a/components/translate/core/browser/translate_ui_delegate.cc b/components/translate/core/browser/translate_ui_delegate.cc index d37824a..99d4715 100644 --- a/components/translate/core/browser/translate_ui_delegate.cc +++ b/components/translate/core/browser/translate_ui_delegate.cc
@@ -14,7 +14,6 @@ #include "components/translate/core/browser/translate_download_manager.h" #include "components/translate/core/browser/translate_driver.h" #include "components/translate/core/browser/translate_manager.h" -#include "components/translate/core/browser/translate_metrics_logger.h" #include "components/translate/core/browser/translate_prefs.h" #include "components/translate/core/common/translate_constants.h" #include "components/variations/variations_associated_data.h" @@ -397,4 +396,11 @@ translate_manager_->GetActiveTranslateMetricsLogger()->LogUIChange(false); } +void TranslateUIDelegate::ReportUIInteraction(UIInteraction ui_interaction) { + if (translate_manager_) { + translate_manager_->GetActiveTranslateMetricsLogger()->LogUIInteraction( + ui_interaction); + } +} + } // namespace translate
diff --git a/components/translate/core/browser/translate_ui_delegate.h b/components/translate/core/browser/translate_ui_delegate.h index 1b9aa9f..0627467 100644 --- a/components/translate/core/browser/translate_ui_delegate.h +++ b/components/translate/core/browser/translate_ui_delegate.h
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" +#include "components/translate/core/browser/translate_metrics_logger.h" #include "components/translate/core/common/translate_errors.h" namespace translate { @@ -141,6 +142,9 @@ // this site, and the user selects to never translate this language. void OnUIClosedByUser(); + // Records a high level UI interaction. + void ReportUIInteraction(UIInteraction ui_interaction); + private: FRIEND_TEST_ALL_PREFIXES(TranslateUIDelegateTest, GetPageHost);
diff --git a/components/variations/field_trial_config/field_trial_util_unittest.cc b/components/variations/field_trial_config/field_trial_util_unittest.cc index 4b788f9..9049df6 100644 --- a/components/variations/field_trial_config/field_trial_util_unittest.cc +++ b/components/variations/field_trial_config/field_trial_util_unittest.cc
@@ -202,6 +202,7 @@ Study::PLATFORM_ANDROID_WEBLAYER, Study::PLATFORM_ANDROID_WEBVIEW, Study::PLATFORM_CHROMEOS, + Study::PLATFORM_CHROMEOS_LACROS, Study::PLATFORM_FUCHSIA, Study::PLATFORM_IOS, Study::PLATFORM_LINUX,
diff --git a/components/variations/proto/devtools/client_variations.js b/components/variations/proto/devtools/client_variations.js index 97c3e5d5..76be0ba 100644 --- a/components/variations/proto/devtools/client_variations.js +++ b/components/variations/proto/devtools/client_variations.js
@@ -9,14 +9,13 @@ const gen = {}; // clang-format off -(function(){var f=this||self;function l(a,b){a=a.split(".");var c=f;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}:c[d]=b} -function m(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; -else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function n(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.base=function(d,e,g){for(var k=Array(arguments.length-2),h=2;h<arguments.length;h++)k[h-2]=arguments[h];return b.prototype[e].apply(d,k)}};function p(a){if(Error.captureStackTrace)Error.captureStackTrace(this,p);else{const b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))}n(p,Error);p.prototype.name="CustomError";function q(a,b){a=a.split("%s");for(var c="",d=a.length-1,e=0;e<d;e++)c+=a[e]+(e<b.length?b[e]:"%s");p.call(this,c+a[d])}n(q,p);q.prototype.name="AssertionError";function r(a,b){throw new q("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));};var t=null;function u(a){var b=a.length,c=3*b/4;c%3?c=Math.floor(c):-1!="=.".indexOf(a[b-1])&&(c=-1!="=.".indexOf(a[b-2])?c-2:c-1);var d=new Uint8Array(c),e=0;w(a,function(g){d[e++]=g});return d.subarray(0,e)} -function w(a,b){function c(I){for(;d<a.length;){var v=a.charAt(d++),x=t[v];if(null!=x)return x;if(!/^[\s\xa0]*$/.test(v))throw Error("Unknown base64 encoding at char: "+v);}return I}y();for(var d=0;;){var e=c(-1),g=c(0),k=c(64),h=c(64);if(64===h&&-1===e)break;b(e<<2|g>>4);64!=k&&(b(g<<4&240|k>>2),64!=h&&b(k<<6&192|h))}} -function y(){if(!t){t={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),b=["+/=","+/","-_=","-_.","-_"],c=0;5>c;c++)for(var d=a.concat(b[c].split("")),e=0;e<d.length;e++){var g=d[e];void 0===t[g]&&(t[g]=e)}}};function z(a){if(a.constructor===Uint8Array)return a;if(a.constructor===ArrayBuffer)return new Uint8Array(a);if("undefined"!=typeof Buffer&&a.constructor===Buffer)return new Uint8Array(a);if(a.constructor===Array)return new Uint8Array(a);if(a.constructor===String)return u(a);r("Type not convertible to Uint8Array.");return new Uint8Array(0)};function A(a){this.b=null;this.a=this.c=this.g=0;a&&B(this,a)}var C=[];function B(a,b){a.b=z(b);a.g=0;a.c=a.b.length;a.a=a.g}A.prototype.reset=function(){this.a=this.g}; -A.prototype.f=function(){var a=this.b;var b=a[this.a];var c=b&127;if(128>b)return this.a+=1,c;b=a[this.a+1];c|=(b&127)<<7;if(128>b)return this.a+=2,c;b=a[this.a+2];c|=(b&127)<<14;if(128>b)return this.a+=3,c;b=a[this.a+3];c|=(b&127)<<21;if(128>b)return this.a+=4,c;b=a[this.a+4];c|=(b&15)<<28;if(128>b)return this.a+=5,c>>>0;this.a+=5;128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&this.a++;return c};A.prototype.h=A.prototype.f;function D(a){if(C.length){var b=C.pop();a&&B(b,a);a=b}else a=new A(a);this.a=a;this.g=this.a.a;this.b=this.c=-1;this.f=!1}D.prototype.reset=function(){this.a.reset();this.b=this.c=-1};function E(a){var b=a.a;if(b.a==b.c)return!1;(b=a.f)||(b=a.a,b=0>b.a||b.a>b.c);if(b)return r("Decoder hit an error"),!1;a.g=a.a.a;var c=a.a.f();b=c>>>3;c&=7;if(0!=c&&5!=c&&1!=c&&2!=c&&3!=c&&4!=c)return r("Invalid wire type: %s (at position %s)",c,a.g),a.f=!0,!1;a.c=b;a.b=c;return!0} -function F(a){switch(a.b){case 0:if(0!=a.b)r("Invalid wire type for skipVarintField"),F(a);else{for(a=a.a;a.b[a.a]&128;)a.a++;a.a++}break;case 1:1!=a.b?(r("Invalid wire type for skipFixed64Field"),F(a)):(a=a.a,a.a+=8);break;case 2:if(2!=a.b)r("Invalid wire type for skipDelimitedField"),F(a);else{var b=a.a.f();a=a.a;a.a+=b}break;case 5:5!=a.b?(r("Invalid wire type for skipFixed32Field"),F(a)):(a=a.a,a.a+=4);break;case 3:b=a.c;do{if(!E(a)){r("Unmatched start-group tag: stream EOF");a.f=!0;break}if(4== -a.b){a.c!=b&&(r("Unmatched end-group tag"),a.f=!0);break}F(a)}while(1);break;default:r("Invalid wire encoding for field.")}};function G(){}var H="function"==typeof Uint8Array,J=Object.freeze?Object.freeze([]):[];function K(a,b){if(b<a.c){b+=a.f;var c=a.a[b];return c===J?a.a[b]=[]:c}if(a.b)return c=a.b[b],c===J?a.b[b]=[]:c}G.prototype.toString=function(){return this.a.toString()};function L(a){var b=a;a=M;b||(b=[]);this.f=-1;this.a=b;a:{if(b=this.a.length){--b;var c=this.a[b];if(!(null===c||"object"!=typeof c||"array"==m(c)||H&&c instanceof Uint8Array)){this.c=b- -1;this.b=c;break a}}this.c=Number.MAX_VALUE}if(a)for(b=0;b<a.length;b++)if(c=a[b],c<this.c)c+=-1,this.a[c]=this.a[c]||J;else{var d=this.c+-1;this.a[d]||(this.b=this.a[d]={});this.b[c]=this.b[c]||J}}n(L,G);var M=[1,3];l("parseClientVariations",function(a){var b="";try{b=atob(a)}catch(d){}a=[];for(var c=0;c<b.length;c++)a.push(b.charCodeAt(c));b=new D(a);for(a=new L;E(b)&&4!=b.b;)switch(b.c){case 1:c=b.a.h();K(a,1).push(c);break;case 3:c=b.a.h();K(a,3).push(c);break;default:F(b)}return{variationIds:K(a,1),triggerVariationIds:K(a,3)}}); +(function(){var f=this||self;function l(a,b){a=a.split(".");var c=f;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}:c[d]=b}function m(a,b){function c(){}c.prototype=b.prototype;a.m=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.base=function(d,e,g){for(var k=Array(arguments.length-2),h=2;h<arguments.length;h++)k[h-2]=arguments[h];return b.prototype[e].apply(d,k)}};function n(a){if(Error.captureStackTrace)Error.captureStackTrace(this,n);else{const b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))}m(n,Error);n.prototype.name="CustomError";function p(a,b){a=a.split("%s");for(var c="",d=a.length-1,e=0;e<d;e++)c+=a[e]+(e<b.length?b[e]:"%s");n.call(this,c+a[d])}m(p,n);p.prototype.name="AssertionError";function q(a,b){throw new p("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));};function r(){this.a=""}r.prototype.toString=function(){return"SafeScript{"+this.a+"}"};r.prototype.g=function(a){this.a=a};(new r).g("");function t(){this.l=""}t.prototype.toString=function(){return"SafeStyle{"+this.l+"}"};t.prototype.g=function(a){this.l=a};(new t).g("");function u(){this.j=""}u.prototype.toString=function(){return"SafeStyleSheet{"+this.j+"}"};u.prototype.g=function(a){this.j=a};(new u).g("");function v(){this.a=""}v.prototype.toString=function(){return"SafeHtml{"+this.a+"}"};v.prototype.g=function(a){this.a=a};(new v).g("<!DOCTYPE html>");(new v).g("");(new v).g("<br>");var w=null;function x(a){var b=a.length,c=3*b/4;c%3?c=Math.floor(c):-1!="=.".indexOf(a[b-1])&&(c=-1!="=.".indexOf(a[b-2])?c-2:c-1);var d=new Uint8Array(c),e=0;y(a,function(g){d[e++]=g});return d.subarray(0,e)} +function y(a,b){function c(N){for(;d<a.length;){var z=a.charAt(d++),B=w[z];if(null!=B)return B;if(!/^[\s\xa0]*$/.test(z))throw Error("Unknown base64 encoding at char: "+z);}return N}A();for(var d=0;;){var e=c(-1),g=c(0),k=c(64),h=c(64);if(64===h&&-1===e)break;b(e<<2|g>>4);64!=k&&(b(g<<4&240|k>>2),64!=h&&b(k<<6&192|h))}} +function A(){if(!w){w={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),b=["+/=","+/","-_=","-_.","-_"],c=0;5>c;c++)for(var d=a.concat(b[c].split("")),e=0;e<d.length;e++){var g=d[e];void 0===w[g]&&(w[g]=e)}}};function C(a){if(a.constructor===Uint8Array)return a;if(a.constructor===ArrayBuffer||"undefined"!=typeof Buffer&&a.constructor===Buffer||a.constructor===Array)return new Uint8Array(a);if(a.constructor===String)return x(a);q("Type not convertible to Uint8Array.");return new Uint8Array(0)};function D(a){this.b=null;this.a=this.h=this.i=0;a&&E(this,a)}var F=[];function E(a,b){a.b=C(b);a.i=0;a.h=a.b.length;a.a=a.i}D.prototype.reset=function(){this.a=this.i}; +D.prototype.f=function(){var a=this.b;var b=a[this.a];var c=b&127;if(128>b)return this.a+=1,c;b=a[this.a+1];c|=(b&127)<<7;if(128>b)return this.a+=2,c;b=a[this.a+2];c|=(b&127)<<14;if(128>b)return this.a+=3,c;b=a[this.a+3];c|=(b&127)<<21;if(128>b)return this.a+=4,c;b=a[this.a+4];c|=(b&15)<<28;if(128>b)return this.a+=5,c>>>0;this.a+=5;128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&this.a++;return c};D.prototype.c=D.prototype.f;function G(a){if(F.length){var b=F.pop();a&&E(b,a);a=b}else a=new D(a);this.a=a;this.h=this.a.a;this.b=this.c=-1;this.f=!1}G.prototype.reset=function(){this.a.reset();this.b=this.c=-1};function H(a){var b=a.a;if(b.a==b.h)return!1;(b=a.f)||(b=a.a,b=0>b.a||b.a>b.h);if(b)return q("Decoder hit an error"),!1;a.h=a.a.a;var c=a.a.f();b=c>>>3;c&=7;if(0!=c&&5!=c&&1!=c&&2!=c&&3!=c&&4!=c)return q("Invalid wire type: %s (at position %s)",c,a.h),a.f=!0,!1;a.c=b;a.b=c;return!0} +function I(a){switch(a.b){case 0:if(0!=a.b)q("Invalid wire type for skipVarintField"),I(a);else{for(a=a.a;a.b[a.a]&128;)a.a++;a.a++}break;case 1:1!=a.b?(q("Invalid wire type for skipFixed64Field"),I(a)):(a=a.a,a.a+=8);break;case 2:if(2!=a.b)q("Invalid wire type for skipDelimitedField"),I(a);else{var b=a.a.f();a=a.a;a.a+=b}break;case 5:5!=a.b?(q("Invalid wire type for skipFixed32Field"),I(a)):(a=a.a,a.a+=4);break;case 3:b=a.c;do{if(!H(a)){q("Unmatched start-group tag: stream EOF");a.f=!0;break}if(4== +a.b){a.c!=b&&(q("Unmatched end-group tag"),a.f=!0);break}I(a)}while(1);break;default:q("Invalid wire encoding for field.")}}function J(a,b){var c=a.a.f();c=a.a.a+c;for(var d=[];a.a.a<c;)d.push(b.call(a.a));return d};function K(){}var L="function"==typeof Uint8Array,M=Object.freeze?Object.freeze([]):[];function O(a,b){if(b<a.c){b+=a.f;var c=a.a[b];return c===M?a.a[b]=[]:c}if(a.b)return c=a.b[b],c===M?a.b[b]=[]:c}K.prototype.toString=function(){return this.a.toString()};function P(a){var b=a;a=Q;b||(b=[]);this.f=-1;this.a=b;a:{if(b=this.a.length){--b;var c=this.a[b];if(!(null===c||"object"!=typeof c||Array.isArray(c)||L&&c instanceof Uint8Array)){this.c=b- -1;this.b=c;break a}}this.c=Number.MAX_VALUE}if(a)for(b=0;b<a.length;b++)if(c=a[b],c<this.c)c+=-1,this.a[c]=this.a[c]||M;else{var d=this.c+-1;this.a[d]||(this.b=this.a[d]={});this.b[c]=this.b[c]||M}}m(P,K);var Q=[1,3]; +function R(a){a=new G(a);for(var b=new P;H(a)&&4!=a.b;)switch(a.c){case 1:for(var c=2==a.b?J(a,a.a.c):[a.a.c()],d=0;d<c.length;d++){var e=c[d];O(b,1).push(e)}break;case 3:c=2==a.b?J(a,a.a.c):[a.a.c()];for(d=0;d<c.length;d++)e=c[d],O(b,3).push(e);break;default:I(a)}return b};l("parseClientVariations",function(a){var b="";try{b=atob(a)}catch(c){}a=[];for(let c=0;c<b.length;c++)a.push(b.charCodeAt(c));b=null;try{b=R(a)}catch(c){b=R([])}return{variationIds:O(b,1),triggerVariationIds:O(b,3)}}); l("formatClientVariations",function(a,b="Active client experiment variation IDs.",c="Active client experiment variation IDs that trigger server-side behavior."){const d=a.variationIds;a=a.triggerVariationIds;const e=["message ClientVariations {"];d.length&&e.push(` // ${b}`,` repeated int32 variation_id = [${d.join(", ")}];`);a.length&&e.push(` // ${c}`,` repeated int32 trigger_variation_id = [${a.join(", ")}];`);e.push("}");return e.join("\n")});}).call(gen); // clang-format on
diff --git a/components/variations/proto/devtools/client_variations_uncompiled.js b/components/variations/proto/devtools/client_variations_uncompiled.js index 7ca4ce4..60ea991 100644 --- a/components/variations/proto/devtools/client_variations_uncompiled.js +++ b/components/variations/proto/devtools/client_variations_uncompiled.js
@@ -31,8 +31,15 @@ bytes.push(decoded.charCodeAt(i)); } - - const parsed = ClientVariations.deserializeBinary(bytes); + let parsed = null; + try { + parsed = ClientVariations.deserializeBinary(bytes); + } catch (e) { + // Deserialization is never expected to fail in Chromium, + // but might fail in downstream repositories such as Edgium or + // if any website uses the same header name 'x-client-data' + parsed = ClientVariations.deserializeBinary([]); + } return { 'variationIds': parsed.getVariationIdList(), 'triggerVariationIds': parsed.getTriggerVariationIdList(),
diff --git a/components/variations/proto/study.proto b/components/variations/proto/study.proto index 7db6a83..71cfd3b7 100644 --- a/components/variations/proto/study.proto +++ b/components/variations/proto/study.proto
@@ -231,6 +231,7 @@ PLATFORM_ANDROID_WEBVIEW = 6; PLATFORM_FUCHSIA = 7; PLATFORM_ANDROID_WEBLAYER = 8; + PLATFORM_CHROMEOS_LACROS = 9; } // Possible form factors Chrome is running on.
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc index ea7ba04..8c75a3a 100644 --- a/components/variations/service/variations_service.cc +++ b/components/variations/service/variations_service.cc
@@ -108,12 +108,13 @@ return "mac"; #elif BUILDFLAG(IS_CHROMEOS_ASH) return "chromeos"; +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + return "chromeos_lacros"; #elif defined(OS_ANDROID) return "android"; #elif defined(OS_FUCHSIA) return "fuchsia"; -#elif (defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) || \ - defined(OS_BSD) || defined(OS_SOLARIS) +#elif defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS) // Default BSD and SOLARIS to Linux to not break those builds, although these // platforms are not officially supported by Chrome. return "linux";
diff --git a/components/variations/study_filtering_unittest.cc b/components/variations/study_filtering_unittest.cc index 4222415c2..9352637 100644 --- a/components/variations/study_filtering_unittest.cc +++ b/components/variations/study_filtering_unittest.cc
@@ -218,12 +218,14 @@ Study::PLATFORM_MAC, Study::PLATFORM_LINUX, Study::PLATFORM_CHROMEOS, + Study::PLATFORM_CHROMEOS_LACROS, Study::PLATFORM_ANDROID, Study::PLATFORM_IOS, Study::PLATFORM_ANDROID_WEBLAYER, Study::PLATFORM_FUCHSIA, Study::PLATFORM_ANDROID_WEBVIEW}; - ASSERT_EQ(Study::Platform_ARRAYSIZE, static_cast<int>(base::size(platforms))); + static_assert(base::size(platforms) == Study::Platform_ARRAYSIZE, + "|platforms| must include all platforms."); bool platform_added[base::size(platforms)] = {false}; Study::Filter filter;
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn index 3bcbec85..ce5490b 100644 --- a/components/viz/common/BUILD.gn +++ b/components/viz/common/BUILD.gn
@@ -268,6 +268,9 @@ "surfaces/parent_local_surface_id_allocator.h", "surfaces/scoped_surface_id_allocator.cc", "surfaces/scoped_surface_id_allocator.h", + "surfaces/subtree_capture_id.cc", + "surfaces/subtree_capture_id.h", + "surfaces/subtree_capture_id_allocator.h", "surfaces/surface_id.cc", "surfaces/surface_id.h", "surfaces/surface_info.cc",
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index 5853adbd6..7a0ed0c82 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -115,6 +115,11 @@ base::FEATURE_DISABLED_BY_DEFAULT}; #endif +// Used to debug Android WebView Vulkan composite. Composite to an intermediate +// buffer and draw the intermediate buffer to the secondary command buffer. +const base::Feature kWebViewVulkanIntermediateBuffer{ + "WebViewVulkanIntermediateBuffer", base::FEATURE_DISABLED_BY_DEFAULT}; + bool IsOverlayPrioritizationEnabled() { return base::FeatureList::IsEnabled(kEnableOverlayPrioritization); }
diff --git a/components/viz/common/features.h b/components/viz/common/features.h index 57abfe69..fb32e0a 100644 --- a/components/viz/common/features.h +++ b/components/viz/common/features.h
@@ -36,6 +36,7 @@ #if defined(USE_X11) VIZ_COMMON_EXPORT extern const base::Feature kUseX11Present; #endif +VIZ_COMMON_EXPORT extern const base::Feature kWebViewVulkanIntermediateBuffer; VIZ_COMMON_EXPORT bool IsForcePreferredIntervalForVideoEnabled(); VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled();
diff --git a/components/viz/common/quads/compositor_render_pass.cc b/components/viz/common/quads/compositor_render_pass.cc index 0ddff20..96c65f3 100644 --- a/components/viz/common/quads/compositor_render_pass.cc +++ b/components/viz/common/quads/compositor_render_pass.cc
@@ -88,6 +88,7 @@ const cc::FilterOperations& filters, const cc::FilterOperations& backdrop_filters, const base::Optional<gfx::RRectF>& backdrop_filter_bounds, + SubtreeCaptureId subtree_capture_id, bool has_transparent_background, bool cache_render_pass, bool has_damage_from_contributing_content, @@ -101,6 +102,7 @@ this->filters = filters; this->backdrop_filters = backdrop_filters; this->backdrop_filter_bounds = backdrop_filter_bounds; + this->subtree_capture_id = subtree_capture_id; this->has_transparent_background = has_transparent_background; this->cache_render_pass = cache_render_pass; this->has_damage_from_contributing_content = @@ -222,8 +224,9 @@ quad_list.size()); copy_pass->SetAll(id, output_rect, damage_rect, transform_to_root_target, filters, backdrop_filters, backdrop_filter_bounds, - has_transparent_background, cache_render_pass, - has_damage_from_contributing_content, generate_mipmap); + subtree_capture_id, has_transparent_background, + cache_render_pass, has_damage_from_contributing_content, + generate_mipmap); if (shared_quad_state_list.empty()) { DCHECK(quad_list.empty());
diff --git a/components/viz/common/quads/compositor_render_pass.h b/components/viz/common/quads/compositor_render_pass.h index c0a6f7b..ca96b4c8 100644 --- a/components/viz/common/quads/compositor_render_pass.h +++ b/components/viz/common/quads/compositor_render_pass.h
@@ -21,6 +21,7 @@ #include "components/viz/common/quads/largest_draw_quad.h" #include "components/viz/common/quads/quad_list.h" #include "components/viz/common/quads/render_pass_internal.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/common/viz_common_export.h" #include "ui/gfx/display_color_spaces.h" #include "ui/gfx/geometry/rect.h" @@ -67,6 +68,7 @@ const cc::FilterOperations& filters, const cc::FilterOperations& backdrop_filters, const base::Optional<gfx::RRectF>& backdrop_filter_bounds, + SubtreeCaptureId subtree_capture_id, bool has_transparent_background, bool cache_render_pass, bool has_damage_from_contributing_content, @@ -85,6 +87,10 @@ // Uniquely identifies the render pass in the compositor's current frame. CompositorRenderPassId id; + // A unique ID that identifies a layer subtree which produces this render + // pass, so that it can be captured by a FrameSinkVideoCapturer. + SubtreeCaptureId subtree_capture_id; + // For testing functions. // TODO(vmpstr): See if we can clean these up by moving the tests to use // AggregatedRenderPasses where appropriate.
diff --git a/components/viz/common/quads/compositor_render_pass_unittest.cc b/components/viz/common/quads/compositor_render_pass_unittest.cc index 720dfd42..e4d22c5 100644 --- a/components/viz/common/quads/compositor_render_pass_unittest.cc +++ b/components/viz/common/quads/compositor_render_pass_unittest.cc
@@ -13,6 +13,7 @@ #include "components/viz/common/quads/aggregated_render_pass.h" #include "components/viz/common/quads/compositor_render_pass_draw_quad.h" #include "components/viz/common/quads/solid_color_draw_quad.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/effects/SkBlurImageFilter.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -37,6 +38,7 @@ EXPECT_EQ(expected->filters, actual->filters); EXPECT_EQ(expected->backdrop_filters, actual->backdrop_filters); EXPECT_EQ(expected->backdrop_filter_bounds, actual->backdrop_filter_bounds); + EXPECT_EQ(expected->subtree_capture_id, actual->subtree_capture_id); EXPECT_EQ(expected->has_transparent_background, actual->has_transparent_background); EXPECT_EQ(expected->generate_mipmap, actual->generate_mipmap); @@ -137,7 +139,7 @@ auto pass = CompositorRenderPass::Create(); pass->SetAll(id, output_rect, damage_rect, transform_to_root, filters, - backdrop_filters, backdrop_filter_bounds, + backdrop_filters, backdrop_filter_bounds, SubtreeCaptureId{1u}, has_transparent_background, cache_render_pass, has_damage_from_contributing_content, generate_mipmap); @@ -191,12 +193,12 @@ bool contrib_generate_mipmap = false; auto contrib = CompositorRenderPass::Create(); - contrib->SetAll(contrib_id, contrib_output_rect, contrib_damage_rect, - contrib_transform_to_root, contrib_filters, - contrib_backdrop_filters, contrib_backdrop_filter_bounds, - contrib_has_transparent_background, contrib_cache_render_pass, - contrib_has_damage_from_contributing_content, - contrib_generate_mipmap); + contrib->SetAll( + contrib_id, contrib_output_rect, contrib_damage_rect, + contrib_transform_to_root, contrib_filters, contrib_backdrop_filters, + contrib_backdrop_filter_bounds, SubtreeCaptureId{2u}, + contrib_has_transparent_background, contrib_cache_render_pass, + contrib_has_damage_from_contributing_content, contrib_generate_mipmap); SharedQuadState* contrib_shared_state = contrib->CreateAndAppendSharedQuadState(); @@ -247,7 +249,7 @@ auto pass = CompositorRenderPass::Create(); pass->SetAll(id, output_rect, damage_rect, transform_to_root, filters, - backdrop_filters, backdrop_filter_bounds, + backdrop_filters, backdrop_filter_bounds, SubtreeCaptureId(), has_transparent_background, cache_render_pass, has_damage_from_contributing_content, generate_mipmap);
diff --git a/components/viz/common/surfaces/subtree_capture_id.cc b/components/viz/common/surfaces/subtree_capture_id.cc new file mode 100644 index 0000000..6be32be --- /dev/null +++ b/components/viz/common/surfaces/subtree_capture_id.cc
@@ -0,0 +1,15 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/common/surfaces/subtree_capture_id.h" + +#include "base/strings/stringprintf.h" + +namespace viz { + +std::string SubtreeCaptureId::ToString() const { + return base::StringPrintf("SubtreeCaptureId(%u)", subtree_id_); +} + +} // namespace viz
diff --git a/components/viz/common/surfaces/subtree_capture_id.h b/components/viz/common/surfaces/subtree_capture_id.h new file mode 100644 index 0000000..3f92911 --- /dev/null +++ b/components/viz/common/surfaces/subtree_capture_id.h
@@ -0,0 +1,48 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_COMMON_SURFACES_SUBTREE_CAPTURE_ID_H_ +#define COMPONENTS_VIZ_COMMON_SURFACES_SUBTREE_CAPTURE_ID_H_ + +#include <cstdint> +#include <string> + +#include "components/viz/common/viz_common_export.h" + +namespace viz { + +// A SubtreeCaptureId uniquely identifies a layer subtree within a +// CompositorFrameSink, which can be captured independently from the root +// CompositorFrameSink by the FrameSinkVideoCapturer. +// +// Use the SubtreeCaptureIdAllocator to allocate a valid instace of this class. +class VIZ_COMMON_EXPORT SubtreeCaptureId { + public: + constexpr SubtreeCaptureId() = default; + constexpr explicit SubtreeCaptureId(uint32_t subtree_id) + : subtree_id_(subtree_id) {} + constexpr SubtreeCaptureId(const SubtreeCaptureId&) = default; + SubtreeCaptureId& operator=(const SubtreeCaptureId&) = default; + ~SubtreeCaptureId() = default; + + constexpr bool is_valid() const { return subtree_id_ != 0; } + constexpr uint32_t subtree_id() const { return subtree_id_; } + + bool operator==(const SubtreeCaptureId& rhs) const { + return subtree_id_ == rhs.subtree_id_; + } + bool operator!=(const SubtreeCaptureId& rhs) const { return !(*this == rhs); } + bool operator<(const SubtreeCaptureId& rhs) const { + return subtree_id_ < rhs.subtree_id_; + } + + std::string ToString() const; + + private: + uint32_t subtree_id_ = 0; +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_COMMON_SURFACES_SUBTREE_CAPTURE_ID_H_
diff --git a/components/viz/common/surfaces/subtree_capture_id_allocator.h b/components/viz/common/surfaces/subtree_capture_id_allocator.h new file mode 100644 index 0000000..330491f9 --- /dev/null +++ b/components/viz/common/surfaces/subtree_capture_id_allocator.h
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_COMMON_SURFACES_SUBTREE_CAPTURE_ID_ALLOCATOR_H_ +#define COMPONENTS_VIZ_COMMON_SURFACES_SUBTREE_CAPTURE_ID_ALLOCATOR_H_ + +#include <cstdint> + +#include "components/viz/common/surfaces/subtree_capture_id.h" + +namespace viz { + +// Generates SubtreeCaptureId's by incrementally increasing the subtree_id's. +class VIZ_COMMON_EXPORT SubtreeCaptureIdAllocator { + public: + SubtreeCaptureIdAllocator() = default; + SubtreeCaptureIdAllocator(const SubtreeCaptureIdAllocator&) = delete; + SubtreeCaptureIdAllocator& operator=(const SubtreeCaptureIdAllocator&) = + delete; + ~SubtreeCaptureIdAllocator() = default; + + SubtreeCaptureId NextSubtreeCaptureId() { + return SubtreeCaptureId(next_subtree_id_++); + } + + private: + uint32_t next_subtree_id_ = 1u; +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_COMMON_SURFACES_SUBTREE_CAPTURE_ID_ALLOCATOR_H_
diff --git a/components/viz/host/client_frame_sink_video_capturer.cc b/components/viz/host/client_frame_sink_video_capturer.cc index b77d91d2..405ec19 100644 --- a/components/viz/host/client_frame_sink_video_capturer.cc +++ b/components/viz/host/client_frame_sink_video_capturer.cc
@@ -72,11 +72,13 @@ } void ClientFrameSinkVideoCapturer::ChangeTarget( - const base::Optional<FrameSinkId>& frame_sink_id) { + const base::Optional<FrameSinkId>& frame_sink_id, + SubtreeCaptureId subtree_capture_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); target_ = frame_sink_id; - capturer_remote_->ChangeTarget(frame_sink_id); + subtree_capture_id_ = subtree_capture_id; + capturer_remote_->ChangeTarget(frame_sink_id, subtree_capture_id); } void ClientFrameSinkVideoCapturer::Start( @@ -192,7 +194,7 @@ if (auto_throttling_enabled_) capturer_remote_->SetAutoThrottlingEnabled(*auto_throttling_enabled_); if (target_) - capturer_remote_->ChangeTarget(target_); + capturer_remote_->ChangeTarget(target_, subtree_capture_id_); for (Overlay* overlay : overlays_) overlay->EstablishConnection(capturer_remote_.get()); if (is_started_)
diff --git a/components/viz/host/client_frame_sink_video_capturer.h b/components/viz/host/client_frame_sink_video_capturer.h index 993a2db..019a5ea 100644 --- a/components/viz/host/client_frame_sink_video_capturer.h +++ b/components/viz/host/client_frame_sink_video_capturer.h
@@ -13,6 +13,7 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/host/viz_host_export.h" #include "media/base/video_types.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -83,7 +84,8 @@ const gfx::Size& max_size, bool use_fixed_aspect_ratio); void SetAutoThrottlingEnabled(bool enabled); - void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id); + void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id, + SubtreeCaptureId subtree_capture_id); void Stop(); void RequestRefreshFrame(); @@ -151,6 +153,7 @@ base::Optional<ResolutionConstraints> resolution_constraints_; base::Optional<bool> auto_throttling_enabled_; base::Optional<FrameSinkId> target_; + SubtreeCaptureId subtree_capture_id_; // Overlays are owned by the callers of CreateOverlay(). std::vector<Overlay*> overlays_; bool is_started_ = false;
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 504c1f1e..c66d791c 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -161,6 +161,8 @@ "hit_test/hit_test_manager.cc", "hit_test/hit_test_manager.h", "surfaces/latest_local_surface_id_lookup_delegate.h", + "surfaces/pending_copy_output_request.cc", + "surfaces/pending_copy_output_request.h", "surfaces/referenced_surface_tracker.cc", "surfaces/referenced_surface_tracker.h", "surfaces/surface.cc", @@ -433,12 +435,19 @@ sources += [ "display_embedder/skia_output_device_vulkan.cc", "display_embedder/skia_output_device_vulkan.h", - "display_embedder/skia_output_device_vulkan_secondary_cb.cc", - "display_embedder/skia_output_device_vulkan_secondary_cb.h", ] public_deps += [ "//gpu/vulkan" ] + if (is_android) { + sources += [ + "display_embedder/skia_output_device_vulkan_secondary_cb.cc", + "display_embedder/skia_output_device_vulkan_secondary_cb.h", + "display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc", + "display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h", + ] + } + if (use_x11 || ozone_platform_x11) { sources += [ "display_embedder/output_presenter_x11.cc",
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc index ff06e95..86d958e 100644 --- a/components/viz/service/display/display_unittest.cc +++ b/components/viz/service/display/display_unittest.cc
@@ -29,6 +29,7 @@ #include "components/viz/common/quads/surface_draw_quad.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/service/display/aggregated_frame.h" #include "components/viz/service/display/delegated_ink_point_renderer_skia.h" #include "components/viz/service/display/direct_renderer.h" @@ -734,8 +735,8 @@ bd_pass->SetAll(render_pass_id_generator.GenerateNextId(), sub_surface_rect, no_damage, gfx::Transform(), cc::FilterOperations(), backdrop_filters, - gfx::RRectF(gfx::RectF(sub_surface_rect), 0), false, - false, false, false); + gfx::RRectF(gfx::RectF(sub_surface_rect), 0), + SubtreeCaptureId(), false, false, false, false); pass_list.push_back(std::move(bd_pass)); CompositorFrame frame = CompositorFrameBuilder()
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc index a5a95f40..2dcab904 100644 --- a/components/viz/service/display/surface_aggregator_unittest.cc +++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -32,11 +32,13 @@ #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/yuv_video_draw_quad.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/service/display/aggregated_frame.h" #include "components/viz/service/display/display_resource_provider.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/surfaces/pending_copy_output_request.h" #include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_manager.h" #include "components/viz/test/compositor_frame_helpers.h" @@ -917,8 +919,8 @@ CopyOutputRequest* RequestCopyOfOutput() { auto copy_request = CopyOutputRequest::CreateStubForTesting(); auto* copy_request_ptr = copy_request.get(); - root_sink_->RequestCopyOfOutput(local_surface_id(), - std::move(copy_request)); + root_sink_->RequestCopyOfOutput(PendingCopyOutputRequest{ + local_surface_id(), SubtreeCaptureId(), std::move(copy_request)}); return copy_request_ptr; } @@ -1590,8 +1592,8 @@ embedded_local_surface_id, device_scale_factor); auto copy_request = CopyOutputRequest::CreateStubForTesting(); auto* copy_request_ptr = copy_request.get(); - embedded_support->RequestCopyOfOutput(embedded_local_surface_id, - std::move(copy_request)); + embedded_support->RequestCopyOfOutput( + {embedded_local_surface_id, SubtreeCaptureId(), std::move(copy_request)}); std::vector<Quad> root_quads = { Quad::SolidColorQuad(SK_ColorWHITE, gfx::Rect(5, 5)), @@ -1743,8 +1745,8 @@ embedded_local_surface_id, device_scale_factor); auto copy_request(CopyOutputRequest::CreateStubForTesting()); auto* copy_request_ptr = copy_request.get(); - embedded_support->RequestCopyOfOutput(embedded_local_surface_id, - std::move(copy_request)); + embedded_support->RequestCopyOfOutput( + {embedded_local_surface_id, SubtreeCaptureId(), std::move(copy_request)}); ParentLocalSurfaceIdAllocator parent_allocator; parent_allocator.GenerateId(); @@ -8862,8 +8864,8 @@ // Now add a CopyOutputRequest on the child surface, so that the delegated // ink metadata does get populated on the aggregated frame. auto copy_request = CopyOutputRequest::CreateStubForTesting(); - child_sink_->RequestCopyOfOutput(child_local_surface_id, - std::move(copy_request)); + child_sink_->RequestCopyOfOutput( + {child_local_surface_id, SubtreeCaptureId(), std::move(copy_request)}); aggregated_frame = AggregateFrame(root_surface_id);
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.h b/components/viz/service/display_embedder/skia_output_device_offscreen.h index 9457d65..c2eed60 100644 --- a/components/viz/service/display_embedder/skia_output_device_offscreen.h +++ b/components/viz/service/display_embedder/skia_output_device_offscreen.h
@@ -48,13 +48,13 @@ sk_sp<SkSurface> sk_surface_; GrBackendTexture backend_texture_; bool supports_rgbx_ = true; - - private: gfx::Size size_; gfx::BufferFormat format_ = gfx::BufferFormat::RGBA_8888; - uint64_t backbuffer_estimated_size_ = 0; sk_sp<SkColorSpace> sk_color_space_; + private: + uint64_t backbuffer_estimated_size_ = 0; + DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceOffscreen); };
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc new file mode 100644 index 0000000..cfdd7e4 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.cc
@@ -0,0 +1,86 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h" + +#include <utility> + +#include "components/viz/common/gpu/vulkan_context_provider.h" +#include "gpu/command_buffer/service/skia_utils.h" +#include "gpu/vulkan/vulkan_device_queue.h" +#include "gpu/vulkan/vulkan_function_pointers.h" +#include "skia/ext/legacy_display_globals.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkDeferredDisplayList.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/core/SkSurfaceCharacterization.h" +#include "third_party/skia/include/gpu/GrBackendSurface.h" +#include "third_party/skia/include/gpu/GrDirectContext.h" +#include "third_party/skia/src/gpu/vk/GrVkSecondaryCBDrawContext.h" +#include "ui/gfx/presentation_feedback.h" +#include "ui/gfx/swap_result.h" + +namespace viz { + +SkiaOutputDeviceVulkanSecondaryCBOffscreen:: + SkiaOutputDeviceVulkanSecondaryCBOffscreen( + scoped_refptr<gpu::SharedContextState> context_state, + gpu::MemoryTracker* memory_tracker, + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback) + : SkiaOutputDeviceOffscreen(std::move(context_state), + gfx::SurfaceOrigin::kTopLeft, + /*has_alpha=*/true, + memory_tracker, + std::move(did_swap_buffer_complete_callback)) { + DCHECK(context_state_->vk_context_provider()); + capabilities_.max_frames_pending = 1; + capabilities_.preserve_buffer_content = false; + capabilities_.supports_post_sub_buffer = false; +} + +SkiaOutputDeviceVulkanSecondaryCBOffscreen:: + ~SkiaOutputDeviceVulkanSecondaryCBOffscreen() = default; + +SkSurface* SkiaOutputDeviceVulkanSecondaryCBOffscreen::BeginPaint( + std::vector<GrBackendSemaphore>* end_semaphores) { + SkSurface* sk_surface = SkiaOutputDeviceOffscreen::BeginPaint(end_semaphores); + sk_surface->getCanvas()->clear(SK_ColorTRANSPARENT); + return sk_surface; +} + +void SkiaOutputDeviceVulkanSecondaryCBOffscreen::SwapBuffers( + BufferPresentedCallback feedback, + std::vector<ui::LatencyInfo> latency_info) { + StartSwapBuffers(std::move(feedback)); + + auto format_index = static_cast<int>(format_); + const auto& sk_color_type = capabilities_.sk_color_types[format_index]; + DCHECK(sk_color_type != kUnknown_SkColorType) + << "SkColorType is invalid for format: " << format_index; + sk_sp<SkImage> sk_image = SkImage::MakeFromTexture( + context_state_->vk_context_provider()->GetGrContext(), backend_texture_, + kTopLeft_GrSurfaceOrigin, sk_color_type, kPremul_SkAlphaType, + sk_color_space_); + gfx::SwapResult result = gfx::SwapResult::SWAP_ACK; + if (sk_image) { + SkPaint paint; + paint.setBlendMode(SkBlendMode::kSrcOver); + context_state_->vk_context_provider() + ->GetGrSecondaryCBDrawContext() + ->getCanvas() + ->drawImage(sk_image, 0, 0, &paint); + context_state_->vk_context_provider() + ->GetGrSecondaryCBDrawContext() + ->flush(); + } else { + result = gfx::SwapResult::SWAP_FAILED; + } + + FinishSwapBuffers(gfx::SwapCompletionResult(result), + gfx::Size(size_.width(), size_.height()), + std::move(latency_info)); +} + +} // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h new file mode 100644 index 0000000..98f6c16 --- /dev/null +++ b/components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h
@@ -0,0 +1,35 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_SECONDARY_CB_OFFSCREEN_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_SECONDARY_CB_OFFSCREEN_H_ + +#include <vector> + +#include "components/viz/service/display_embedder/skia_output_device_offscreen.h" +#include "gpu/command_buffer/service/shared_context_state.h" + +namespace viz { + +// Draw into an offscreen buffer which is then drawn to into the secondary +// command buffer. This is meant to for debugging direct compositing with +// secondary command buffers. +class SkiaOutputDeviceVulkanSecondaryCBOffscreen final + : public SkiaOutputDeviceOffscreen { + public: + SkiaOutputDeviceVulkanSecondaryCBOffscreen( + scoped_refptr<gpu::SharedContextState> context_state, + gpu::MemoryTracker* memory_tracker, + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback); + ~SkiaOutputDeviceVulkanSecondaryCBOffscreen() override; + + SkSurface* BeginPaint( + std::vector<GrBackendSemaphore>* end_semaphores) override; + void SwapBuffers(BufferPresentedCallback feedback, + std::vector<ui::LatencyInfo> latency_info) override; +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_VULKAN_SECONDARY_CB_OFFSCREEN_H_
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 1b1d8e0..d40f19c36 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -50,8 +50,11 @@ #if BUILDFLAG(ENABLE_VULKAN) #include "components/viz/service/display_embedder/skia_output_device_vulkan.h" -#include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb.h" #include "gpu/vulkan/vulkan_util.h" +#if defined(OS_ANDROID) +#include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb.h" +#include "components/viz/service/display_embedder/skia_output_device_vulkan_secondary_cb_offscreen.h" +#endif #endif #if (BUILDFLAG(ENABLE_VULKAN) || BUILDFLAG(SKIA_USE_DAWN)) && defined(USE_X11) @@ -1249,12 +1252,22 @@ #endif // !defined(OS_WIN) (void)needs_background_image; +#if defined(OS_ANDROID) if (vulkan_context_provider_->GetGrSecondaryCBDrawContext()) { - output_device_ = std::make_unique<SkiaOutputDeviceVulkanSecondaryCB>( - vulkan_context_provider_, shared_gpu_deps_->memory_tracker(), - GetDidSwapBuffersCompleteCallback()); + if (base::FeatureList::IsEnabled( + features::kWebViewVulkanIntermediateBuffer)) { + output_device_ = + std::make_unique<SkiaOutputDeviceVulkanSecondaryCBOffscreen>( + context_state_, shared_gpu_deps_->memory_tracker(), + GetDidSwapBuffersCompleteCallback()); + } else { + output_device_ = std::make_unique<SkiaOutputDeviceVulkanSecondaryCB>( + vulkan_context_provider_, shared_gpu_deps_->memory_tracker(), + GetDidSwapBuffersCompleteCallback()); + } return true; } +#endif #if defined(USE_X11) if (!features::IsUsingOzonePlatform()) {
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc index e677ecec1..94c8969b 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -256,16 +256,17 @@ surface_resource_holder_.ReceiveFromChild(resources); } -std::vector<std::unique_ptr<CopyOutputRequest>> +std::vector<PendingCopyOutputRequest> CompositorFrameSinkSupport::TakeCopyOutputRequests( const LocalSurfaceId& latest_local_id) { - std::vector<std::unique_ptr<CopyOutputRequest>> results; + std::vector<PendingCopyOutputRequest> results; for (auto it = copy_output_requests_.begin(); it != copy_output_requests_.end();) { // Requests with a non-valid local id should be satisfied as soon as // possible. - if (!it->first.is_valid() || it->first <= latest_local_id) { - results.push_back(std::move(it->second)); + if (!it->local_surface_id.is_valid() || + it->local_surface_id <= latest_local_id) { + results.push_back(std::move(*it)); it = copy_output_requests_.erase(it); } else { ++it; @@ -765,10 +766,8 @@ } void CompositorFrameSinkSupport::RequestCopyOfOutput( - const LocalSurfaceId& local_surface_id, - std::unique_ptr<CopyOutputRequest> copy_request) { - copy_output_requests_.push_back( - std::make_pair(local_surface_id, std::move(copy_request))); + PendingCopyOutputRequest pending_copy_output_request) { + copy_output_requests_.push_back(std::move(pending_copy_output_request)); if (last_activated_surface_id_.is_valid()) { BeginFrameAck ack; ack.has_damage = true;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h index 3a5f1fa..82c63a7 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -6,6 +6,7 @@ #define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_H_ #include <memory> +#include <set> #include <vector> #include "base/callback.h" @@ -127,7 +128,7 @@ const std::vector<TransferableResource>& resources) override; // Takes the CopyOutputRequests that were requested for a surface with at // most |local_surface_id|. - std::vector<std::unique_ptr<CopyOutputRequest>> TakeCopyOutputRequests( + std::vector<PendingCopyOutputRequest> TakeCopyOutputRequests( const LocalSurfaceId& local_surface_id) override; void OnFrameTokenChanged(uint32_t frame_token) override; void OnSurfaceProcessed(Surface* surface) override; @@ -179,8 +180,8 @@ void AttachCaptureClient(CapturableFrameSink::Client* client) override; void DetachCaptureClient(CapturableFrameSink::Client* client) override; gfx::Size GetActiveFrameSize() override; - void RequestCopyOfOutput(const LocalSurfaceId& local_surface_id, - std::unique_ptr<CopyOutputRequest> request) override; + void RequestCopyOfOutput( + PendingCopyOutputRequest pending_copy_output_request) override; const CompositorFrameMetadata* GetLastActivatedFrameMetadata() override; HitTestAggregator* GetHitTestAggregator(); @@ -197,8 +198,7 @@ // string. static const char* GetSubmitResultAsString(SubmitResult result); - const std::vector< - std::pair<LocalSurfaceId, std::unique_ptr<CopyOutputRequest>>>& + const std::vector<PendingCopyOutputRequest>& copy_output_requests_for_testing() const { return copy_output_requests_; } @@ -313,13 +313,13 @@ // These are the CopyOutputRequests made on the frame sink (as opposed to // being included as a part of a CompositorFrame). They stay here until a // Surface with a LocalSurfaceId which is at least the stored LocalSurfaceId - // takes them. For example, if we store a pair of LocalSurfaceId stored_id and - // a CopyOutputRequest, then a surface with LocalSurfaceId >= stored_id will - // take it, but a surface with LocalSurfaceId < stored_id will not. Note that - // if stored_id is default initialized, then the next surface will take it - // regardless of its LocalSurfaceId. - std::vector<std::pair<LocalSurfaceId, std::unique_ptr<CopyOutputRequest>>> - copy_output_requests_; + // takes them. For example, for a stored PendingCopyOutputRequest, a surface + // with LocalSurfaceId >= PendingCopyOutputRequest::local_surface_id will take + // it, but a surface with LocalSurfaceId < + // PendingCopyOutputRequest::local_surface_id will not. Note that if the + // PendingCopyOutputRequest::local_surface_id is default initialized, then the + // next surface will take it regardless of its LocalSurfaceId. + std::vector<PendingCopyOutputRequest> copy_output_requests_; mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback compositor_frame_callback_;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc index 62b7554..48538474 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -14,6 +14,7 @@ #include "components/viz/common/frame_sinks/copy_output_result.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/common/surfaces/surface_id.h" #include "components/viz/common/surfaces/surface_info.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" @@ -793,6 +794,60 @@ std::move(finished).Run(); } +TEST_F(CompositorFrameSinkSupportTest, CopyRequestOnSubtree) { + const SurfaceId surface_id(support_->frame_sink_id(), local_surface_id_); + + constexpr SubtreeCaptureId kSubtreeId1(22); + constexpr SubtreeCaptureId kSubtreeId2(44); + + { + auto frame = CompositorFrameBuilder() + .AddDefaultRenderPass() + .AddDefaultRenderPass() + .SetReferencedSurfaces({SurfaceRange(surface_id)}) + .Build(); + frame.render_pass_list.front()->subtree_capture_id = kSubtreeId1; + support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)); + EXPECT_EQ(surface_observer_.last_created_surface_id().local_surface_id(), + local_surface_id_); + } + + // Requesting copy of output of a render pass identifiable by a valid + // SubtreeCaptureId. + bool called1 = false; + base::RunLoop called1_run_loop; + auto request = std::make_unique<CopyOutputRequest>( + CopyOutputRequest::ResultFormat::RGBA_BITMAP, + base::BindOnce(&CopyRequestTestCallback, &called1, + called1_run_loop.QuitClosure())); + support_->RequestCopyOfOutput( + {local_surface_id_, kSubtreeId1, std::move(request)}); + GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient(); + EXPECT_FALSE(called1); + + // Requesting copy of output using a SubtreeCaptureId that has no associated + // render pass. The callback will be called immediately. + bool called2 = false; + base::RunLoop called2_run_loop; + request = std::make_unique<CopyOutputRequest>( + CopyOutputRequest::ResultFormat::RGBA_BITMAP, + base::BindOnce(&CopyRequestTestCallback, &called2, + called2_run_loop.QuitClosure())); + support_->RequestCopyOfOutput( + {local_surface_id_, kSubtreeId2, std::move(request)}); + GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient(); + called2_run_loop.Run(); + EXPECT_FALSE(called1); + EXPECT_TRUE(called2); + + support_->EvictSurface(local_surface_id_); + ExpireAllTemporaryReferences(); + local_surface_id_ = LocalSurfaceId(); + manager_.surface_manager()->GarbageCollectSurfaces(); + called1_run_loop.Run(); + EXPECT_TRUE(called1); +} + TEST_F(CompositorFrameSinkSupportTest, DuplicateCopyRequest) { const SurfaceId surface_id(support_->frame_sink_id(), local_surface_id_); @@ -814,7 +869,8 @@ called1_run_loop.QuitClosure())); request->set_source(kArbitrarySourceId1); - support_->RequestCopyOfOutput(local_surface_id_, std::move(request)); + support_->RequestCopyOfOutput( + {local_surface_id_, SubtreeCaptureId(), std::move(request)}); GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient(); EXPECT_FALSE(called1); @@ -826,7 +882,8 @@ called2_run_loop.QuitClosure())); request->set_source(kArbitrarySourceId2); - support_->RequestCopyOfOutput(local_surface_id_, std::move(request)); + support_->RequestCopyOfOutput( + {local_surface_id_, SubtreeCaptureId(), std::move(request)}); GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient(); // Callbacks have different sources so neither should be called. EXPECT_FALSE(called1); @@ -840,7 +897,8 @@ called3_run_loop.QuitClosure())); request->set_source(kArbitrarySourceId1); - support_->RequestCopyOfOutput(local_surface_id_, std::move(request)); + support_->RequestCopyOfOutput( + {local_surface_id_, SubtreeCaptureId(), std::move(request)}); GetSurfaceForId(surface_id)->TakeCopyOutputRequestsFromClient(); // Two callbacks are from source1, so the first should be called. called1_run_loop.Run(); @@ -1065,7 +1123,8 @@ auto request = std::make_unique<CopyOutputRequest>( CopyOutputRequest::ResultFormat::RGBA_BITMAP, base::BindOnce(StubResultCallback)); - support_->RequestCopyOfOutput(local_surface_id1, std::move(request)); + support_->RequestCopyOfOutput( + {local_surface_id1, SubtreeCaptureId(), std::move(request)}); // First surface takes CopyOutputRequests from its client. Now only the first // surface should report having CopyOutputRequests. @@ -1107,7 +1166,8 @@ auto request = std::make_unique<CopyOutputRequest>( CopyOutputRequest::ResultFormat::RGBA_BITMAP, base::BindOnce(StubResultCallback)); - support_->RequestCopyOfOutput(local_surface_id2, std::move(request)); + support_->RequestCopyOfOutput( + {local_surface_id2, SubtreeCaptureId(), std::move(request)}); // The first surface doesn't have copy output requests, because it can't // satisfy the request that the client has. @@ -1148,7 +1208,8 @@ auto request = std::make_unique<CopyOutputRequest>( CopyOutputRequest::ResultFormat::RGBA_BITMAP, base::BindOnce(StubResultCallback)); - support_->RequestCopyOfOutput(local_surface_id1, std::move(request)); + support_->RequestCopyOfOutput( + {local_surface_id1, SubtreeCaptureId(), std::move(request)}); // Create the second surface. support_->SubmitCompositorFrame(local_surface_id2,
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc index 14d8887..b8c4736 100644 --- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc +++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -7,15 +7,19 @@ #include <stddef.h> #include <stdint.h> +#include <utility> + #include "base/bind.h" #include "base/check_op.h" #include "base/metrics/histogram_functions.h" #include "base/trace_event/trace_event.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/service/display/shared_bitmap_manager.h" #include "components/viz/service/display_embedder/output_surface_provider.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" #include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h" #include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h" +#include "components/viz/service/surfaces/pending_copy_output_request.h" namespace viz { @@ -300,8 +304,8 @@ // |request| will send an empty result when it goes out of scope. return; } - it->second->RequestCopyOfOutput(surface_id.local_surface_id(), - std::move(request)); + it->second->RequestCopyOfOutput(PendingCopyOutputRequest{ + surface_id.local_surface_id(), SubtreeCaptureId(), std::move(request)}); } void FrameSinkManagerImpl::SetHitTestAsyncQueriedDebugRegions(
diff --git a/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h b/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h index ed9e14e..fb5ec96 100644 --- a/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h +++ b/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/time/time.h" +#include "components/viz/service/surfaces/pending_copy_output_request.h" #include "ui/gfx/geometry/size.h" namespace gfx { @@ -17,7 +18,6 @@ namespace viz { class CompositorFrameMetadata; -class CopyOutputRequest; class LocalSurfaceId; // Interface for CompositorFrameSink implementations that support frame sink @@ -60,8 +60,7 @@ // default constructed, then the next surface will provide the copy output // regardless of its LocalSurfaceId. virtual void RequestCopyOfOutput( - const LocalSurfaceId& local_surface_id, - std::unique_ptr<CopyOutputRequest> request) = 0; + PendingCopyOutputRequest pending_copy_output_request) = 0; // Returns the CompositorFrameMetadata of the last activated CompositorFrame. // Return null if no CompositorFrame has activated yet.
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index d5a5739..ce5fca55 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -226,15 +226,18 @@ } void FrameSinkVideoCapturerImpl::ChangeTarget( - const base::Optional<FrameSinkId>& frame_sink_id) { + const base::Optional<FrameSinkId>& frame_sink_id, + const SubtreeCaptureId& subtree_capture_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (frame_sink_id) { requested_target_ = *frame_sink_id; + request_subtree_id_ = subtree_capture_id; SetResolvedTarget( frame_sink_manager_->FindCapturableFrameSink(requested_target_)); } else { requested_target_ = FrameSinkId(); + request_subtree_id_ = SubtreeCaptureId(); SetResolvedTarget(nullptr); } } @@ -660,7 +663,8 @@ request->scale_to().ToString().c_str(), utilization)); } - resolved_target_->RequestCopyOfOutput(LocalSurfaceId(), std::move(request)); + resolved_target_->RequestCopyOfOutput( + {LocalSurfaceId(), request_subtree_id_, std::move(request)}); } void FrameSinkVideoCapturerImpl::DidCopyFrame(
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h index 2f0e13f..3319829 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -9,7 +9,9 @@ #include <memory> #include <queue> +#include <string> #include <vector> + #include "base/callback_forward.h" #include "base/containers/flat_map.h" #include "base/macros.h" @@ -22,6 +24,7 @@ #include "base/unguessable_token.h" #include "components/viz/common/quads/compositor_frame_metadata.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h" #include "components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h" #include "components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h" @@ -110,7 +113,8 @@ const gfx::Size& max_size, bool use_fixed_aspect_ratio) final; void SetAutoThrottlingEnabled(bool enabled) final; - void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id) final; + void ChangeTarget(const base::Optional<FrameSinkId>& frame_sink_id, + const SubtreeCaptureId& subtree_capture_id) final; void Start(mojo::PendingRemote<mojom::FrameSinkVideoConsumer> consumer) final; void Stop() final; void RequestRefreshFrame() final; @@ -258,6 +262,12 @@ // ChangeTarget(). FrameSinkId requested_target_; + // If valid, this is the ID of a layer subtree within the requested frame + // sink, whose associated render pass should be captured by this capturer. + // If not valid, then this capturer capturer the root render pass of the + // target frame sink. + SubtreeCaptureId request_subtree_id_; + // The resolved target of video capture, or null if the requested target does // not yet exist (or no longer exists). CapturableFrameSink* resolved_target_ = nullptr;
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc index a0094e46..0f427669 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -19,6 +19,7 @@ #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_result.h" #include "components/viz/common/frame_sinks/copy_output_util.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_manager.h" #include "media/base/limits.h" #include "media/base/video_util.h" @@ -251,8 +252,8 @@ gfx::Size GetActiveFrameSize() override { return source_size(); } void RequestCopyOfOutput( - const LocalSurfaceId& local_surface_id, - std::unique_ptr<CopyOutputRequest> request) override { + PendingCopyOutputRequest pending_copy_output_request) override { + auto& request = pending_copy_output_request.copy_output_request; EXPECT_EQ(CopyOutputResult::Format::I420_PLANES, request->result_format()); EXPECT_NE(base::UnguessableToken(), request->source()); EXPECT_EQ(gfx::Rect(size_set_.source_size), request->area()); @@ -522,7 +523,7 @@ .WillRepeatedly(Return(&frame_sink_)); EXPECT_EQ(FrameSinkId(), capturer_->requested_target()); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); EXPECT_EQ(kFrameSinkId, capturer_->requested_target()); EXPECT_EQ(capturer_.get(), frame_sink_.attached_client()); } @@ -534,7 +535,7 @@ .WillRepeatedly(Return(nullptr)); EXPECT_EQ(FrameSinkId(), capturer_->requested_target()); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); EXPECT_EQ(kFrameSinkId, capturer_->requested_target()); EXPECT_EQ(nullptr, frame_sink_.attached_client()); @@ -569,7 +570,7 @@ // Now, set the target. As it resolves, the capturer will immediately attempt // a refresh capture, which will cancel the timer and trigger a copy request. - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); EXPECT_EQ(1, frame_sink_.num_copy_results()); EXPECT_FALSE(IsRefreshRetryTimerRunning()); @@ -585,7 +586,7 @@ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); EXPECT_FALSE(IsRefreshRetryTimerRunning()); MockConsumer consumer; @@ -678,7 +679,7 @@ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); NiceMock<MockConsumer> consumer; StartCapture(&consumer); @@ -776,7 +777,7 @@ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); NiceMock<MockConsumer> consumer; StartCapture(&consumer); @@ -833,7 +834,7 @@ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); // Start capturing to the first consumer. MockConsumer consumer; @@ -920,7 +921,7 @@ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); MockConsumer consumer; const int num_refresh_frames = 2; // Initial, plus later refresh. @@ -976,7 +977,7 @@ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); MockConsumer consumer; constexpr int num_refresh_frames = 3; // Initial, plus two refreshes after @@ -1073,7 +1074,7 @@ TEST_F(FrameSinkVideoCapturerTest, CompositorFrameMetadataReachesConsumer) { EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); MockConsumer consumer; // Initial refresh frame for starting capture, plus later refresh. @@ -1133,7 +1134,7 @@ TEST_F(FrameSinkVideoCapturerTest, DeliversUpdateRectAndCaptureCounter) { EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); MockConsumer consumer; StartCapture(&consumer); @@ -1248,7 +1249,7 @@ TEST_F(FrameSinkVideoCapturerTest, CaptureCounterSkipsWhenFramesAreDropped) { EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId)) .WillRepeatedly(Return(&frame_sink_)); - capturer_->ChangeTarget(kFrameSinkId); + capturer_->ChangeTarget(kFrameSinkId, SubtreeCaptureId()); MockConsumer consumer; StartCapture(&consumer);
diff --git a/components/viz/service/surfaces/pending_copy_output_request.cc b/components/viz/service/surfaces/pending_copy_output_request.cc new file mode 100644 index 0000000..a541a993 --- /dev/null +++ b/components/viz/service/surfaces/pending_copy_output_request.cc
@@ -0,0 +1,27 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/surfaces/pending_copy_output_request.h" + +#include <utility> + +namespace viz { + +PendingCopyOutputRequest::PendingCopyOutputRequest( + LocalSurfaceId surface_id, + SubtreeCaptureId subtree_id, + std::unique_ptr<CopyOutputRequest> request) + : local_surface_id(surface_id), + subtree_capture_id(subtree_id), + copy_output_request(std::move(request)) {} + +PendingCopyOutputRequest::PendingCopyOutputRequest(PendingCopyOutputRequest&&) = + default; + +PendingCopyOutputRequest& PendingCopyOutputRequest::operator=( + PendingCopyOutputRequest&&) = default; + +PendingCopyOutputRequest::~PendingCopyOutputRequest() = default; + +} // namespace viz
diff --git a/components/viz/service/surfaces/pending_copy_output_request.h b/components/viz/service/surfaces/pending_copy_output_request.h new file mode 100644 index 0000000..4783a5d --- /dev/null +++ b/components/viz/service/surfaces/pending_copy_output_request.h
@@ -0,0 +1,43 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_PENDING_COPY_OUTPUT_REQUEST_H_ +#define COMPONENTS_VIZ_SERVICE_SURFACES_PENDING_COPY_OUTPUT_REQUEST_H_ + +#include <memory> + +#include "components/viz/common/frame_sinks/copy_output_request.h" +#include "components/viz/common/surfaces/local_surface_id.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" +#include "components/viz/service/viz_service_export.h" + +namespace viz { + +// Encapsulates the necessary parameters to request a copy-of-output on a +// surface. +struct VIZ_SERVICE_EXPORT PendingCopyOutputRequest { + PendingCopyOutputRequest(LocalSurfaceId surface_id, + SubtreeCaptureId subtree_id, + std::unique_ptr<CopyOutputRequest> request); + PendingCopyOutputRequest(PendingCopyOutputRequest&&); + PendingCopyOutputRequest& operator=(PendingCopyOutputRequest&&); + ~PendingCopyOutputRequest(); + + // The ID of the local surface which |copy_output_request| will be placed on + // its next composited frame. If this ID is default constructed, then the next + // surface will provide the copy-of-output regardless of its LocalSurfaceId. + LocalSurfaceId local_surface_id; + + // If valid, the |copy_output_request| will be placed on a render pass + // associated with a layer subtree identified by this ID. Otherwise, it will + // be placed on the root render pass. + SubtreeCaptureId subtree_capture_id; + + // The actual copy-of-output request. + std::unique_ptr<CopyOutputRequest> copy_output_request; +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_SURFACES_PENDING_COPY_OUTPUT_REQUEST_H_
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index ae5ea2e..e25a769a 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -15,7 +15,7 @@ #include "base/stl_util.h" #include "base/time/tick_clock.h" #include "base/trace_event/trace_event.h" -#include "components/viz/common/frame_sinks/copy_output_request.h" +#include "components/viz/common/quads/compositor_render_pass.h" #include "components/viz/common/resources/returned_resource.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" @@ -29,6 +29,26 @@ namespace viz { +namespace { + +// Adds the given |request| to the requests of the given |render_pass|, removing +// any duplicate requests made by the same source. +void RequestCopyOfOutputOnRenderPass(std::unique_ptr<CopyOutputRequest> request, + CompositorRenderPass& render_pass) { + if (request->has_source()) { + const base::UnguessableToken& source = request->source(); + // Remove existing CopyOutputRequests made on the Surface by the same + // source. + base::EraseIf(render_pass.copy_requests, + [&source](const std::unique_ptr<CopyOutputRequest>& x) { + return x->has_source() && x->source() == source; + }); + } + render_pass.copy_requests.push_back(std::move(request)); +} + +} // namespace + Surface::PresentationHelper::PresentationHelper( base::WeakPtr<SurfaceClient> surface_client, uint32_t frame_token) @@ -262,25 +282,40 @@ } void Surface::RequestCopyOfOutput( - std::unique_ptr<CopyOutputRequest> copy_request) { + PendingCopyOutputRequest pending_copy_output_request) { TRACE_EVENT1("viz", "Surface::RequestCopyOfOutput", "has_active_frame_data", !!active_frame_data_); + + if (!pending_copy_output_request.subtree_capture_id.is_valid()) { + RequestCopyOfOutputOnRootRenderPass( + std::move(pending_copy_output_request.copy_output_request)); + return; + } + + if (!active_frame_data_) + return; + + for (auto& render_pass : active_frame_data_->frame.render_pass_list) { + if (render_pass->subtree_capture_id == + pending_copy_output_request.subtree_capture_id) { + RequestCopyOfOutputOnRenderPass( + std::move(pending_copy_output_request.copy_output_request), + *render_pass); + return; + } + } +} + +void Surface::RequestCopyOfOutputOnRootRenderPass( + std::unique_ptr<CopyOutputRequest> copy_request) { + TRACE_EVENT1("viz", "Surface::RequestCopyOfOutputOnRootRenderPass", + "has_active_frame_data", !!active_frame_data_); if (!active_frame_data_) return; // |copy_request| auto-sends empty result on out-of-scope. - std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests = - active_frame_data_->frame.render_pass_list.back()->copy_requests; - - if (copy_request->has_source()) { - const base::UnguessableToken& source = copy_request->source(); - // Remove existing CopyOutputRequests made on the Surface by the same - // source. - base::EraseIf(copy_requests, - [&source](const std::unique_ptr<CopyOutputRequest>& x) { - return x->has_source() && x->source() == source; - }); - } - copy_requests.push_back(std::move(copy_request)); + RequestCopyOfOutputOnRenderPass( + std::move(copy_request), + *active_frame_data_->frame.render_pass_list.back()); } void Surface::OnActivationDependencyResolved( @@ -425,7 +460,7 @@ RecomputeActiveReferencedSurfaces(); for (auto& copy_request : old_copy_requests) - RequestCopyOfOutput(std::move(copy_request)); + RequestCopyOfOutputOnRootRenderPass(std::move(copy_request)); UnrefFrameResourcesAndRunCallbacks(std::move(previous_frame_data)); @@ -557,10 +592,10 @@ void Surface::TakeCopyOutputRequestsFromClient() { if (!surface_client_) return; - for (std::unique_ptr<CopyOutputRequest>& request : + for (PendingCopyOutputRequest& request_params : surface_client_->TakeCopyOutputRequests( surface_id().local_surface_id())) { - RequestCopyOfOutput(std::move(request)); + RequestCopyOfOutput(std::move(request_params)); } }
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h index cdf3329..cdc8c82 100644 --- a/components/viz/service/surfaces/surface.h +++ b/components/viz/service/surfaces/surface.h
@@ -25,6 +25,7 @@ #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/surface_info.h" +#include "components/viz/service/surfaces/pending_copy_output_request.h" #include "components/viz/service/surfaces/surface_client.h" #include "components/viz/service/surfaces/surface_dependency_deadline.h" #include "components/viz/service/viz_service_export.h" @@ -311,7 +312,15 @@ CompositorFrame* frame, std::vector<ui::LatencyInfo>* latency_info); - void RequestCopyOfOutput(std::unique_ptr<CopyOutputRequest> copy_request); + // Places the copy-of-output request on the render pass defined by + // |PendingCopyOutputRequest::subtree_capture_id| if such a render pass + // exists, otherwise the request will be ignored. + void RequestCopyOfOutput( + PendingCopyOutputRequest pending_copy_output_request); + + // Always placed the given |copy_request| on the root render pass. + void RequestCopyOfOutputOnRootRenderPass( + std::unique_ptr<CopyOutputRequest> copy_request); const SurfaceInfo surface_info_; SurfaceId previous_frame_surface_id_;
diff --git a/components/viz/service/surfaces/surface_client.h b/components/viz/service/surfaces/surface_client.h index b902e91..d85bca8 100644 --- a/components/viz/service/surfaces/surface_client.h +++ b/components/viz/service/surfaces/surface_client.h
@@ -9,6 +9,7 @@ #include <vector> #include "base/macros.h" +#include "components/viz/service/surfaces/pending_copy_output_request.h" #include "components/viz/service/viz_service_export.h" namespace base { @@ -24,7 +25,6 @@ namespace viz { struct ReturnedResource; class CompositorFrame; -class CopyOutputRequest; class LocalSurfaceId; class Surface; struct TransferableResource; @@ -64,8 +64,8 @@ // Takes all the CopyOutputRequests made at the client level that happened for // a LocalSurfaceId preceeding the given one. - virtual std::vector<std::unique_ptr<CopyOutputRequest>> - TakeCopyOutputRequests(const LocalSurfaceId& latest_surface_id) = 0; + virtual std::vector<PendingCopyOutputRequest> TakeCopyOutputRequests( + const LocalSurfaceId& latest_surface_id) = 0; // Notifies the client that a frame with |token| has been activated. virtual void OnFrameTokenChanged(uint32_t frame_token) = 0;
diff --git a/components/viz/service/surfaces/surface_unittest.cc b/components/viz/service/surfaces/surface_unittest.cc index abd259a..6fce1d1 100644 --- a/components/viz/service/surfaces/surface_unittest.cc +++ b/components/viz/service/surfaces/surface_unittest.cc
@@ -4,15 +4,17 @@ #include <utility> -#include "components/viz/service/surfaces/surface.h" #include "base/bind.h" #include "base/run_loop.h" #include "cc/test/scheduler_test_common.h" #include "components/viz/common/frame_sinks/copy_output_result.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/surfaces/pending_copy_output_request.h" +#include "components/viz/service/surfaces/surface.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/compositor_frame_helpers.h" #include "components/viz/test/fake_external_begin_frame_source.h" @@ -100,12 +102,12 @@ bool copy_called = false; base::RunLoop copy_runloop; - support->RequestCopyOfOutput( - local_surface_id, + support->RequestCopyOfOutput(PendingCopyOutputRequest{ + local_surface_id, SubtreeCaptureId(), std::make_unique<CopyOutputRequest>( CopyOutputRequest::ResultFormat::RGBA_BITMAP, base::BindOnce(&TestCopyResultCallback, ©_called, - copy_runloop.QuitClosure()))); + copy_runloop.QuitClosure()))}); surface->TakeCopyOutputRequestsFromClient(); EXPECT_TRUE(surface_manager->GetSurfaceForId(surface_id)); EXPECT_FALSE(copy_called);
diff --git a/components/viz/test/stub_surface_client.cc b/components/viz/test/stub_surface_client.cc index d880e05..bb33424 100644 --- a/components/viz/test/stub_surface_client.cc +++ b/components/viz/test/stub_surface_client.cc
@@ -12,10 +12,9 @@ StubSurfaceClient::~StubSurfaceClient() = default; -std::vector<std::unique_ptr<CopyOutputRequest>> -StubSurfaceClient::TakeCopyOutputRequests( +std::vector<PendingCopyOutputRequest> StubSurfaceClient::TakeCopyOutputRequests( const LocalSurfaceId& latest_surface_id) { - return std::vector<std::unique_ptr<CopyOutputRequest>>(); + return std::vector<PendingCopyOutputRequest>(); } } // namespace viz
diff --git a/components/viz/test/stub_surface_client.h b/components/viz/test/stub_surface_client.h index 627a366..a6dc7df 100644 --- a/components/viz/test/stub_surface_client.h +++ b/components/viz/test/stub_surface_client.h
@@ -27,7 +27,7 @@ const std::vector<ReturnedResource>& resources) override {} void ReceiveFromChild( const std::vector<TransferableResource>& resources) override {} - std::vector<std::unique_ptr<CopyOutputRequest>> TakeCopyOutputRequests( + std::vector<PendingCopyOutputRequest> TakeCopyOutputRequests( const LocalSurfaceId& latest_surface_id) override; void OnFrameTokenChanged(uint32_t frame_token) override {} void OnSurfaceProcessed(Surface* surface) override {}
diff --git a/components/webapps/webapps_client.h b/components/webapps/webapps_client.h index c972eda..9e850e1 100644 --- a/components/webapps/webapps_client.h +++ b/components/webapps/webapps_client.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_WEBAPPS_WEBAPPS_CLIENT_H_ #define COMPONENTS_WEBAPPS_WEBAPPS_CLIENT_H_ +#include "build/build_config.h" #include "components/security_state/core/security_state.h" class GURL; @@ -44,8 +45,12 @@ content::WebContents* web_contents, InstallTrigger trigger) = 0; +#if defined(OS_ANDROID) virtual bool IsInstallationInProgress(content::WebContents* web_contents, const GURL& manifest_url) = 0; + + virtual bool CanShowAppBanners(content::WebContents* web_contents) = 0; +#endif }; } // namespace webapps
diff --git a/content/browser/accessibility/accessibility_tools_utils_mac.h b/content/browser/accessibility/accessibility_tools_utils_mac.h index 64460518..8ddc3078 100644 --- a/content/browser/accessibility/accessibility_tools_utils_mac.h +++ b/content/browser/accessibility/accessibility_tools_utils_mac.h
@@ -33,6 +33,12 @@ CONTENT_EXPORT NSArray* ChildrenOf(const id node); // +// Returns AXSize and AXPosition attributes for an accessible object. +// +CONTENT_EXPORT NSSize SizeOf(const id node); +CONTENT_EXPORT NSPoint PositionOf(const id node); + +// // Returns (parameterized) attributes of an accessible object, (either // AXUIElement or BrowserAccessibilityCocoa). //
diff --git a/content/browser/accessibility/accessibility_tools_utils_mac.mm b/content/browser/accessibility/accessibility_tools_utils_mac.mm index 84575002..7285ab2 100644 --- a/content/browser/accessibility/accessibility_tools_utils_mac.mm +++ b/content/browser/accessibility/accessibility_tools_utils_mac.mm
@@ -50,6 +50,55 @@ return nil; } +NSSize SizeOf(const id node) { + if (IsBrowserAccessibilityCocoa(node)) { + return [[static_cast<BrowserAccessibilityCocoa*>(node) size] sizeValue]; + } + + if (!IsAXUIElement(node)) { + NOTREACHED() + << "Only AXUIElementRef and BrowserAccessibilityCocoa are supported."; + return NSMakeSize(0, 0); + } + + id value = AttributeValueOf(node, NSAccessibilitySizeAttribute); + if (value && CFGetTypeID(value) == AXValueGetTypeID()) { + AXValueType type = AXValueGetType(static_cast<AXValueRef>(value)); + if (type == kAXValueCGSizeType) { + NSSize size; + if (AXValueGetValue(static_cast<AXValueRef>(value), type, &size)) { + return size; + } + } + } + return NSMakeSize(0, 0); +} + +NSPoint PositionOf(const id node) { + if (IsBrowserAccessibilityCocoa(node)) { + return + [[static_cast<BrowserAccessibilityCocoa*>(node) position] pointValue]; + } + + if (!IsAXUIElement(node)) { + NOTREACHED() + << "Only AXUIElementRef and BrowserAccessibilityCocoa are supported."; + return NSMakePoint(0, 0); + } + + id value = AttributeValueOf(node, NSAccessibilityPositionAttribute); + if (value && CFGetTypeID(value) == AXValueGetTypeID()) { + AXValueType type = AXValueGetType(static_cast<AXValueRef>(value)); + if (type == kAXValueCGPointType) { + NSPoint point; + if (AXValueGetValue(static_cast<AXValueRef>(value), type, &point)) { + return point; + } + } + } + return NSMakePoint(0, 0); +} + NSArray* AttributeNamesOf(const id node) { if (IsBrowserAccessibilityCocoa(node)) return [node accessibilityAttributeNames];
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.h b/content/browser/accessibility/accessibility_tree_formatter_mac.h index 5500a598..c3f5b06 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_mac.h +++ b/content/browser/accessibility/accessibility_tree_formatter_mac.h
@@ -41,10 +41,12 @@ base::Value* dict) const; void RecursiveBuildTree(const id node, + const NSRect& root_rect, const a11y::LineIndexer* line_indexer, base::Value* dict) const; void AddProperties(const id node, + const NSRect& root_rect, const a11y::LineIndexer* line_indexer, base::Value* dict) const; @@ -54,7 +56,8 @@ const ui::AXPropertyNode& property_node, const a11y::LineIndexer* line_indexer) const; - base::Value PopulatePosition(const BrowserAccessibilityCocoa*) const; + base::Value PopulateLocalPosition(const id node, + const NSRect& root_rect) const; base::Value PopulatePoint(NSPoint) const; base::Value PopulateSize(NSSize) const; base::Value PopulateRect(NSRect) const;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm index a12233b2..fa612b1 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm +++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -30,6 +30,8 @@ using content::a11y::AttributeNamesOf; using content::a11y::AttributeValueOf; using content::a11y::ChildrenOf; +using content::a11y::SizeOf; +using content::a11y::PositionOf; using content::a11y::IsAXUIElement; using content::a11y::IsBrowserAccessibilityCocoa; using content::a11y::LineIndexer; @@ -42,9 +44,7 @@ namespace { -const char kPositionDictAttr[] = "position"; -const char kXCoordDictAttr[] = "x"; -const char kYCoordDictAttr[] = "y"; +const char kLocalPositionDictAttr[] = "LocalPosition"; const char kRangeLocDictAttr[] = "loc"; const char kRangeLenDictAttr[] = "len"; @@ -109,8 +109,12 @@ LineIndexer line_indexer(root); base::Value dict(base::Value::Type::DICTIONARY); + NSPoint position = PositionOf(root); + NSSize size = SizeOf(root); + NSRect rect = NSMakeRect(position.x, position.y, size.width, size.height); + EvaluateScripts(&line_indexer, &dict); - RecursiveBuildTree(root, &line_indexer, &dict); + RecursiveBuildTree(root, rect, &line_indexer, &dict); return dict; } @@ -137,15 +141,16 @@ void AccessibilityTreeFormatterMac::RecursiveBuildTree( const id node, + const NSRect& root_rect, const LineIndexer* line_indexer, base::Value* dict) const { - AddProperties(node, line_indexer, dict); + AddProperties(node, root_rect, line_indexer, dict); NSArray* children = ChildrenOf(node); base::Value child_dict_list(base::Value::Type::LIST); for (id child in children) { base::Value child_dict(base::Value::Type::DICTIONARY); - RecursiveBuildTree(child, line_indexer, &child_dict); + RecursiveBuildTree(child, root_rect, line_indexer, &child_dict); child_dict_list.Append(std::move(child_dict)); } dict->SetPath(kChildrenDictAttr, std::move(child_dict_list)); @@ -153,15 +158,11 @@ void AccessibilityTreeFormatterMac::AddProperties( const id node, + const NSRect& root_rect, const LineIndexer* line_indexer, base::Value* dict) const { - // Chromium tree special processing - if (IsBrowserAccessibilityCocoa(node)) { - // Position (no size since it's exposed as standard AXSize attribute) - BrowserAccessibilityCocoa* cocoa_node = - static_cast<BrowserAccessibilityCocoa*>(node); - dict->SetPath(kPositionDictAttr, PopulatePosition(cocoa_node)); - } + // Chromium special attributes. + dict->SetPath(kLocalPositionDictAttr, PopulateLocalPosition(node, root_rect)); // Dump all attributes if match-all filter is specified. if (HasMatchAllPropertyFilter()) { @@ -193,33 +194,22 @@ } } -base::Value AccessibilityTreeFormatterMac::PopulatePosition( - const BrowserAccessibilityCocoa* cocoa_node) const { - BrowserAccessibility* node = [cocoa_node owner]; - BrowserAccessibilityManager* root_manager = node->manager()->GetRootManager(); - DCHECK(root_manager); - +base::Value AccessibilityTreeFormatterMac::PopulateLocalPosition( + const id node, + const NSRect& root_rect) const { // The NSAccessibility position of an object is in global coordinates and // based on the lower-left corner of the object. To make this easier and // less confusing, convert it to local window coordinates using the top-left // corner when dumping the position. - BrowserAccessibility* root = root_manager->GetRoot(); - BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(root); - NSPoint root_position = [[cocoa_root position] pointValue]; - NSSize root_size = [[cocoa_root size] sizeValue]; - int root_top = -static_cast<int>(root_position.y + root_size.height); - int root_left = static_cast<int>(root_position.x); + int root_top = -static_cast<int>(root_rect.origin.y + root_rect.size.height); + int root_left = static_cast<int>(root_rect.origin.x); - NSPoint node_position = [[cocoa_node position] pointValue]; - NSSize node_size = [[cocoa_node size] sizeValue]; + NSPoint node_position = PositionOf(node); + NSSize node_size = SizeOf(node); - base::Value position(base::Value::Type::DICTIONARY); - position.SetIntPath(kXCoordDictAttr, - static_cast<int>(node_position.x - root_left)); - position.SetIntPath( - kYCoordDictAttr, - static_cast<int>(-node_position.y - node_size.height - root_top)); - return position; + return PopulatePoint(NSMakePoint( + static_cast<int>(node_position.x - root_left), + static_cast<int>(-node_position.y - node_size.height - root_top))); } base::Value AccessibilityTreeFormatterMac::PopulateObject( @@ -439,14 +429,6 @@ if (item.first == kChildrenDictAttr) { continue; } - // Special case: position. - if (item.first == kPositionDictAttr) { - WriteAttribute(false, - FormatCoordinates(item.second, kPositionDictAttr, - kXCoordDictAttr, kYCoordDictAttr), - &line); - continue; - } // Write formatted value. std::string formatted_value = FormatAttributeValue(item.second);
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index fe956cf3..a5f5b62ac 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -95,7 +95,7 @@ #include "third_party/blink/public/mojom/device/device.mojom.h" #include "third_party/blink/public/mojom/feature_observer/feature_observer.mojom.h" #include "third_party/blink/public/mojom/file/file_utilities.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom.h" #include "third_party/blink/public/mojom/filesystem/file_system.mojom.h" #include "third_party/blink/public/mojom/geolocation/geolocation_service.mojom.h" #include "third_party/blink/public/mojom/idle/idle_manager.mojom.h" @@ -598,7 +598,7 @@ map->Add<blink::mojom::IdleManager>(base::BindRepeating( &RenderFrameHostImpl::BindIdleManager, base::Unretained(host))); - map->Add<blink::mojom::NativeFileSystemManager>( + map->Add<blink::mojom::FileSystemAccessManager>( base::BindRepeating(&RenderFrameHostImpl::GetNativeFileSystemManager, base::Unretained(host))); @@ -999,7 +999,7 @@ &RenderProcessHostImpl::CreatePermissionService, host)); map->Add<blink::mojom::FileSystemManager>(BindWorkerReceiverForOrigin( &RenderProcessHostImpl::BindFileSystemManager, host)); - map->Add<blink::mojom::NativeFileSystemManager>(BindWorkerReceiverForOrigin( + map->Add<blink::mojom::FileSystemAccessManager>(BindWorkerReceiverForOrigin( &RenderProcessHostImpl::BindNativeFileSystemManager, host)); map->Add<blink::mojom::NativeIOHost>(BindWorkerReceiverForOrigin( &RenderProcessHostImpl::BindNativeIOHost, host)); @@ -1077,7 +1077,7 @@ &RenderProcessHostImpl::CreatePaymentManagerForOrigin, host)); map->Add<blink::mojom::PermissionService>(BindWorkerReceiverForOrigin( &RenderProcessHostImpl::CreatePermissionService, host)); - map->Add<blink::mojom::NativeFileSystemManager>(BindWorkerReceiverForOrigin( + map->Add<blink::mojom::FileSystemAccessManager>(BindWorkerReceiverForOrigin( &RenderProcessHostImpl::BindNativeFileSystemManager, host)); map->Add<blink::mojom::NativeIOHost>(BindWorkerReceiverForOrigin( &RenderProcessHostImpl::BindNativeIOHost, host)); @@ -1178,7 +1178,7 @@ &RenderProcessHostImpl::CreatePaymentManagerForOrigin, host)); map->Add<blink::mojom::PermissionService>(BindServiceWorkerReceiverForOrigin( &RenderProcessHostImpl::CreatePermissionService, host)); - map->Add<blink::mojom::NativeFileSystemManager>( + map->Add<blink::mojom::FileSystemAccessManager>( BindServiceWorkerReceiverForOrigin( &RenderProcessHostImpl::BindNativeFileSystemManager, host)); map->Add<blink::mojom::NativeIOHost>(BindServiceWorkerReceiverForOrigin(
diff --git a/content/browser/compositor/test/test_image_transport_factory.cc b/content/browser/compositor/test/test_image_transport_factory.cc index 7650eac..4559caf 100644 --- a/content/browser/compositor/test/test_image_transport_factory.cc +++ b/content/browser/compositor/test/test_image_transport_factory.cc
@@ -88,6 +88,10 @@ return frame_sink_id_allocator_.NextFrameSinkId(); } +viz::SubtreeCaptureId TestImageTransportFactory::AllocateSubtreeCaptureId() { + return subtree_capture_id_allocator_.NextSubtreeCaptureId(); +} + viz::HostFrameSinkManager* TestImageTransportFactory::GetHostFrameSinkManager() { return &host_frame_sink_manager_;
diff --git a/content/browser/compositor/test/test_image_transport_factory.h b/content/browser/compositor/test/test_image_transport_factory.h index 87a9f09..2b47278 100644 --- a/content/browser/compositor/test/test_image_transport_factory.h +++ b/content/browser/compositor/test/test_image_transport_factory.h
@@ -13,6 +13,7 @@ #include "cc/test/test_task_graph_runner.h" #include "components/viz/common/display/renderer_settings.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" #include "components/viz/test/test_frame_sink_manager.h" #include "components/viz/test/test_gpu_memory_buffer_manager.h" @@ -44,6 +45,7 @@ gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override; cc::TaskGraphRunner* GetTaskGraphRunner() override; viz::FrameSinkId AllocateFrameSinkId() override; + viz::SubtreeCaptureId AllocateSubtreeCaptureId() override; viz::HostFrameSinkManager* GetHostFrameSinkManager() override; // ImageTransportFactory implementation. @@ -56,6 +58,7 @@ viz::TestGpuMemoryBufferManager gpu_memory_buffer_manager_; viz::RendererSettings renderer_settings_; viz::FrameSinkIdAllocator frame_sink_id_allocator_; + viz::SubtreeCaptureIdAllocator subtree_capture_id_allocator_; scoped_refptr<viz::ContextProvider> shared_main_context_provider_; viz::HostFrameSinkManager host_frame_sink_manager_; viz::TestFrameSinkManagerImpl test_frame_sink_manager_impl_;
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc index 8532a82..d22a77a 100644 --- a/content/browser/compositor/viz_process_transport_factory.cc +++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -281,6 +281,10 @@ return frame_sink_id_allocator_.NextFrameSinkId(); } +viz::SubtreeCaptureId VizProcessTransportFactory::AllocateSubtreeCaptureId() { + return subtree_capture_id_allocator_.NextSubtreeCaptureId(); +} + viz::HostFrameSinkManager* VizProcessTransportFactory::GetHostFrameSinkManager() { return host_frame_sink_manager_;
diff --git a/content/browser/compositor/viz_process_transport_factory.h b/content/browser/compositor/viz_process_transport_factory.h index 8097090c..1c34598 100644 --- a/content/browser/compositor/viz_process_transport_factory.h +++ b/content/browser/compositor/viz_process_transport_factory.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "build/build_config.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id_allocator.h" #include "components/viz/service/main/viz_compositor_thread_runner_impl.h" #include "content/browser/compositor/image_transport_factory.h" #include "gpu/command_buffer/common/context_result.h" @@ -70,6 +71,7 @@ gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override; cc::TaskGraphRunner* GetTaskGraphRunner() override; viz::FrameSinkId AllocateFrameSinkId() override; + viz::SubtreeCaptureId AllocateSubtreeCaptureId() override; viz::HostFrameSinkManager* GetHostFrameSinkManager() override; // ImageTransportFactory implementation. @@ -139,6 +141,7 @@ base::flat_map<ui::Compositor*, CompositorData> compositor_data_map_; viz::FrameSinkIdAllocator frame_sink_id_allocator_; + viz::SubtreeCaptureIdAllocator subtree_capture_id_allocator_; viz::HostFrameSinkManager* const host_frame_sink_manager_; scoped_refptr<base::SingleThreadTaskRunner> const resize_task_runner_;
diff --git a/content/browser/devtools/devtools_video_consumer.cc b/content/browser/devtools/devtools_video_consumer.cc index 8ca2835..32095bf 100644 --- a/content/browser/devtools/devtools_video_consumer.cc +++ b/content/browser/devtools/devtools_video_consumer.cc
@@ -8,7 +8,9 @@ #include "base/bind.h" #include "base/memory/shared_memory_mapping.h" +#include "base/optional.h" #include "cc/paint/skia_paint_canvas.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/surface_utils.h" #include "media/base/limits.h" @@ -84,10 +86,11 @@ const viz::FrameSinkId& frame_sink_id) { frame_sink_id_ = frame_sink_id; if (capturer_) { - if (frame_sink_id_.is_valid()) - capturer_->ChangeTarget(frame_sink_id_); - else - capturer_->ChangeTarget(base::nullopt); + capturer_->ChangeTarget( + frame_sink_id_.is_valid() + ? base::make_optional<viz::FrameSinkId>(frame_sink_id_) + : base::nullopt, + viz::SubtreeCaptureId()); } } @@ -129,7 +132,7 @@ kDefaultUseFixedAspectRatio); capturer_->SetFormat(pixel_format_, color_space_); if (frame_sink_id_.is_valid()) - capturer_->ChangeTarget(frame_sink_id_); + capturer_->ChangeTarget(frame_sink_id_, viz::SubtreeCaptureId()); capturer_->Start(this); }
diff --git a/content/browser/devtools/devtools_video_consumer_unittest.cc b/content/browser/devtools/devtools_video_consumer_unittest.cc index 7d4f41d..58bd2e96 100644 --- a/content/browser/devtools/devtools_video_consumer_unittest.cc +++ b/content/browser/devtools/devtools_video_consumer_unittest.cc
@@ -80,8 +80,8 @@ bool use_fixed_aspect_ratio)); // This is never called. MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool)); - void ChangeTarget( - const base::Optional<viz::FrameSinkId>& frame_sink_id) final { + void ChangeTarget(const base::Optional<viz::FrameSinkId>& frame_sink_id, + const viz::SubtreeCaptureId& subtree_capture_id) final { frame_sink_id_ = frame_sink_id ? *frame_sink_id : viz::FrameSinkId(); MockChangeTarget(frame_sink_id_); }
diff --git a/content/browser/direct_sockets/direct_sockets_browsertest.cc b/content/browser/direct_sockets/direct_sockets_browsertest.cc index 439ad0d..26ddcf2 100644 --- a/content/browser/direct_sockets/direct_sockets_browsertest.cc +++ b/content/browser/direct_sockets/direct_sockets_browsertest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <map> #include <vector> #include "base/optional.h" @@ -32,9 +33,12 @@ #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/tcp_socket.mojom.h" #include "services/network/test/test_network_context.h" +#include "testing/gmock/include/gmock/gmock-matchers.h" #include "url/gurl.h" #include "url/url_canon_ip.h" +using testing::StartsWith; + namespace content { namespace { @@ -62,6 +66,11 @@ MockHostResolver(const MockHostResolver&) = delete; MockHostResolver& operator=(const MockHostResolver&) = delete; + static std::map<std::string, std::string>& known_hosts() { + static base::NoDestructor<std::map<std::string, std::string>> hosts; + return *hosts; + } + void ResolveHost(const ::net::HostPortPair& host_port_pair, const ::net::NetworkIsolationKey& network_isolation_key, network::mojom::ResolveHostParametersPtr optional_parameters, @@ -70,7 +79,11 @@ mojo::Remote<network::mojom::ResolveHostClient> response_client( std::move(pending_response_client)); - const std::string host = host_port_pair.host(); + std::string host = host_port_pair.host(); + auto iter = known_hosts().find(host); + if (iter != known_hosts().end()) + host = iter->second; + net::IPAddress remote_address; // TODO(crbug.com/1141241): Replace if/else with AssignFromIPLiteral. if (host.find(':') != std::string::npos) { @@ -129,19 +142,20 @@ mojo::PendingReceiver<network::mojom::TCPConnectedSocket> socket, mojo::PendingRemote<network::mojom::SocketObserver> observer, CreateTCPConnectedSocketCallback callback) override { - history_.push_back(RecordedCall{ - DirectSocketsServiceImpl::ProtocolType::kTcp, - remote_addr_list[0].address().ToString(), remote_addr_list[0].port(), - tcp_connected_socket_options->send_buffer_size, - tcp_connected_socket_options->receive_buffer_size, - tcp_connected_socket_options->no_delay}); + const net::IPEndPoint& peer_addr = remote_addr_list.front(); + history_.push_back( + RecordedCall{DirectSocketsServiceImpl::ProtocolType::kTcp, + peer_addr.address().ToString(), peer_addr.port(), + tcp_connected_socket_options->send_buffer_size, + tcp_connected_socket_options->receive_buffer_size, + tcp_connected_socket_options->no_delay}); mojo::ScopedDataPipeProducerHandle producer; mojo::ScopedDataPipeConsumerHandle consumer; DCHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &producer, &consumer)); - std::move(callback).Run(result_, base::nullopt, base::nullopt, - std::move(consumer), std::move(producer)); + std::move(callback).Run(result_, local_addr, peer_addr, std::move(consumer), + std::move(producer)); } void CreateHostResolver( @@ -232,7 +246,8 @@ const std::string script = base::StringPrintf( "openTcp({remoteAddress: '127.0.0.1', remotePort: %d})", listening_port); - EXPECT_EQ("openTcp succeeded", EvalJs(shell(), script)); + EXPECT_THAT(EvalJs(shell(), script).ExtractString(), + StartsWith("openTcp succeeded")); } IN_PROC_BROWSER_TEST_F(DirectSocketsBrowserTest, OpenTcp_Success_Global) { @@ -242,7 +257,27 @@ const std::string script = base::StringPrintf( "openTcp({remoteAddress: '127.0.0.1', remotePort: %d})", listening_port); - EXPECT_EQ("openTcp succeeded", EvalJs(shell(), script)); + EXPECT_THAT(EvalJs(shell(), script).ExtractString(), + StartsWith("openTcp succeeded")); +} + +IN_PROC_BROWSER_TEST_F(DirectSocketsBrowserTest, OpenTcp_Success_Hostname) { + EXPECT_TRUE(NavigateToURL(shell(), GetTestPageURL())); + + const char kExampleHostname[] = "mail.example.com"; + const char kExampleAddress[] = "98.76.54.32"; + MockHostResolver::known_hosts()[kExampleHostname] = kExampleAddress; + + MockNetworkContext mock_network_context(net::OK); + DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context); + const std::string expected_result = base::StringPrintf( + "openTcp succeeded: {remoteAddress: \"%s\", remotePort: 993}", + kExampleAddress); + + const std::string script = base::StringPrintf( + "openTcp({remoteAddress: '%s', remotePort: 993})", kExampleHostname); + + EXPECT_EQ(expected_result, EvalJs(shell(), script)); } IN_PROC_BROWSER_TEST_F(DirectSocketsBrowserTest, OpenTcp_CannotEvadeCors) { @@ -297,7 +332,6 @@ MockNetworkContext mock_network_context(net::OK); DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context); - const std::string expected_result = "openTcp succeeded"; const std::string script = R"( @@ -309,7 +343,8 @@ noDelay: true }) )"; - EXPECT_EQ(expected_result, EvalJs(shell(), script)); + EXPECT_THAT(EvalJs(shell(), script).ExtractString(), + StartsWith("openTcp succeeded")); DCHECK_EQ(1U, mock_network_context.history().size()); const RecordedCall& call = mock_network_context.history()[0];
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.cc b/content/browser/direct_sockets/direct_sockets_service_impl.cc index 1189362a3..ae746b2 100644 --- a/content/browser/direct_sockets/direct_sockets_service_impl.cc +++ b/content/browser/direct_sockets/direct_sockets_service_impl.cc
@@ -37,17 +37,19 @@ return network_context; } -// Populate |local_addr| from options. -void PopulateLocalAddr(const blink::mojom::DirectSocketOptions& options, - base::Optional<net::IPEndPoint>& local_addr) { - DCHECK(!local_addr); +// Get local ip address from options. +base::Optional<net::IPEndPoint> GetLocalAddr( + const blink::mojom::DirectSocketOptions& options) { + base::Optional<net::IPEndPoint> local_addr = base::nullopt; if (!options.local_hostname) - return; + return local_addr; net::IPAddress local_address; bool success = local_address.AssignFromIPLiteral(*options.local_hostname); if (success) local_addr = net::IPEndPoint(local_address, options.local_port); + + return local_addr; } } // namespace @@ -142,8 +144,7 @@ } DCHECK(resolved_addresses && !resolved_addresses->empty()); - base::Optional<net::IPEndPoint> local_addr = base::nullopt; - PopulateLocalAddr(*options_, local_addr); + const base::Optional<net::IPEndPoint> local_addr = GetLocalAddr(*options_); network::mojom::TCPConnectedSocketOptionsPtr tcp_connected_socket_options = network::mojom::TCPConnectedSocketOptions::New(); @@ -180,8 +181,7 @@ } DCHECK(resolved_addresses && !resolved_addresses->empty()); - base::Optional<net::IPEndPoint> local_addr = base::nullopt; - PopulateLocalAddr(*options_, local_addr); + base::Optional<net::IPEndPoint> local_addr = GetLocalAddr(*options_); // TODO(crbug.com/1119620): network_context_->CreateUDPSocket // TODO(crbug.com/1119620): Connect(remote_addr, udp_socket_options) @@ -274,10 +274,10 @@ } // static -void DirectSocketsServiceImpl::PopulateLocalAddrForTesting( - const blink::mojom::DirectSocketOptions& options, - base::Optional<net::IPEndPoint>& local_addr) { - PopulateLocalAddr(options, local_addr); +base::Optional<net::IPEndPoint> +DirectSocketsServiceImpl::GetLocalAddrForTesting( + const blink::mojom::DirectSocketOptions& options) { + return GetLocalAddr(options); } void DirectSocketsServiceImpl::RenderFrameDeleted(
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.h b/content/browser/direct_sockets/direct_sockets_service_impl.h index cbc26fa..4ecbd53c 100644 --- a/content/browser/direct_sockets/direct_sockets_service_impl.h +++ b/content/browser/direct_sockets/direct_sockets_service_impl.h
@@ -65,9 +65,8 @@ static void SetNetworkContextForTesting(network::mojom::NetworkContext*); - static void PopulateLocalAddrForTesting( - const blink::mojom::DirectSocketOptions& options, - base::Optional<net::IPEndPoint>& local_addr); + static base::Optional<net::IPEndPoint> GetLocalAddrForTesting( + const blink::mojom::DirectSocketOptions& options); private: friend class DirectSocketsUnitTest;
diff --git a/content/browser/direct_sockets/direct_sockets_unittest.cc b/content/browser/direct_sockets/direct_sockets_unittest.cc index 7dadef71..f6b87c2 100644 --- a/content/browser/direct_sockets/direct_sockets_unittest.cc +++ b/content/browser/direct_sockets/direct_sockets_unittest.cc
@@ -35,9 +35,9 @@ return direct_sockets_service().ValidateOptions(options); } - void PopulateLocalAddr(const blink::mojom::DirectSocketOptions& options, - base::Optional<net::IPEndPoint>& local_addr) { - DirectSocketsServiceImpl::PopulateLocalAddrForTesting(options, local_addr); + base::Optional<net::IPEndPoint> GetLocalAddr( + const blink::mojom::DirectSocketOptions& options) { + return DirectSocketsServiceImpl::GetLocalAddrForTesting(options); } private: @@ -69,30 +69,26 @@ blink::mojom::DirectSocketOptions options; // Test for default condition. - base::Optional<net::IPEndPoint> local_addr = base::nullopt; - PopulateLocalAddr(options, local_addr); + base::Optional<net::IPEndPoint> local_addr = GetLocalAddr(options); EXPECT_EQ(local_addr, base::nullopt); // Test with IPv4 address and default port(0) provided. - local_addr = base::nullopt; options.local_hostname = "12.34.56.78"; - PopulateLocalAddr(options, local_addr); + local_addr = GetLocalAddr(options); const uint8_t ipv4[net::IPAddress::kIPv4AddressSize] = {12, 34, 56, 78}; EXPECT_EQ(local_addr, net::IPEndPoint(net::IPAddress(ipv4), 0)); // Test with IPv6 address and default port(0) provided. - local_addr = base::nullopt; options.local_hostname = "fedc:ba98:7654:3210:fedc:ba98:7654:3210"; - PopulateLocalAddr(options, local_addr); + local_addr = GetLocalAddr(options); const uint8_t ipv6[net::IPAddress::kIPv6AddressSize] = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; EXPECT_EQ(local_addr, net::IPEndPoint(net::IPAddress(ipv6), 0)); // Test with IPv6 address and port(12345) provided. - local_addr = base::nullopt; options.local_port = 12345; - PopulateLocalAddr(options, local_addr); + local_addr = GetLocalAddr(options); EXPECT_EQ(local_addr, net::IPEndPoint(net::IPAddress(ipv6), 12345)); }
diff --git a/content/browser/file_system_access/file_system_chooser.cc b/content/browser/file_system_access/file_system_chooser.cc index 9cd45aa4..ad25cdb 100644 --- a/content/browser/file_system_access/file_system_chooser.cc +++ b/content/browser/file_system_access/file_system_chooser.cc
@@ -314,7 +314,7 @@ RecordFileSelectionResult(type_, 0); std::move(callback_).Run( native_file_system_error::FromStatus( - blink::mojom::NativeFileSystemStatus::kOperationAborted), + blink::mojom::FileSystemAccessStatus::kOperationAborted), {}); delete this; }
diff --git a/content/browser/file_system_access/file_system_chooser.h b/content/browser/file_system_access/file_system_chooser.h index f115772..4084fa7 100644 --- a/content/browser/file_system_access/file_system_chooser.h +++ b/content/browser/file_system_access/file_system_chooser.h
@@ -12,7 +12,7 @@ #include "content/common/content_export.h" #include "content/public/browser/native_file_system_entry_factory.h" #include "storage/browser/file_system/isolated_context.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom.h" #include "ui/shell_dialogs/select_file_dialog.h" namespace content { @@ -33,7 +33,7 @@ }; using ResultCallback = - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, std::vector<ResultEntry>)>; class CONTENT_EXPORT Options {
diff --git a/content/browser/file_system_access/file_system_chooser_browsertest.cc b/content/browser/file_system_access/file_system_chooser_browsertest.cc index 4f7bee57..3f7de9d 100644 --- a/content/browser/file_system_access/file_system_chooser_browsertest.cc +++ b/content/browser/file_system_access/file_system_chooser_browsertest.cc
@@ -25,7 +25,7 @@ #include "content/shell/browser/shell.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "storage/browser/file_system/external_mount_points.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-shared.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-shared.h" #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" #include "ui/shell_dialogs/select_file_dialog.h" #include "ui/shell_dialogs/select_file_dialog_factory.h"
diff --git a/content/browser/file_system_access/file_system_chooser_unittest.cc b/content/browser/file_system_access/file_system_chooser_unittest.cc index e74737b..88116624 100644 --- a/content/browser/file_system_access/file_system_chooser_unittest.cc +++ b/content/browser/file_system_access/file_system_chooser_unittest.cc
@@ -35,7 +35,7 @@ blink::mojom::ChooseFileSystemEntryType::kOpenFile, std::move(accepts), include_accepts_all, base::FilePath()), base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr, + [&](blink::mojom::FileSystemAccessErrorPtr, std::vector<FileSystemChooser::ResultEntry> entries) { result = std::move(entries); loop.Quit();
diff --git a/content/browser/file_system_access/native_file_system_directory_handle_impl.cc b/content/browser/file_system_access/native_file_system_directory_handle_impl.cc index 80f184b..8995324 100644 --- a/content/browser/file_system_access/native_file_system_directory_handle_impl.cc +++ b/content/browser/file_system_access/native_file_system_directory_handle_impl.cc
@@ -17,15 +17,15 @@ #include "storage/browser/file_system/file_system_context.h" #include "storage/browser/file_system/file_system_operation_runner.h" #include "storage/common/file_system/file_system_util.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom.h" -using blink::mojom::NativeFileSystemEntry; -using blink::mojom::NativeFileSystemEntryPtr; -using blink::mojom::NativeFileSystemHandle; -using blink::mojom::NativeFileSystemStatus; -using blink::mojom::NativeFileSystemTransferToken; +using blink::mojom::FileSystemAccessEntry; +using blink::mojom::FileSystemAccessEntryPtr; +using blink::mojom::FileSystemAccessHandle; +using blink::mojom::FileSystemAccessStatus; +using blink::mojom::FileSystemAccessTransferToken; using storage::FileSystemOperationRunner; namespace content { @@ -60,9 +60,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); storage::FileSystemURL child_url; - blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + blink::mojom::FileSystemAccessErrorPtr get_child_url_result = GetChildURL(basename, &child_url); - if (get_child_url_result->status != NativeFileSystemStatus::kOk) { + if (get_child_url_result->status != FileSystemAccessStatus::kOk) { std::move(callback).Run(std::move(get_child_url_result), mojo::NullRemote()); return; @@ -70,7 +70,7 @@ if (GetReadPermissionStatus() != PermissionStatus::GRANTED) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied), + FileSystemAccessStatus::kPermissionDenied), mojo::NullRemote()); return; } @@ -83,7 +83,7 @@ base::BindOnce( &NativeFileSystemDirectoryHandleImpl::GetFileWithWritePermission, weak_factory_.GetWeakPtr(), child_url), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, GetFileCallback callback) { std::move(callback).Run(std::move(result), mojo::NullRemote()); }), @@ -105,9 +105,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); storage::FileSystemURL child_url; - blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + blink::mojom::FileSystemAccessErrorPtr get_child_url_result = GetChildURL(basename, &child_url); - if (get_child_url_result->status != NativeFileSystemStatus::kOk) { + if (get_child_url_result->status != FileSystemAccessStatus::kOk) { std::move(callback).Run(std::move(get_child_url_result), mojo::NullRemote()); return; @@ -115,7 +115,7 @@ if (GetReadPermissionStatus() != PermissionStatus::GRANTED) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied), + FileSystemAccessStatus::kPermissionDenied), mojo::NullRemote()); return; } @@ -128,7 +128,7 @@ base::BindOnce(&NativeFileSystemDirectoryHandleImpl:: GetDirectoryWithWritePermission, weak_factory_.GetWeakPtr(), child_url), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, GetDirectoryCallback callback) { std::move(callback).Run(std::move(result), mojo::NullRemote()); }), @@ -144,16 +144,16 @@ } void NativeFileSystemDirectoryHandleImpl::GetEntries( - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryEntriesListener> + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryEntriesListener> pending_listener) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::unique_ptr< - mojo::Remote<blink::mojom::NativeFileSystemDirectoryEntriesListener>, + mojo::Remote<blink::mojom::FileSystemAccessDirectoryEntriesListener>, base::OnTaskRunnerDeleter> listener( new mojo::Remote< - blink::mojom::NativeFileSystemDirectoryEntriesListener>( + blink::mojom::FileSystemAccessDirectoryEntriesListener>( std::move(pending_listener)), base::OnTaskRunnerDeleter(base::SequencedTaskRunnerHandle::Get())); listener->reset_on_disconnect(); @@ -161,7 +161,7 @@ if (GetReadPermissionStatus() != PermissionStatus::GRANTED) { (*listener)->DidReadDirectory( native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied), + FileSystemAccessStatus::kPermissionDenied), {}, false); return; } @@ -181,9 +181,9 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); storage::FileSystemURL child_url; - blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + blink::mojom::FileSystemAccessErrorPtr get_child_url_result = GetChildURL(basename, &child_url); - if (get_child_url_result->status != NativeFileSystemStatus::kOk) { + if (get_child_url_result->status != FileSystemAccessStatus::kOk) { std::move(callback).Run(std::move(get_child_url_result)); return; } @@ -191,14 +191,14 @@ RunWithWritePermission( base::BindOnce(&NativeFileSystemDirectoryHandleImpl::RemoveEntryImpl, weak_factory_.GetWeakPtr(), child_url, recurse), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, RemoveEntryCallback callback) { std::move(callback).Run(std::move(result)); }), std::move(callback)); } void NativeFileSystemDirectoryHandleImpl::Resolve( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> possible_child, ResolveCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -215,7 +215,7 @@ if (!possible_child) { std::move(callback).Run( native_file_system_error::FromStatus( - blink::mojom::NativeFileSystemStatus::kOperationFailed), + blink::mojom::FileSystemAccessStatus::kOperationFailed), base::nullopt); return; } @@ -270,7 +270,7 @@ } void NativeFileSystemDirectoryHandleImpl::Transfer( - mojo::PendingReceiver<NativeFileSystemTransferToken> token) { + mojo::PendingReceiver<FileSystemAccessTransferToken> token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); manager()->CreateTransferToken(*this, std::move(token)); @@ -343,7 +343,7 @@ } void NativeFileSystemDirectoryHandleImpl::DidReadDirectory( - mojo::Remote<blink::mojom::NativeFileSystemDirectoryEntriesListener>* + mojo::Remote<blink::mojom::FileSystemAccessDirectoryEntriesListener>* listener, base::File::Error result, std::vector<filesystem::mojom::DirectoryEntry> file_list, @@ -360,17 +360,17 @@ return; } - std::vector<NativeFileSystemEntryPtr> entries; + std::vector<FileSystemAccessEntryPtr> entries; for (const auto& entry : file_list) { std::string basename = storage::FilePathToString(entry.name); storage::FileSystemURL child_url; - blink::mojom::NativeFileSystemErrorPtr get_child_url_result = + blink::mojom::FileSystemAccessErrorPtr get_child_url_result = GetChildURL(basename, &child_url); // Skip any entries with names that aren't allowed to be accessed by // this API, such as files with disallowed characters in their names. - if (get_child_url_result->status != NativeFileSystemStatus::kOk) + if (get_child_url_result->status != FileSystemAccessStatus::kOk) continue; entries.push_back( @@ -486,13 +486,13 @@ return true; } -blink::mojom::NativeFileSystemErrorPtr +blink::mojom::FileSystemAccessErrorPtr NativeFileSystemDirectoryHandleImpl::GetChildURL( const std::string& basename, storage::FileSystemURL* result) { if (!IsSafePathComponent(basename)) { return native_file_system_error::FromStatus( - NativeFileSystemStatus::kInvalidArgument, "Name is not allowed."); + FileSystemAccessStatus::kInvalidArgument, "Name is not allowed."); } const storage::FileSystemURL parent = url(); @@ -502,18 +502,18 @@ return native_file_system_error::Ok(); } -NativeFileSystemEntryPtr NativeFileSystemDirectoryHandleImpl::CreateEntry( +FileSystemAccessEntryPtr NativeFileSystemDirectoryHandleImpl::CreateEntry( const std::string& basename, const storage::FileSystemURL& url, HandleType handle_type) { if (handle_type == HandleType::kDirectory) { - return NativeFileSystemEntry::New( - NativeFileSystemHandle::NewDirectory( + return FileSystemAccessEntry::New( + FileSystemAccessHandle::NewDirectory( manager()->CreateDirectoryHandle(context(), url, handle_state())), basename); } - return NativeFileSystemEntry::New( - NativeFileSystemHandle::NewFile( + return FileSystemAccessEntry::New( + FileSystemAccessHandle::NewFile( manager()->CreateFileHandle(context(), url, handle_state())), basename); }
diff --git a/content/browser/file_system_access/native_file_system_directory_handle_impl.h b/content/browser/file_system_access/native_file_system_directory_handle_impl.h index 537b2a6..4770fd6 100644 --- a/content/browser/file_system_access/native_file_system_directory_handle_impl.h +++ b/content/browser/file_system_access/native_file_system_directory_handle_impl.h
@@ -13,7 +13,7 @@ #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "storage/browser/file_system/file_system_url.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom.h" namespace content { // This is the browser side implementation of the @@ -25,7 +25,7 @@ // sequence. class CONTENT_EXPORT NativeFileSystemDirectoryHandleImpl : public NativeFileSystemHandleBase, - public blink::mojom::NativeFileSystemDirectoryHandle { + public blink::mojom::FileSystemAccessDirectoryHandle { public: NativeFileSystemDirectoryHandleImpl(NativeFileSystemManagerImpl* manager, const BindingContext& context, @@ -33,7 +33,7 @@ const SharedHandleState& handle_state); ~NativeFileSystemDirectoryHandleImpl() override; - // blink::mojom::NativeFileSystemDirectoryHandle: + // blink::mojom::FileSystemAccessDirectoryHandle: void GetPermissionStatus(bool writable, GetPermissionStatusCallback callback) override; void RequestPermission(bool writable, @@ -45,16 +45,16 @@ bool create, GetDirectoryCallback callback) override; void GetEntries(mojo::PendingRemote< - blink::mojom::NativeFileSystemDirectoryEntriesListener> + blink::mojom::FileSystemAccessDirectoryEntriesListener> pending_listener) override; void RemoveEntry(const std::string& basename, bool recurse, RemoveEntryCallback callback) override; - void Resolve(mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> + void Resolve(mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> possible_child, ResolveCallback callback) override; void Transfer( - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> token) + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token) override; // The File System Access API should not give access to files that might @@ -81,7 +81,7 @@ GetDirectoryCallback callback, base::File::Error result); void DidReadDirectory( - mojo::Remote<blink::mojom::NativeFileSystemDirectoryEntriesListener>* + mojo::Remote<blink::mojom::FileSystemAccessDirectoryEntriesListener>* listener, base::File::Error result, std::vector<filesystem::mojom::DirectoryEntry> file_list, @@ -97,12 +97,12 @@ // Calculates a FileSystemURL for a (direct) child of this directory with the // given basename. Returns an error when |basename| includes invalid input // like "/". - blink::mojom::NativeFileSystemErrorPtr GetChildURL( + blink::mojom::FileSystemAccessErrorPtr GetChildURL( const std::string& basename, storage::FileSystemURL* result) WARN_UNUSED_RESULT; - // Helper to create a blink::mojom::NativeFileSystemEntry struct. - blink::mojom::NativeFileSystemEntryPtr CreateEntry( + // Helper to create a blink::mojom::FileSystemAccessEntry struct. + blink::mojom::FileSystemAccessEntryPtr CreateEntry( const std::string& basename, const storage::FileSystemURL& url, NativeFileSystemPermissionContext::HandleType handle_type);
diff --git a/content/browser/file_system_access/native_file_system_directory_handle_impl_unittest.cc b/content/browser/file_system_access/native_file_system_directory_handle_impl_unittest.cc index a3ba2409..d1cb4f8 100644 --- a/content/browser/file_system_access/native_file_system_directory_handle_impl_unittest.cc +++ b/content/browser/file_system_access/native_file_system_directory_handle_impl_unittest.cc
@@ -137,24 +137,24 @@ namespace { class TestNativeFileSystemDirectoryEntriesListener - : public blink::mojom::NativeFileSystemDirectoryEntriesListener { + : public blink::mojom::FileSystemAccessDirectoryEntriesListener { public: TestNativeFileSystemDirectoryEntriesListener( - std::vector<blink::mojom::NativeFileSystemEntryPtr>* entries, - blink::mojom::NativeFileSystemErrorPtr* final_result, + std::vector<blink::mojom::FileSystemAccessEntryPtr>* entries, + blink::mojom::FileSystemAccessErrorPtr* final_result, base::OnceClosure done) : entries_(entries), final_result_(final_result), done_(std::move(done)) {} void DidReadDirectory( - blink::mojom::NativeFileSystemErrorPtr result, - std::vector<blink::mojom::NativeFileSystemEntryPtr> entries, + blink::mojom::FileSystemAccessErrorPtr result, + std::vector<blink::mojom::FileSystemAccessEntryPtr> entries, bool has_more_entries) override { entries_->insert(entries_->end(), std::make_move_iterator(entries.begin()), std::make_move_iterator(entries.end())); if (has_more_entries) { - EXPECT_EQ(result->status, blink::mojom::NativeFileSystemStatus::kOk); + EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); } else { *final_result_ = std::move(result); std::move(done_).Run(); @@ -162,8 +162,8 @@ } private: - std::vector<blink::mojom::NativeFileSystemEntryPtr>* entries_; - blink::mojom::NativeFileSystemErrorPtr* final_result_; + std::vector<blink::mojom::FileSystemAccessEntryPtr>* entries_; + blink::mojom::FileSystemAccessErrorPtr* final_result_; base::OnceClosure done_; }; } // namespace @@ -192,10 +192,10 @@ #endif } - std::vector<blink::mojom::NativeFileSystemEntryPtr> entries; - blink::mojom::NativeFileSystemErrorPtr result; + std::vector<blink::mojom::FileSystemAccessEntryPtr> entries; + blink::mojom::FileSystemAccessErrorPtr result; base::RunLoop loop; - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryEntriesListener> + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryEntriesListener> listener; mojo::MakeSelfOwnedReceiver( std::make_unique<TestNativeFileSystemDirectoryEntriesListener>( @@ -204,7 +204,7 @@ handle_->GetEntries(std::move(listener)); loop.Run(); - EXPECT_EQ(result->status, blink::mojom::NativeFileSystemStatus::kOk); + EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); std::vector<std::string> names; for (const auto& entry : entries) { names.push_back(entry->name); @@ -219,11 +219,11 @@ denied_handle_->GetFile( "filename", /*create=*/false, base::BindLambdaForTesting( - [](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle> + [](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessFileHandle> file_handle) { EXPECT_EQ(result->status, - blink::mojom::NativeFileSystemStatus::kPermissionDenied); + blink::mojom::FileSystemAccessStatus::kPermissionDenied); EXPECT_FALSE(file_handle.is_valid()); }) .Then(loop.QuitClosure())); @@ -237,11 +237,11 @@ denied_handle_->GetDirectory( "GetDirectory_NoReadAccess", /*create=*/false, base::BindLambdaForTesting( - [](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> + [](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> dir_handle) { EXPECT_EQ(result->status, - blink::mojom::NativeFileSystemStatus::kPermissionDenied); + blink::mojom::FileSystemAccessStatus::kPermissionDenied); EXPECT_FALSE(dir_handle.is_valid()); }) .Then(loop.QuitClosure())); @@ -251,10 +251,10 @@ TEST_F(NativeFileSystemDirectoryHandleImplTest, GetEntries_NoReadAccess) { ASSERT_TRUE(base::WriteFile(dir_.GetPath().AppendASCII("filename"), "data")); - std::vector<blink::mojom::NativeFileSystemEntryPtr> entries; - blink::mojom::NativeFileSystemErrorPtr result; + std::vector<blink::mojom::FileSystemAccessEntryPtr> entries; + blink::mojom::FileSystemAccessErrorPtr result; base::RunLoop loop; - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryEntriesListener> + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryEntriesListener> listener; mojo::MakeSelfOwnedReceiver( std::make_unique<TestNativeFileSystemDirectoryEntriesListener>( @@ -264,7 +264,7 @@ loop.Run(); EXPECT_EQ(result->status, - blink::mojom::NativeFileSystemStatus::kPermissionDenied); + blink::mojom::FileSystemAccessStatus::kPermissionDenied); EXPECT_TRUE(entries.empty()); }
diff --git a/content/browser/file_system_access/native_file_system_drag_drop_token_impl.cc b/content/browser/file_system_access/native_file_system_drag_drop_token_impl.cc index f6167ff..26107f6 100644 --- a/content/browser/file_system_access/native_file_system_drag_drop_token_impl.cc +++ b/content/browser/file_system_access/native_file_system_drag_drop_token_impl.cc
@@ -9,7 +9,7 @@ #include "base/files/file_path.h" #include "base/unguessable_token.h" #include "mojo/public/cpp/bindings/pending_receiver.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom.h" namespace content { @@ -18,7 +18,7 @@ NativeFileSystemManagerImpl::PathType path_type, const base::FilePath& file_path, int renderer_process_id, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> receiver) + mojo::PendingReceiver<blink::mojom::FileSystemAccessDragDropToken> receiver) : manager_(manager), path_type_(path_type), file_path_(file_path), @@ -42,7 +42,7 @@ } void NativeFileSystemDragDropTokenImpl::Clone( - mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessDragDropToken> clone_receiver) { receivers_.Add(this, std::move(clone_receiver)); }
diff --git a/content/browser/file_system_access/native_file_system_drag_drop_token_impl.h b/content/browser/file_system_access/native_file_system_drag_drop_token_impl.h index c8a2b258..9b256b3d 100644 --- a/content/browser/file_system_access/native_file_system_drag_drop_token_impl.h +++ b/content/browser/file_system_access/native_file_system_drag_drop_token_impl.h
@@ -11,7 +11,7 @@ #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom.h" namespace content { @@ -20,16 +20,16 @@ // and dropped file/directory in the browser process. The associated // mojo::PendingRemote<NativeFileSystemDragDropToken>s are passed to the // renderer process specified by `renderer_process_id` and can then be redeemed -// for NativeFileSystemEntry objects. +// for FileSystemAccessEntry objects. class CONTENT_EXPORT NativeFileSystemDragDropTokenImpl - : public blink::mojom::NativeFileSystemDragDropToken { + : public blink::mojom::FileSystemAccessDragDropToken { public: NativeFileSystemDragDropTokenImpl( NativeFileSystemManagerImpl* manager, NativeFileSystemManagerImpl::PathType path_type, const base::FilePath& file_path, int renderer_process_id, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessDragDropToken> receiver); ~NativeFileSystemDragDropTokenImpl() override; @@ -48,10 +48,10 @@ const base::UnguessableToken& token() const { return token_; } - // blink::mojom::NativeFileSystemDragDropToken: + // blink::mojom::FileSystemAccessDragDropToken: void GetInternalId(GetInternalIdCallback callback) override; - void Clone(mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> + void Clone(mojo::PendingReceiver<blink::mojom::FileSystemAccessDragDropToken> receiver) override; private: @@ -68,7 +68,7 @@ // the originally constructed instance and then additional receivers for // each clone. `manager_` must not remove this token until `receivers_` is // empty. - mojo::ReceiverSet<blink::mojom::NativeFileSystemDragDropToken> receivers_; + mojo::ReceiverSet<blink::mojom::FileSystemAccessDragDropToken> receivers_; }; } // namespace content
diff --git a/content/browser/file_system_access/native_file_system_error.cc b/content/browser/file_system_access/native_file_system_error.cc index 5fc9e4a..d87eb39 100644 --- a/content/browser/file_system_access/native_file_system_error.cc +++ b/content/browser/file_system_access/native_file_system_error.cc
@@ -6,29 +6,29 @@ namespace content { -using blink::mojom::NativeFileSystemError; -using blink::mojom::NativeFileSystemErrorPtr; -using blink::mojom::NativeFileSystemStatus; +using blink::mojom::FileSystemAccessError; +using blink::mojom::FileSystemAccessErrorPtr; +using blink::mojom::FileSystemAccessStatus; namespace native_file_system_error { -NativeFileSystemErrorPtr Ok() { - return NativeFileSystemError::New(NativeFileSystemStatus::kOk, +FileSystemAccessErrorPtr Ok() { + return FileSystemAccessError::New(FileSystemAccessStatus::kOk, base::File::FILE_OK, ""); } -NativeFileSystemErrorPtr FromFileError(base::File::Error result, +FileSystemAccessErrorPtr FromFileError(base::File::Error result, base::StringPiece message) { if (result == base::File::FILE_OK) return Ok(); - return NativeFileSystemError::New(NativeFileSystemStatus::kFileError, result, + return FileSystemAccessError::New(FileSystemAccessStatus::kFileError, result, std::string(message)); } -blink::mojom::NativeFileSystemErrorPtr FromStatus( - blink::mojom::NativeFileSystemStatus status, +blink::mojom::FileSystemAccessErrorPtr FromStatus( + blink::mojom::FileSystemAccessStatus status, base::StringPiece message) { - return NativeFileSystemError::New(status, base::File::FILE_OK, + return FileSystemAccessError::New(status, base::File::FILE_OK, std::string(message)); }
diff --git a/content/browser/file_system_access/native_file_system_error.h b/content/browser/file_system_access/native_file_system_error.h index d162bda..7298470 100644 --- a/content/browser/file_system_access/native_file_system_error.h +++ b/content/browser/file_system_access/native_file_system_error.h
@@ -9,25 +9,25 @@ #include "base/files/file.h" #include "base/strings/string_piece.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h" namespace content { namespace native_file_system_error { -// Returns a NativeFileSystemError representing a successful result of an +// Returns a FileSystemAccessError representing a successful result of an // operation. -blink::mojom::NativeFileSystemErrorPtr Ok(); +blink::mojom::FileSystemAccessErrorPtr Ok(); -// Wraps a base::File::Error in a NativeFileSystemError, optionally with a +// Wraps a base::File::Error in a FileSystemAccessError, optionally with a // custom error message. -blink::mojom::NativeFileSystemErrorPtr FromFileError( +blink::mojom::FileSystemAccessErrorPtr FromFileError( base::File::Error result, base::StringPiece message = ""); -// Wraps a NativeFileSystemStatus in a NativeFileSystemError, optionally with a +// Wraps a FileSystemAccessStatus in a FileSystemAccessError, optionally with a // custom error message. -blink::mojom::NativeFileSystemErrorPtr FromStatus( - blink::mojom::NativeFileSystemStatus status, +blink::mojom::FileSystemAccessErrorPtr FromStatus( + blink::mojom::FileSystemAccessStatus status, base::StringPiece message = ""); } // namespace native_file_system_error
diff --git a/content/browser/file_system_access/native_file_system_file_handle_impl.cc b/content/browser/file_system_access/native_file_system_file_handle_impl.cc index 94c8e0c..4ebbd98 100644 --- a/content/browser/file_system_access/native_file_system_file_handle_impl.cc +++ b/content/browser/file_system_access/native_file_system_file_handle_impl.cc
@@ -19,10 +19,10 @@ #include "storage/browser/file_system/file_system_operation_runner.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom.h" -using blink::mojom::NativeFileSystemStatus; +using blink::mojom::FileSystemAccessStatus; using storage::BlobDataHandle; using storage::BlobImpl; using storage::FileSystemOperation; @@ -57,7 +57,7 @@ if (GetReadPermissionStatus() != PermissionStatus::GRANTED) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied), + FileSystemAccessStatus::kPermissionDenied), base::File::Info(), nullptr); return; } @@ -84,7 +84,7 @@ base::BindOnce(&NativeFileSystemFileHandleImpl::CreateFileWriterImpl, weak_factory_.GetWeakPtr(), keep_existing_data, auto_close), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, CreateFileWriterCallback callback) { std::move(callback).Run(std::move(result), mojo::NullRemote()); }), @@ -92,7 +92,7 @@ } void NativeFileSystemFileHandleImpl::IsSameEntry( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, IsSameEntryCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -108,7 +108,7 @@ if (!other) { std::move(callback).Run( native_file_system_error::FromStatus( - blink::mojom::NativeFileSystemStatus::kOperationFailed), + blink::mojom::FileSystemAccessStatus::kOperationFailed), false); return; } @@ -134,7 +134,7 @@ } void NativeFileSystemFileHandleImpl::Transfer( - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> token) { + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); manager()->CreateTransferToken(*this, std::move(token)); @@ -250,7 +250,7 @@ if (GetWritePermissionStatus() != blink::mojom::PermissionStatus::GRANTED) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied), + FileSystemAccessStatus::kPermissionDenied), mojo::NullRemote()); return; } @@ -264,7 +264,7 @@ << " exceeds max unique files of: " << max_swap_files_ << " base path: " << swap_path; std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationFailed, + FileSystemAccessStatus::kOperationFailed, "Failed to create swap file."), mojo::NullRemote()); return;
diff --git a/content/browser/file_system_access/native_file_system_file_handle_impl.h b/content/browser/file_system_access/native_file_system_file_handle_impl.h index e7f5471..afb308cc 100644 --- a/content/browser/file_system_access/native_file_system_file_handle_impl.h +++ b/content/browser/file_system_access/native_file_system_file_handle_impl.h
@@ -12,7 +12,7 @@ #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "storage/browser/file_system/file_system_url.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom.h" namespace content { @@ -25,7 +25,7 @@ // sequence. class CONTENT_EXPORT NativeFileSystemFileHandleImpl : public NativeFileSystemHandleBase, - public blink::mojom::NativeFileSystemFileHandle { + public blink::mojom::FileSystemAccessFileHandle { public: NativeFileSystemFileHandleImpl(NativeFileSystemManagerImpl* manager, const BindingContext& context, @@ -33,7 +33,7 @@ const SharedHandleState& handle_state); ~NativeFileSystemFileHandleImpl() override; - // blink::mojom::NativeFileSystemFileHandle: + // blink::mojom::FileSystemAccessFileHandle: void GetPermissionStatus(bool writable, GetPermissionStatusCallback callback) override; void RequestPermission(bool writable, @@ -43,10 +43,10 @@ bool auto_close, CreateFileWriterCallback callback) override; void IsSameEntry( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, IsSameEntryCallback callback) override; void Transfer( - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> token) + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token) override; void set_max_swap_files_for_testing(int max) { max_swap_files_ = max; }
diff --git a/content/browser/file_system_access/native_file_system_file_handle_impl_unittest.cc b/content/browser/file_system_access/native_file_system_file_handle_impl_unittest.cc index e94f4c6..acdc853 100644 --- a/content/browser/file_system_access/native_file_system_file_handle_impl_unittest.cc +++ b/content/browser/file_system_access/native_file_system_file_handle_impl_unittest.cc
@@ -121,7 +121,7 @@ test_src_origin_, storage::kFileSystemTypeTest, base::FilePath::FromUTF8Unsafe("test.crswap")); - std::vector<mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter>> + std::vector<mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> writers; for (int i = 0; i < max_files; i++) { FileSystemURL swap_url; @@ -139,10 +139,10 @@ /*keep_existing_data=*/false, /*auto_close=*/false, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> + [&](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote) { - EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, + EXPECT_EQ(blink::mojom::FileSystemAccessStatus::kOk, result->status); EXPECT_EQ("", ReadFile(swap_url)); writers.push_back(std::move(writer_remote)); @@ -156,10 +156,10 @@ /*keep_existing_data=*/false, /*auto_close=*/false, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> + [&](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote) { - EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOperationFailed, + EXPECT_EQ(blink::mojom::FileSystemAccessStatus::kOperationFailed, result->status); loop.Quit(); }));
diff --git a/content/browser/file_system_access/native_file_system_file_writer_impl.cc b/content/browser/file_system_access/native_file_system_file_writer_impl.cc index daedaa6..dc12072 100644 --- a/content/browser/file_system_access/native_file_system_file_writer_impl.cc +++ b/content/browser/file_system_access/native_file_system_file_writer_impl.cc
@@ -23,9 +23,9 @@ #include "storage/browser/file_system/file_system_operation_runner.h" #include "third_party/blink/public/common/blob/blob_utils.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h" -using blink::mojom::NativeFileSystemStatus; +using blink::mojom::FileSystemAccessStatus; using storage::BlobDataHandle; using storage::FileSystemOperation; using storage::FileSystemOperationRunner; @@ -143,7 +143,7 @@ const storage::FileSystemURL& url, const storage::FileSystemURL& swap_url, const SharedHandleState& handle_state, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileWriter> receiver, + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileWriter> receiver, bool has_transient_user_activation, bool auto_close, download::QuarantineConnectionCallback quarantine_connection_callback) @@ -186,7 +186,7 @@ RunWithWritePermission( base::BindOnce(&NativeFileSystemFileWriterImpl::WriteImpl, weak_factory_.GetWeakPtr(), offset, std::move(data)), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, WriteCallback callback) { std::move(callback).Run(std::move(result), /*bytes_written=*/0); @@ -203,7 +203,7 @@ RunWithWritePermission( base::BindOnce(&NativeFileSystemFileWriterImpl::WriteStreamImpl, weak_factory_.GetWeakPtr(), offset, std::move(stream)), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, WriteStreamCallback callback) { std::move(callback).Run(std::move(result), /*bytes_written=*/0); @@ -218,7 +218,7 @@ RunWithWritePermission( base::BindOnce(&NativeFileSystemFileWriterImpl::TruncateImpl, weak_factory_.GetWeakPtr(), length), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, TruncateCallback callback) { std::move(callback).Run(std::move(result)); }), @@ -231,7 +231,7 @@ RunWithWritePermission( base::BindOnce(&NativeFileSystemFileWriterImpl::CloseImpl, weak_factory_.GetWeakPtr()), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, CloseCallback callback) { std::move(callback).Run(std::move(result)); }), @@ -244,7 +244,7 @@ RunWithWritePermission( base::BindOnce(&NativeFileSystemFileWriterImpl::AbortImpl, weak_factory_.GetWeakPtr()), - base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result, + base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result, AbortCallback callback) { std::move(callback).Run(std::move(result)); }), @@ -294,7 +294,7 @@ MaybeCallCallbackAndDeleteThis(); } - void WriteCompleted(blink::mojom::NativeFileSystemErrorPtr result, + void WriteCompleted(blink::mojom::FileSystemAccessErrorPtr result, uint64_t bytes_written) { DCHECK(!write_result_); write_result_ = std::move(result); @@ -328,7 +328,7 @@ return; } if (!write_result_.is_null() && - write_result_->status != blink::mojom::NativeFileSystemStatus::kOk) { + write_result_->status != blink::mojom::FileSystemAccessStatus::kOk) { // Writing failed, report that error. std::move(callback_).Run(std::move(write_result_), 0); delete this; @@ -348,7 +348,7 @@ mojo::Receiver<blink::mojom::BlobReaderClient> receiver_; base::Optional<int32_t> read_result_; - blink::mojom::NativeFileSystemErrorPtr write_result_; + blink::mojom::FileSystemAccessErrorPtr write_result_; uint64_t bytes_written_ = 0; }; @@ -356,7 +356,7 @@ // Do not call this method if |close_callback_| is not set. void NativeFileSystemFileWriterImpl::CallCloseCallbackAndMaybeDeleteThis( - blink::mojom::NativeFileSystemErrorPtr result) { + blink::mojom::FileSystemAccessErrorPtr result) { std::move(close_callback_).Run(std::move(result)); if (!receiver_.is_bound()) { @@ -373,8 +373,8 @@ if (!is_closed() && auto_close_) { // Close the Writer. |this| is deleted via // CallCloseCallbackAndMaybeDeleteThis when Close finishes. - Close(base::BindOnce([](blink::mojom::NativeFileSystemErrorPtr result) { - if (result->status != blink::mojom::NativeFileSystemStatus::kOk) { + Close(base::BindOnce([](blink::mojom::FileSystemAccessErrorPtr result) { + if (result->status != blink::mojom::FileSystemAccessStatus::kOk) { DLOG(ERROR) << "AutoClose failed with result:" << base::File::ErrorToString(result->file_error); } @@ -397,7 +397,7 @@ if (is_closed()) { std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kInvalidState, + FileSystemAccessStatus::kInvalidState, "An attempt was made to write to a closed writer."), /*bytes_written=*/0); return; @@ -417,7 +417,7 @@ if (rv != MOJO_RESULT_OK) { std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationFailed, + FileSystemAccessStatus::kOperationFailed, "Internal read error: failed to create mojo data pipe."), /*bytes_written=*/0); return; @@ -446,7 +446,7 @@ if (is_closed()) { std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kInvalidState, + FileSystemAccessStatus::kInvalidState, "An attempt was made to write to a closed writer."), /*bytes_written=*/0); return; @@ -483,7 +483,7 @@ if (is_closed()) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kInvalidState, + FileSystemAccessStatus::kInvalidState, "An attempt was made to write to a closed writer.")); return; } @@ -505,7 +505,7 @@ blink::mojom::PermissionStatus::GRANTED); if (is_closed()) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kInvalidState, + FileSystemAccessStatus::kInvalidState, "An attempt was made to close an already closed writer.")); return; } @@ -528,7 +528,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (is_closed()) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kInvalidState, + FileSystemAccessStatus::kInvalidState, "An attempt was made to abort an already closed writer.")); return; } @@ -552,7 +552,7 @@ manager()->operation_runner().PostTaskWithThisObject( FROM_HERE, base::BindOnce(&RemoveSwapFile, swap_url())); CallCloseCallbackAndMaybeDeleteThis(native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationAborted, + FileSystemAccessStatus::kOperationAborted, "Failed to perform Safe Browsing check.")); return; } @@ -580,7 +580,7 @@ manager()->operation_runner().PostTaskWithThisObject( FROM_HERE, base::BindOnce(&RemoveSwapFile, swap_url())); CallCloseCallbackAndMaybeDeleteThis(native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationAborted, + FileSystemAccessStatus::kOperationAborted, "Write operation blocked by Safe Browsing.")); return; } @@ -706,7 +706,7 @@ // There is nothing to do except to return the error message to the // application. CallCloseCallbackAndMaybeDeleteThis(native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationAborted, + FileSystemAccessStatus::kOperationAborted, "Write operation aborted due to security policy.")); return; }
diff --git a/content/browser/file_system_access/native_file_system_file_writer_impl.h b/content/browser/file_system_access/native_file_system_file_writer_impl.h index a6c31367..2a9e1433 100644 --- a/content/browser/file_system_access/native_file_system_file_writer_impl.h +++ b/content/browser/file_system_access/native_file_system_file_writer_impl.h
@@ -18,7 +18,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "storage/browser/file_system/file_system_url.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom.h" namespace content { @@ -31,7 +31,7 @@ // sequence. class CONTENT_EXPORT NativeFileSystemFileWriterImpl : public NativeFileSystemHandleBase, - public blink::mojom::NativeFileSystemFileWriter { + public blink::mojom::FileSystemAccessFileWriter { public: // Creates a FileWriter that writes in a swap file URL and // materializes the changes in the target file URL only after `Close` @@ -47,7 +47,7 @@ const storage::FileSystemURL& url, const storage::FileSystemURL& swap_url, const SharedHandleState& handle_state, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileWriter> receiver, + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileWriter> receiver, bool has_transient_user_activation, bool auto_close, download::QuarantineConnectionCallback quarantine_connection_callback); @@ -80,13 +80,13 @@ // progress until the write completes. struct WriteState; - mojo::Receiver<blink::mojom::NativeFileSystemFileWriter> receiver_; + mojo::Receiver<blink::mojom::FileSystemAccessFileWriter> receiver_; void OnDisconnect(); // Delete the FileWriter after Close if the mojo pipe is unbound. void CallCloseCallbackAndMaybeDeleteThis( - blink::mojom::NativeFileSystemErrorPtr result); + blink::mojom::FileSystemAccessErrorPtr result); void WriteImpl(uint64_t offset, mojo::PendingRemote<blink::mojom::Blob> data,
diff --git a/content/browser/file_system_access/native_file_system_file_writer_impl_unittest.cc b/content/browser/file_system_access/native_file_system_file_writer_impl_unittest.cc index 0b53a08..b5dd989 100644 --- a/content/browser/file_system_access/native_file_system_file_writer_impl_unittest.cc +++ b/content/browser/file_system_access/native_file_system_file_writer_impl_unittest.cc
@@ -34,7 +34,7 @@ #include "storage/browser/test/test_file_system_context.h" #include "testing/gtest/include/gtest/gtest.h" -using blink::mojom::NativeFileSystemStatus; +using blink::mojom::FileSystemAccessStatus; using storage::FileSystemURL; using storage::IsolatedContext; @@ -239,15 +239,15 @@ } } - NativeFileSystemStatus WriteBlobSync( + FileSystemAccessStatus WriteBlobSync( uint64_t position, mojo::PendingRemote<blink::mojom::Blob> blob, uint64_t* bytes_written_out) { base::RunLoop loop; - NativeFileSystemStatus result_out; + FileSystemAccessStatus result_out; handle_->Write(position, std::move(blob), base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, + [&](blink::mojom::FileSystemAccessErrorPtr result, uint64_t bytes_written) { result_out = result->status; *bytes_written_out = bytes_written; @@ -257,15 +257,15 @@ return result_out; } - NativeFileSystemStatus WriteStreamSync( + FileSystemAccessStatus WriteStreamSync( uint64_t position, mojo::ScopedDataPipeConsumerHandle data_pipe, uint64_t* bytes_written_out) { base::RunLoop loop; - NativeFileSystemStatus result_out; + FileSystemAccessStatus result_out; handle_->WriteStream(position, std::move(data_pipe), base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, + [&](blink::mojom::FileSystemAccessErrorPtr result, uint64_t bytes_written) { result_out = result->status; *bytes_written_out = bytes_written; @@ -275,12 +275,12 @@ return result_out; } - NativeFileSystemStatus TruncateSync(uint64_t length) { + FileSystemAccessStatus TruncateSync(uint64_t length) { base::RunLoop loop; - NativeFileSystemStatus result_out; + FileSystemAccessStatus result_out; handle_->Truncate(length, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result) { + [&](blink::mojom::FileSystemAccessErrorPtr result) { result_out = result->status; loop.Quit(); })); @@ -288,11 +288,11 @@ return result_out; } - NativeFileSystemStatus CloseSync() { + FileSystemAccessStatus CloseSync() { base::RunLoop loop; - NativeFileSystemStatus result_out; + FileSystemAccessStatus result_out; handle_->Close(base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result) { + [&](blink::mojom::FileSystemAccessErrorPtr result) { result_out = result->status; loop.Quit(); })); @@ -300,11 +300,11 @@ return result_out; } - NativeFileSystemStatus AbortSync() { + FileSystemAccessStatus AbortSync() { base::RunLoop loop; - NativeFileSystemStatus result_out; + FileSystemAccessStatus result_out; handle_->Abort(base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result) { + [&](blink::mojom::FileSystemAccessErrorPtr result) { result_out = result->status; loop.Quit(); })); @@ -314,7 +314,7 @@ virtual bool WriteUsingBlobs() { return true; } - NativeFileSystemStatus WriteSync(uint64_t position, + FileSystemAccessStatus WriteSync(uint64_t position, const std::string& contents, uint64_t* bytes_written_out) { if (WriteUsingBlobs()) @@ -349,7 +349,7 @@ FixedNativeFileSystemPermissionGrant::PermissionStatus::GRANTED, base::FilePath()); - mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> remote_; + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> remote_; base::WeakPtr<NativeFileSystemFileWriterImpl> handle_; }; @@ -374,20 +374,20 @@ ignore_result(blob.InitWithNewPipeAndPassReceiver()); uint64_t bytes_written; - NativeFileSystemStatus result = + FileSystemAccessStatus result = WriteBlobSync(0, std::move(blob), &bytes_written); EXPECT_EQ(bytes_written, 0u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ("", ReadFile(test_file_url_)); } TEST_F(NativeFileSystemFileWriterImplTest, HashSimpleOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); base::RunLoop loop; @@ -437,8 +437,8 @@ size_t target_size = 9 * 1024u; std::string file_data(target_size, '0'); uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, file_data, &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, file_data, &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, target_size); base::RunLoop loop; @@ -457,12 +457,12 @@ TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteValidEmptyString) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 0u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_TRUE(base::Contains(quarantine_.paths, test_file_url_.path())); EXPECT_EQ("", ReadFile(test_file_url_)); @@ -471,12 +471,12 @@ TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteValidNonEmpty) { std::string test_data("abcdefghijklmnopqrstuvwxyz"); uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, test_data, &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, test_data, &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, test_data.size()); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_TRUE(base::Contains(quarantine_.paths, test_file_url_.path())); EXPECT_EQ(test_data, ReadFile(test_file_url_)); @@ -484,18 +484,18 @@ TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteWithOffsetInFile) { uint64_t bytes_written; - NativeFileSystemStatus result; + FileSystemAccessStatus result; result = WriteSync(0, "1234567890", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 10u); result = WriteSync(4, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_TRUE(base::Contains(quarantine_.paths, test_file_url_.path())); EXPECT_EQ("1234abc890", ReadFile(test_file_url_)); @@ -503,12 +503,12 @@ TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteWithOffsetPastFile) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(4, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kFileError); + FileSystemAccessStatus result = WriteSync(4, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kFileError); EXPECT_EQ(bytes_written, 0u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_TRUE(base::Contains(quarantine_.paths, test_file_url_.path())); using std::string_literals::operator""s; @@ -517,135 +517,135 @@ TEST_F(NativeFileSystemFileWriterImplTest, TruncateShrink) { uint64_t bytes_written; - NativeFileSystemStatus result; + FileSystemAccessStatus result; result = WriteSync(0, "1234567890", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 10u); result = TruncateSync(5); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ("12345", ReadFile(test_file_url_)); } TEST_F(NativeFileSystemFileWriterImplTest, TruncateGrow) { uint64_t bytes_written; - NativeFileSystemStatus result; + FileSystemAccessStatus result; result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = TruncateSync(5); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(std::string("abc\0\0", 5), ReadFile(test_file_url_)); } TEST_F(NativeFileSystemFileWriterImplTest, CloseAfterCloseNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); + EXPECT_EQ(result, FileSystemAccessStatus::kInvalidState); } TEST_F(NativeFileSystemFileWriterImplTest, TruncateAfterCloseNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = TruncateSync(0); - EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); + EXPECT_EQ(result, FileSystemAccessStatus::kInvalidState); } TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteAfterCloseNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = WriteSync(0, "bcd", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); + EXPECT_EQ(result, FileSystemAccessStatus::kInvalidState); } TEST_F(NativeFileSystemFileWriterImplTest, AbortAfterCloseNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = AbortSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); + EXPECT_EQ(result, FileSystemAccessStatus::kInvalidState); } TEST_F(NativeFileSystemFileWriterImplTest, AbortOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = AbortSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ("", ReadFile(test_file_url_)); } TEST_F(NativeFileSystemFileWriterImplTest, TruncateAfterAbortNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = AbortSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = TruncateSync(0); - EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); + EXPECT_EQ(result, FileSystemAccessStatus::kInvalidState); } TEST_P(NativeFileSystemFileWriterImplWriteTest, WriteAfterAbortNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = AbortSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = WriteSync(0, "bcd", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); + EXPECT_EQ(result, FileSystemAccessStatus::kInvalidState); } TEST_F(NativeFileSystemFileWriterImplTest, CloseAfterAbortNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); result = AbortSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kInvalidState); + EXPECT_EQ(result, FileSystemAccessStatus::kInvalidState); } // TODO(mek): More tests, particularly for error conditions. @@ -664,8 +664,8 @@ TEST_F(NativeFileSystemFileWriterAfterWriteChecksTest, Allow) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); std::string expected_hash; @@ -690,7 +690,7 @@ NativeFileSystemPermissionContext::AfterWriteCheckResult::kAllow)); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); task_environment_.RunUntilIdle(); EXPECT_FALSE(storage::AsyncFileTestHelper::FileExists( @@ -702,8 +702,8 @@ TEST_F(NativeFileSystemFileWriterAfterWriteChecksTest, Block) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); EXPECT_CALL(permission_context_, PerformAfterWriteChecks_(_, kFrameId, _)) @@ -711,7 +711,7 @@ NativeFileSystemPermissionContext::AfterWriteCheckResult::kBlock)); result = CloseSync(); - EXPECT_EQ(result, NativeFileSystemStatus::kOperationAborted); + EXPECT_EQ(result, FileSystemAccessStatus::kOperationAborted); task_environment_.RunUntilIdle(); EXPECT_FALSE(storage::AsyncFileTestHelper::FileExists( @@ -724,8 +724,8 @@ TEST_F(NativeFileSystemFileWriterAfterWriteChecksTest, HandleCloseDuringCheckOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); using SBCallback = base::OnceCallback<void( @@ -766,8 +766,8 @@ TEST_F(NativeFileSystemFileWriterAfterWriteChecksTest, HandleCloseDuringCheckNotOK) { uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "abc", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "abc", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); using SBCallback = base::OnceCallback<void( @@ -825,7 +825,7 @@ storage::AsyncFileTestHelper::CreateFile(file_system_context_.get(), test_swap_url_)); - mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> remote; handle_ = manager_->CreateFileWriter(NativeFileSystemManagerImpl::BindingContext( kTestOrigin, kTestURL, kFrameId), @@ -837,8 +837,8 @@ /*auto_close=*/false, quarantine_callback_); uint64_t bytes_written; - NativeFileSystemStatus result = WriteSync(0, "foo", &bytes_written); - EXPECT_EQ(result, NativeFileSystemStatus::kOk); + FileSystemAccessStatus result = WriteSync(0, "foo", &bytes_written); + EXPECT_EQ(result, FileSystemAccessStatus::kOk); EXPECT_EQ(bytes_written, 3u); using SBCallback = base::OnceCallback<void(
diff --git a/content/browser/file_system_access/native_file_system_handle_base.cc b/content/browser/file_system_access/native_file_system_handle_base.cc index 00e46b0..08716edb 100644 --- a/content/browser/file_system_access/native_file_system_handle_base.cc +++ b/content/browser/file_system_access/native_file_system_handle_base.cc
@@ -89,7 +89,7 @@ void NativeFileSystemHandleBase::DoRequestPermission( bool writable, - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, PermissionStatus)> callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); PermissionStatus current_status = @@ -137,7 +137,7 @@ void NativeFileSystemHandleBase::DidRequestPermission( bool writable, - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, PermissionStatus)> callback, NativeFileSystemPermissionGrant::PermissionRequestOutcome outcome) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -147,14 +147,14 @@ case Outcome::kThirdPartyContext: std::move(callback).Run( native_file_system_error::FromStatus( - blink::mojom::NativeFileSystemStatus::kSecurityError, + blink::mojom::FileSystemAccessStatus::kSecurityError, "Not allowed to request permissions in this context."), writable ? GetWritePermissionStatus() : GetReadPermissionStatus()); return; case Outcome::kNoUserActivation: std::move(callback).Run( native_file_system_error::FromStatus( - blink::mojom::NativeFileSystemStatus::kSecurityError, + blink::mojom::FileSystemAccessStatus::kSecurityError, "User activation is required to request permissions."), writable ? GetWritePermissionStatus() : GetReadPermissionStatus()); return;
diff --git a/content/browser/file_system_access/native_file_system_handle_base.h b/content/browser/file_system_access/native_file_system_handle_base.h index 4175c65..2c57498 100644 --- a/content/browser/file_system_access/native_file_system_handle_base.h +++ b/content/browser/file_system_access/native_file_system_handle_base.h
@@ -58,15 +58,15 @@ PermissionStatus GetWritePermissionStatus(); // Implementation for the GetPermissionStatus method in the - // blink::mojom::NativeFileSystemFileHandle and DirectoryHandle interfaces. + // blink::mojom::FileSystemAccessFileHandle and DirectoryHandle interfaces. void DoGetPermissionStatus( bool writable, base::OnceCallback<void(PermissionStatus)> callback); // Implementation for the RequestPermission method in the - // blink::mojom::NativeFileSystemFileHandle and DirectoryHandle interfaces. + // blink::mojom::FileSystemAccessFileHandle and DirectoryHandle interfaces. void DoRequestPermission( bool writable, - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, PermissionStatus)> callback); // Invokes |callback|, possibly after first requesting write permission. If @@ -75,7 +75,7 @@ template <typename CallbackArgType> void RunWithWritePermission( base::OnceCallback<void(CallbackArgType)> callback, - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, CallbackArgType)> no_permission_callback, CallbackArgType callback_arg); @@ -185,7 +185,7 @@ private: void DidRequestPermission( bool writable, - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, PermissionStatus)> callback, NativeFileSystemPermissionGrant::PermissionRequestOutcome outcome); @@ -206,7 +206,7 @@ template <typename CallbackArgType> void NativeFileSystemHandleBase::RunWithWritePermission( base::OnceCallback<void(CallbackArgType)> callback, - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, CallbackArgType)> no_permission_callback, CallbackArgType callback_arg) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -214,18 +214,18 @@ /*writable=*/true, base::BindOnce( [](base::OnceCallback<void(CallbackArgType)> callback, - base::OnceCallback<void(blink::mojom::NativeFileSystemErrorPtr, + base::OnceCallback<void(blink::mojom::FileSystemAccessErrorPtr, CallbackArgType)> no_permission_callback, CallbackArgType callback_arg, - blink::mojom::NativeFileSystemErrorPtr result, + blink::mojom::FileSystemAccessErrorPtr result, blink::mojom::PermissionStatus status) { if (status == blink::mojom::PermissionStatus::GRANTED) { std::move(callback).Run(std::move(callback_arg)); return; } - if (result->status == blink::mojom::NativeFileSystemStatus::kOk) { + if (result->status == blink::mojom::FileSystemAccessStatus::kOk) { result->status = - blink::mojom::NativeFileSystemStatus::kPermissionDenied; + blink::mojom::FileSystemAccessStatus::kPermissionDenied; } std::move(no_permission_callback) .Run(std::move(result), std::move(callback_arg));
diff --git a/content/browser/file_system_access/native_file_system_handle_base_unittest.cc b/content/browser/file_system_access/native_file_system_handle_base_unittest.cc index afdfee3..26244a29 100644 --- a/content/browser/file_system_access/native_file_system_handle_base_unittest.cc +++ b/content/browser/file_system_access/native_file_system_handle_base_unittest.cc
@@ -156,9 +156,9 @@ handle.DoRequestPermission( /*writable=*/true, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr error, + [&](blink::mojom::FileSystemAccessErrorPtr error, PermissionStatus result) { - EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, error->status); + EXPECT_EQ(blink::mojom::FileSystemAccessStatus::kOk, error->status); EXPECT_EQ(PermissionStatus::GRANTED, result); loop.Quit(); })); @@ -198,9 +198,9 @@ handle.DoRequestPermission( /*writable=*/true, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr error, + [&](blink::mojom::FileSystemAccessErrorPtr error, PermissionStatus result) { - EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, error->status); + EXPECT_EQ(blink::mojom::FileSystemAccessStatus::kOk, error->status); EXPECT_EQ(PermissionStatus::GRANTED, result); loop.Quit(); }));
diff --git a/content/browser/file_system_access/native_file_system_manager_impl.cc b/content/browser/file_system_access/native_file_system_manager_impl.cc index 21413f08..bea4230 100644 --- a/content/browser/file_system_access/native_file_system_manager_impl.cc +++ b/content/browser/file_system_access/native_file_system_manager_impl.cc
@@ -38,13 +38,13 @@ #include "storage/browser/file_system/isolated_context.h" #include "storage/common/file_system/file_system_types.h" #include "storage/common/file_system/file_system_util.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h" #include "url/origin.h" namespace content { -using blink::mojom::NativeFileSystemStatus; +using blink::mojom::FileSystemAccessStatus; using PermissionStatus = NativeFileSystemPermissionGrant::PermissionStatus; using SensitiveDirectoryResult = NativeFileSystemPermissionContext::SensitiveDirectoryResult; @@ -64,7 +64,7 @@ if (!web_contents) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationAborted), + FileSystemAccessStatus::kOperationAborted), {}); return; } @@ -75,7 +75,7 @@ // Third party iframes are not allowed to show a file picker. std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied, + FileSystemAccessStatus::kPermissionDenied, "Third party iframes are not allowed to show a file picker."), {}); return; @@ -233,7 +233,7 @@ void NativeFileSystemManagerImpl::BindReceiver( const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver) { + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!network::IsOriginPotentiallyTrustworthy(binding_context.origin)) { @@ -245,7 +245,7 @@ } void NativeFileSystemManagerImpl::BindInternalsReceiver( - mojo::PendingReceiver<storage::mojom::NativeFileSystemContext> receiver) { + mojo::PendingReceiver<storage::mojom::FileSystemAccessContext> receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); internals_receivers_.Add(this, std::move(receiver)); @@ -302,8 +302,8 @@ !permission_context_->CanObtainWritePermission(context.origin))) { std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied), - std::vector<blink::mojom::NativeFileSystemEntryPtr>()); + FileSystemAccessStatus::kPermissionDenied), + std::vector<blink::mojom::FileSystemAccessEntryPtr>()); return; } } @@ -312,8 +312,8 @@ if (!rfh) { std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationAborted), - std::vector<blink::mojom::NativeFileSystemEntryPtr>()); + FileSystemAccessStatus::kOperationAborted), + std::vector<blink::mojom::FileSystemAccessEntryPtr>()); return; } @@ -324,9 +324,9 @@ if (!rfh->HasTransientUserActivation()) { std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kPermissionDenied, + FileSystemAccessStatus::kPermissionDenied, "User activation is required to show a file picker."), - std::vector<blink::mojom::NativeFileSystemEntryPtr>()); + std::vector<blink::mojom::FileSystemAccessEntryPtr>()); return; } @@ -398,7 +398,7 @@ PathType path_type, const base::FilePath& file_path, int renderer_id, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessDragDropToken> receiver) { auto drag_drop_token_impl = std::make_unique<NativeFileSystemDragDropTokenImpl>( @@ -408,9 +408,9 @@ } void NativeFileSystemManagerImpl::GetEntryFromDragDropToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> token, GetEntryFromDragDropTokenCallback token_resolved_callback) { - mojo::Remote<blink::mojom::NativeFileSystemDragDropToken> drop_token_remote( + mojo::Remote<blink::mojom::FileSystemAccessDragDropToken> drop_token_remote( std::move(token)); // Get a failure callback in case this token ends up not being valid (i.e. @@ -432,7 +432,7 @@ } void NativeFileSystemManagerImpl::ResolveDragDropToken( - mojo::Remote<blink::mojom::NativeFileSystemDragDropToken>, + mojo::Remote<blink::mojom::FileSystemAccessDragDropToken>, const BindingContext& binding_context, GetEntryFromDragDropTokenCallback token_resolved_callback, mojo::ReportBadMessageCallback failed_token_redemption_callback, @@ -482,16 +482,16 @@ file_path, binding_context.origin, std::move(url.file_system), file_type, UserAction::kDragAndDrop); - blink::mojom::NativeFileSystemEntryPtr entry; + blink::mojom::FileSystemAccessEntryPtr entry; if (file_type == HandleType::kDirectory) { - entry = blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewDirectory( + entry = blink::mojom::FileSystemAccessEntry::New( + blink::mojom::FileSystemAccessHandle::NewDirectory( CreateDirectoryHandle(binding_context, url.url, shared_handle_state)), url.base_name); } else { - entry = blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewFile( + entry = blink::mojom::FileSystemAccessEntry::New( + blink::mojom::FileSystemAccessHandle::NewFile( CreateFileHandle(binding_context, url.url, shared_handle_state)), url.base_name); } @@ -500,8 +500,8 @@ } void NativeFileSystemManagerImpl::GetFileHandleFromToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileHandle> file_handle_receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -514,8 +514,8 @@ } void NativeFileSystemManagerImpl::GetDirectoryHandleFromToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, + mojo::PendingReceiver<blink::mojom::FileSystemAccessDirectoryHandle> directory_handle_receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -528,7 +528,7 @@ } void NativeFileSystemManagerImpl::SerializeHandle( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, SerializeHandleCallback callback) { ResolveTransferToken( std::move(token), @@ -614,7 +614,7 @@ void NativeFileSystemManagerImpl::DeserializeHandle( const url::Origin& origin, const std::vector<uint8_t>& bits, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> token) { + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token) { DCHECK(!bits.empty()); std::string bits_as_string(bits.begin(), bits.end()); @@ -687,7 +687,7 @@ } } -blink::mojom::NativeFileSystemEntryPtr +blink::mojom::FileSystemAccessEntryPtr NativeFileSystemManagerImpl::CreateFileEntryFromPath( const BindingContext& binding_context, PathType path_type, @@ -701,13 +701,13 @@ file_path, binding_context.origin, std::move(url.file_system), HandleType::kFile, user_action); - return blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewFile( + return blink::mojom::FileSystemAccessEntry::New( + blink::mojom::FileSystemAccessHandle::NewFile( CreateFileHandle(binding_context, url.url, shared_handle_state)), url.base_name); } -blink::mojom::NativeFileSystemEntryPtr +blink::mojom::FileSystemAccessEntryPtr NativeFileSystemManagerImpl::CreateDirectoryEntryFromPath( const BindingContext& binding_context, PathType path_type, @@ -721,13 +721,13 @@ file_path, binding_context.origin, std::move(url.file_system), HandleType::kDirectory, user_action); - return blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewDirectory( + return blink::mojom::FileSystemAccessEntry::New( + blink::mojom::FileSystemAccessHandle::NewDirectory( CreateDirectoryHandle(binding_context, url.url, shared_handle_state)), url.base_name); } -mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle> +mojo::PendingRemote<blink::mojom::FileSystemAccessFileHandle> NativeFileSystemManagerImpl::CreateFileHandle( const BindingContext& binding_context, const storage::FileSystemURL& url, @@ -738,14 +738,14 @@ handle_state.file_system.is_valid()) << url.mount_type(); - mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle> result; + mojo::PendingRemote<blink::mojom::FileSystemAccessFileHandle> result; file_receivers_.Add(std::make_unique<NativeFileSystemFileHandleImpl>( this, binding_context, url, handle_state), result.InitWithNewPipeAndPassReceiver()); return result; } -mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> +mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> NativeFileSystemManagerImpl::CreateDirectoryHandle( const BindingContext& binding_context, const storage::FileSystemURL& url, @@ -756,7 +756,7 @@ handle_state.file_system.is_valid()) << url.mount_type(); - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> result; + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> result; directory_receivers_.Add( std::make_unique<NativeFileSystemDirectoryHandleImpl>( this, binding_context, url, handle_state), @@ -764,7 +764,7 @@ return result; } -mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> +mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> NativeFileSystemManagerImpl::CreateFileWriter( const BindingContext& binding_context, const storage::FileSystemURL& url, @@ -773,7 +773,8 @@ bool auto_close) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> result; + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> result; + RenderFrameHost* rfh = RenderFrameHost::FromID(binding_context.frame_id); bool has_transient_user_activation = rfh && rfh->HasTransientUserActivation(); @@ -791,7 +792,7 @@ const storage::FileSystemURL& url, const storage::FileSystemURL& swap_url, const SharedHandleState& handle_state, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileWriter> receiver, + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileWriter> receiver, bool has_transient_user_activation, bool auto_close, download::QuarantineConnectionCallback quarantine_connection_callback) { @@ -811,7 +812,7 @@ void NativeFileSystemManagerImpl::CreateTransferToken( const NativeFileSystemFileHandleImpl& file, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver) { return CreateTransferTokenImpl(file.url(), file.context().origin, file.handle_state(), HandleType::kFile, @@ -820,7 +821,7 @@ void NativeFileSystemManagerImpl::CreateTransferToken( const NativeFileSystemDirectoryHandleImpl& directory, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver) { return CreateTransferTokenImpl(directory.url(), directory.context().origin, directory.handle_state(), @@ -828,11 +829,11 @@ } void NativeFileSystemManagerImpl::ResolveTransferToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, ResolvedTokenCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - mojo::Remote<blink::mojom::NativeFileSystemTransferToken> token_remote( + mojo::Remote<blink::mojom::FileSystemAccessTransferToken> token_remote( std::move(token)); auto* raw_token = token_remote.get(); raw_token->GetInternalID(mojo::WrapCallbackWithDefaultInvokeIfNotRun( @@ -844,7 +845,7 @@ void NativeFileSystemManagerImpl::DidResolveTransferTokenForFileHandle( const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileHandle> file_handle_receiver, NativeFileSystemTransferTokenImpl* resolved_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -869,7 +870,7 @@ void NativeFileSystemManagerImpl::DidResolveTransferTokenForDirectoryHandle( const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::PendingReceiver<blink::mojom::FileSystemAccessDirectoryHandle> directory_handle_receiver, NativeFileSystemTransferTokenImpl* resolved_token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -927,14 +928,14 @@ const BindingContext& binding_context, const FileSystemChooser::Options& options, ChooseEntriesCallback callback, - blink::mojom::NativeFileSystemErrorPtr result, + blink::mojom::FileSystemAccessErrorPtr result, std::vector<FileSystemChooser::ResultEntry> entries) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (result->status != NativeFileSystemStatus::kOk || entries.empty()) { + if (result->status != FileSystemAccessStatus::kOk || entries.empty()) { std::move(callback).Run( std::move(result), - std::vector<blink::mojom::NativeFileSystemEntryPtr>()); + std::vector<blink::mojom::FileSystemAccessEntryPtr>()); return; } @@ -974,8 +975,8 @@ if (result == SensitiveDirectoryResult::kAbort) { std::move(callback).Run( native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationAborted), - std::vector<blink::mojom::NativeFileSystemEntryPtr>()); + FileSystemAccessStatus::kOperationAborted), + std::vector<blink::mojom::FileSystemAccessEntryPtr>()); return; } if (result == SensitiveDirectoryResult::kTryAgain) { @@ -1032,7 +1033,7 @@ return; } - std::vector<blink::mojom::NativeFileSystemEntryPtr> result_entries; + std::vector<blink::mojom::FileSystemAccessEntryPtr> result_entries; result_entries.reserve(entries.size()); for (const auto& entry : entries) { result_entries.push_back(CreateFileEntryFromPath( @@ -1049,14 +1050,14 @@ ChooseEntriesCallback callback, bool success) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - std::vector<blink::mojom::NativeFileSystemEntryPtr> result_entries; + std::vector<blink::mojom::FileSystemAccessEntryPtr> result_entries; if (!success) { // TODO(https://crbug.com/1124871): Failure to create or truncate the file // should probably not just result in a generic error, but instead inform // the user of the problem? std::move(callback).Run( native_file_system_error::FromStatus( - blink::mojom::NativeFileSystemStatus::kOperationFailed, + blink::mojom::FileSystemAccessStatus::kOperationFailed, "Failed to create or truncate file"), std::move(result_entries)); return; @@ -1066,8 +1067,8 @@ entry.path, binding_context.origin, std::move(url.file_system), HandleType::kFile, UserAction::kSave); - result_entries.push_back(blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewFile( + result_entries.push_back(blink::mojom::FileSystemAccessEntry::New( + blink::mojom::FileSystemAccessHandle::NewFile( CreateFileHandle(binding_context, url.url, shared_handle_state)), url.base_name)); @@ -1086,11 +1087,11 @@ "NativeFileSystemAPI.ConfirmReadDirectoryResult", shared_handle_state.read_grant->GetStatus()); - std::vector<blink::mojom::NativeFileSystemEntryPtr> result_entries; + std::vector<blink::mojom::FileSystemAccessEntryPtr> result_entries; if (shared_handle_state.read_grant->GetStatus() != PermissionStatus::GRANTED) { std::move(callback).Run(native_file_system_error::FromStatus( - NativeFileSystemStatus::kOperationAborted), + FileSystemAccessStatus::kOperationAborted), std::move(result_entries)); return; } @@ -1098,8 +1099,8 @@ FileSystemURLAndFSHandle url = CreateFileSystemURLFromPath( binding_context.origin, entry.type, entry.path); - result_entries.push_back(blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewDirectory(CreateDirectoryHandle( + result_entries.push_back(blink::mojom::FileSystemAccessEntry::New( + blink::mojom::FileSystemAccessHandle::NewDirectory(CreateDirectoryHandle( binding_context, url.url, SharedHandleState(shared_handle_state.read_grant, shared_handle_state.write_grant, @@ -1114,7 +1115,7 @@ const url::Origin& origin, const SharedHandleState& handle_state, HandleType handle_type, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1149,7 +1150,7 @@ } void NativeFileSystemManagerImpl::DoResolveTransferToken( - mojo::Remote<blink::mojom::NativeFileSystemTransferToken>, + mojo::Remote<blink::mojom::FileSystemAccessTransferToken>, ResolvedTokenCallback callback, const base::UnguessableToken& token) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/content/browser/file_system_access/native_file_system_manager_impl.h b/content/browser/file_system_access/native_file_system_manager_impl.h index e414cd52..f704feca8 100644 --- a/content/browser/file_system_access/native_file_system_manager_impl.h +++ b/content/browser/file_system_access/native_file_system_manager_impl.h
@@ -12,7 +12,7 @@ #include "base/threading/sequence_bound.h" #include "base/types/pass_key.h" #include "components/download/public/common/quarantine_connection.h" -#include "components/services/storage/public/mojom/native_file_system_context.mojom.h" +#include "components/services/storage/public/mojom/file_system_access_context.mojom.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/file_system_access/file_system_chooser.h" #include "content/common/content_export.h" @@ -26,9 +26,9 @@ #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/unique_receiver_set.h" #include "storage/browser/file_system/file_system_url.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" namespace storage { @@ -57,8 +57,8 @@ // thread only. class CONTENT_EXPORT NativeFileSystemManagerImpl : public NativeFileSystemEntryFactory, - public blink::mojom::NativeFileSystemManager, - public storage::mojom::NativeFileSystemContext { + public blink::mojom::FileSystemAccessManager, + public storage::mojom::FileSystemAccessContext { public: using BindingContext = NativeFileSystemEntryFactory::BindingContext; using PassKey = base::PassKey<NativeFileSystemManagerImpl>; @@ -94,12 +94,12 @@ void BindReceiver( const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver); + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver); void BindInternalsReceiver( - mojo::PendingReceiver<storage::mojom::NativeFileSystemContext> receiver); + mojo::PendingReceiver<storage::mojom::FileSystemAccessContext> receiver); - // blink::mojom::NativeFileSystemManager: + // blink::mojom::FileSystemAccessManager: void GetSandboxedFileSystem(GetSandboxedFileSystemCallback callback) override; void ChooseEntries( blink::mojom::ChooseFileSystemEntryType type, @@ -108,34 +108,34 @@ bool include_accepts_all, ChooseEntriesCallback callback) override; void GetFileHandleFromToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileHandle> file_handle_receiver) override; void GetDirectoryHandleFromToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, + mojo::PendingReceiver<blink::mojom::FileSystemAccessDirectoryHandle> directory_handle_receiver) override; void GetEntryFromDragDropToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> token, GetEntryFromDragDropTokenCallback token_resolved_callback) override; - // storage::mojom::NativeFileSystemContext: + // storage::mojom::FileSystemAccessContext: void SerializeHandle( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, SerializeHandleCallback callback) override; void DeserializeHandle( const url::Origin& origin, const std::vector<uint8_t>& bits, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> token) + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token) override; // NativeFileSystemEntryFactory: - blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPath( + blink::mojom::FileSystemAccessEntryPtr CreateFileEntryFromPath( const BindingContext& binding_context, PathType path_type, const base::FilePath& file_path, UserAction user_action) override; - blink::mojom::NativeFileSystemEntryPtr CreateDirectoryEntryFromPath( + blink::mojom::FileSystemAccessEntryPtr CreateDirectoryEntryFromPath( const BindingContext& binding_context, PathType path_type, const base::FilePath& directory_path, @@ -143,21 +143,21 @@ // Creates a new NativeFileSystemFileHandleImpl for a given url. Assumes the // passed in URL is valid and represents a file. - mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle> + mojo::PendingRemote<blink::mojom::FileSystemAccessFileHandle> CreateFileHandle(const BindingContext& binding_context, const storage::FileSystemURL& url, const SharedHandleState& handle_state); // Creates a new NativeFileSystemDirectoryHandleImpl for a given url. Assumes // the passed in URL is valid and represents a directory. - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> CreateDirectoryHandle(const BindingContext& context, const storage::FileSystemURL& url, const SharedHandleState& handle_state); // Creates a new NativeFileSystemFileWriterImpl for a given target and // swap file URLs. Assumes the passed in URLs are valid and represent files. - mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> CreateFileWriter(const BindingContext& binding_context, const storage::FileSystemURL& url, const storage::FileSystemURL& swap_url, @@ -170,7 +170,7 @@ const storage::FileSystemURL& url, const storage::FileSystemURL& swap_url, const SharedHandleState& handle_state, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileWriter> receiver, + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileWriter> receiver, bool has_transient_user_activation, bool auto_close, download::QuarantineConnectionCallback quarantine_connection_callback); @@ -178,22 +178,22 @@ // Create a transfer token for a specific file or directory. void CreateTransferToken( const NativeFileSystemFileHandleImpl& file, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver); void CreateTransferToken( const NativeFileSystemDirectoryHandleImpl& directory, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver); // Creates an instance of NativeFileSystemDragDropTokenImpl with `file_path` // and `renderer_id` and attaches the instance to `receiver`. The `receiver`'s - // associated remote can be redeemed for a NativeFileSystemEntry object by a + // associated remote can be redeemed for a FileSystemAccessEntry object by a // process with ID matching `renderer_id`. void CreateNativeFileSystemDragDropToken( PathType path_type, const base::FilePath& file_path, int renderer_id, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDragDropToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessDragDropToken> receiver); // Given a mojom transfer token, looks up the token in our internal list of @@ -202,7 +202,7 @@ using ResolvedTokenCallback = base::OnceCallback<void(NativeFileSystemTransferTokenImpl*)>; void ResolveTransferToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token, ResolvedTokenCallback callback); storage::FileSystemContext* context() { @@ -280,7 +280,7 @@ void DidChooseEntries(const BindingContext& binding_context, const FileSystemChooser::Options& options, ChooseEntriesCallback callback, - blink::mojom::NativeFileSystemErrorPtr result, + blink::mojom::FileSystemAccessErrorPtr result, std::vector<FileSystemChooser::ResultEntry> entries); void DidVerifySensitiveDirectoryAccess( const BindingContext& binding_context, @@ -305,39 +305,39 @@ const url::Origin& origin, const SharedHandleState& handle_state, NativeFileSystemPermissionContext::HandleType handle_type, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver); void DoResolveTransferToken( - mojo::Remote<blink::mojom::NativeFileSystemTransferToken>, + mojo::Remote<blink::mojom::FileSystemAccessTransferToken>, ResolvedTokenCallback callback, const base::UnguessableToken& token); void DidResolveTransferTokenForFileHandle( const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> + mojo::PendingReceiver<blink::mojom::FileSystemAccessFileHandle> file_handle_receiver, NativeFileSystemTransferTokenImpl* resolved_token); void DidResolveTransferTokenForDirectoryHandle( const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::PendingReceiver<blink::mojom::FileSystemAccessDirectoryHandle> directory_handle_receiver, NativeFileSystemTransferTokenImpl* resolved_token); void DidResolveForSerializeHandle( SerializeHandleCallback callback, NativeFileSystemTransferTokenImpl* resolved_token); - // Calls `token_resolved_callback` with a NativeFileSystemEntry object + // Calls `token_resolved_callback` with a FileSystemAccessEntry object // that's at the file path of the NativeFileSystemDragDropToken with token // value `token`. If no such token exists, calls // `failed_token_redemption_callback`. void ResolveDragDropToken( - mojo::Remote<blink::mojom::NativeFileSystemDragDropToken>, + mojo::Remote<blink::mojom::FileSystemAccessDragDropToken>, const BindingContext& binding_context, GetEntryFromDragDropTokenCallback token_resolved_callback, mojo::ReportBadMessageCallback failed_token_redemption_callback, const base::UnguessableToken& token); - // Calls `token_resolved_callback` with a NativeFileSystemEntry representing + // Calls `token_resolved_callback` with a FileSystemAccessEntry representing // the file/directory at `file_path`. Called by // NativeFileSystemManager::ResolveDragDropToken after it looks up // whether the token's file path refers to a file or directory. @@ -359,17 +359,17 @@ // track of associated origin and other state as well to not have to rely on // the renderer passing that in, and to be able to do security checks around // transferability etc. - mojo::ReceiverSet<blink::mojom::NativeFileSystemManager, BindingContext> + mojo::ReceiverSet<blink::mojom::FileSystemAccessManager, BindingContext> receivers_; - mojo::ReceiverSet<storage::mojom::NativeFileSystemContext> + mojo::ReceiverSet<storage::mojom::FileSystemAccessContext> internals_receivers_; // All the receivers for file and directory handles that have references to // them. - mojo::UniqueReceiverSet<blink::mojom::NativeFileSystemFileHandle> + mojo::UniqueReceiverSet<blink::mojom::FileSystemAccessFileHandle> file_receivers_; - mojo::UniqueReceiverSet<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::UniqueReceiverSet<blink::mojom::FileSystemAccessDirectoryHandle> directory_receivers_; base::flat_set<std::unique_ptr<NativeFileSystemFileWriterImpl>, base::UniquePtrComparator>
diff --git a/content/browser/file_system_access/native_file_system_manager_impl_unittest.cc b/content/browser/file_system_access/native_file_system_manager_impl_unittest.cc index 4a4729a..6a77c62b 100644 --- a/content/browser/file_system_access/native_file_system_manager_impl_unittest.cc +++ b/content/browser/file_system_access/native_file_system_manager_impl_unittest.cc
@@ -39,8 +39,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-shared.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-shared.h" namespace content { @@ -79,14 +79,14 @@ // Returns the contents of the file referred to by `file_remote` as a // `std::string`. std::string ReadStringFromFileRemote( - mojo::Remote<blink::mojom::NativeFileSystemFileHandle> file_remote) { + mojo::Remote<blink::mojom::FileSystemAccessFileHandle> file_remote) { base::RunLoop await_get_blob; mojo::Remote<blink::mojom::Blob> blob; file_remote->AsBlob(base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, + [&](blink::mojom::FileSystemAccessErrorPtr result, const base::File::Info& info, blink::mojom::SerializedBlobPtr received_blob) { - EXPECT_EQ(result->status, blink::mojom::NativeFileSystemStatus::kOk); + EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); EXPECT_FALSE(received_blob.is_null()); blob.Bind(std::move(received_blob->blob)); await_get_blob.Quit(); @@ -173,7 +173,7 @@ return result; } - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> GetHandleForDirectory(const base::FilePath& path) { auto grant = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( FixedNativeFileSystemPermissionGrant::PermissionStatus::GRANTED, path); @@ -189,16 +189,16 @@ NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(grant)); - blink::mojom::NativeFileSystemEntryPtr entry = + blink::mojom::FileSystemAccessEntryPtr entry = manager_->CreateDirectoryEntryFromPath( kBindingContext, NativeFileSystemEntryFactory::PathType::kLocal, path, NativeFileSystemPermissionContext::UserAction::kOpen); - return mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle>( + return mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle>( std::move(entry->entry_handle->get_directory())); } NativeFileSystemTransferTokenImpl* SerializeAndDeserializeToken( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote) { std::vector<uint8_t> serialized; base::RunLoop serialize_loop; @@ -231,7 +231,7 @@ NativeFileSystemEntryFactory::PathType path_type, const std::string& expected_file_contents) { // Create a token representing a dropped file at `file_path`. - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> token_remote; manager_->CreateNativeFileSystemDragDropToken( path_type, file_path, kBindingContext.process_id(), @@ -253,12 +253,12 @@ .WillOnce(testing::Return(allow_grant_)); // Attempt to resolve `token_remote` and store the resulting - // NativeFileSystemFileHandle in `file_remote`. + // FileSystemAccessFileHandle in `file_remote`. base::RunLoop await_token_resolution; - blink::mojom::NativeFileSystemEntryPtr native_file_system_entry; + blink::mojom::FileSystemAccessEntryPtr native_file_system_entry; manager_remote_->GetEntryFromDragDropToken( std::move(token_remote), - base::BindLambdaForTesting([&](blink::mojom::NativeFileSystemEntryPtr + base::BindLambdaForTesting([&](blink::mojom::FileSystemAccessEntryPtr returned_native_file_system_entry) { native_file_system_entry = std::move(returned_native_file_system_entry); @@ -268,10 +268,10 @@ ASSERT_FALSE(native_file_system_entry.is_null()); ASSERT_TRUE(native_file_system_entry->entry_handle->is_file()); - mojo::Remote<blink::mojom::NativeFileSystemFileHandle> file_handle( + mojo::Remote<blink::mojom::FileSystemAccessFileHandle> file_handle( std::move(native_file_system_entry->entry_handle->get_file())); - // Check to see if the resulting NativeFileSystemFileHandle can read the + // Check to see if the resulting FileSystemAccessFileHandle can read the // contents of the file at `file_path`. EXPECT_EQ(ReadStringFromFileRemote(std::move(file_handle)), expected_file_contents); @@ -281,7 +281,7 @@ const base::FilePath& dir_path, NativeFileSystemEntryFactory::PathType path_type, const std::string& expected_child_file_name) { - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> token_remote; manager_->CreateNativeFileSystemDragDropToken( path_type, dir_path, kBindingContext.process_id(), @@ -303,12 +303,12 @@ .WillOnce(testing::Return(allow_grant_)); // Attempt to resolve `token_remote` and store the resulting - // NativeFileSystemDirectoryHandle in `dir_remote`. + // FileSystemAccessDirectoryHandle in `dir_remote`. base::RunLoop await_token_resolution; - blink::mojom::NativeFileSystemEntryPtr native_file_system_entry; + blink::mojom::FileSystemAccessEntryPtr native_file_system_entry; manager_remote_->GetEntryFromDragDropToken( std::move(token_remote), - base::BindLambdaForTesting([&](blink::mojom::NativeFileSystemEntryPtr + base::BindLambdaForTesting([&](blink::mojom::FileSystemAccessEntryPtr returned_native_file_system_entry) { native_file_system_entry = std::move(returned_native_file_system_entry); @@ -318,7 +318,7 @@ ASSERT_FALSE(native_file_system_entry.is_null()); ASSERT_TRUE(native_file_system_entry->entry_handle->is_directory()); - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> dir_remote( + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> dir_remote( std::move(native_file_system_entry->entry_handle->get_directory())); // Use `dir_remote` to verify that dir_path contains a child called @@ -327,11 +327,11 @@ dir_remote->GetFile( expected_child_file_name, /*create=*/false, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle> + [&](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessFileHandle> file_handle) { await_get_file.Quit(); - ASSERT_EQ(blink::mojom::NativeFileSystemStatus::kOk, + ASSERT_EQ(blink::mojom::FileSystemAccessStatus::kOk, result->status); })); await_get_file.Run(); @@ -360,7 +360,7 @@ testing::StrictMock<MockNativeFileSystemPermissionContext> permission_context_; scoped_refptr<NativeFileSystemManagerImpl> manager_; - mojo::Remote<blink::mojom::NativeFileSystemManager> manager_remote_; + mojo::Remote<blink::mojom::FileSystemAccessManager> manager_remote_; scoped_refptr<FixedNativeFileSystemPermissionGrant> ask_grant_ = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( @@ -377,19 +377,19 @@ }; TEST_F(NativeFileSystemManagerImplTest, GetSandboxedFileSystem_Permissions) { - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> directory_remote; base::RunLoop loop; manager_remote_->GetSandboxedFileSystem(base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> + [&](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> handle) { - EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, result->status); + EXPECT_EQ(blink::mojom::FileSystemAccessStatus::kOk, result->status); directory_remote = std::move(handle); loop.Quit(); })); loop.Run(); - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> root( + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> root( std::move(directory_remote)); ASSERT_TRUE(root); EXPECT_EQ(PermissionStatus::GRANTED, @@ -412,11 +412,11 @@ NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(ask_grant_)); - blink::mojom::NativeFileSystemEntryPtr entry = + blink::mojom::FileSystemAccessEntryPtr entry = manager_->CreateFileEntryFromPath( kBindingContext, NativeFileSystemEntryFactory::PathType::kLocal, kTestPath, NativeFileSystemPermissionContext::UserAction::kOpen); - mojo::Remote<blink::mojom::NativeFileSystemFileHandle> handle( + mojo::Remote<blink::mojom::FileSystemAccessFileHandle> handle( std::move(entry->entry_handle->get_file())); EXPECT_EQ(PermissionStatus::GRANTED, @@ -440,11 +440,11 @@ NativeFileSystemPermissionContext::UserAction::kSave)) .WillOnce(testing::Return(allow_grant_)); - blink::mojom::NativeFileSystemEntryPtr entry = + blink::mojom::FileSystemAccessEntryPtr entry = manager_->CreateFileEntryFromPath( kBindingContext, NativeFileSystemEntryFactory::PathType::kLocal, kTestPath, NativeFileSystemPermissionContext::UserAction::kSave); - mojo::Remote<blink::mojom::NativeFileSystemFileHandle> handle( + mojo::Remote<blink::mojom::FileSystemAccessFileHandle> handle( std::move(entry->entry_handle->get_file())); EXPECT_EQ(PermissionStatus::GRANTED, @@ -468,11 +468,11 @@ NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(ask_grant_)); - blink::mojom::NativeFileSystemEntryPtr entry = + blink::mojom::FileSystemAccessEntryPtr entry = manager_->CreateDirectoryEntryFromPath( kBindingContext, NativeFileSystemEntryFactory::PathType::kLocal, kTestPath, NativeFileSystemPermissionContext::UserAction::kOpen); - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> handle( + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> handle( std::move(entry->entry_handle->get_directory())); EXPECT_EQ(PermissionStatus::GRANTED, GetPermissionStatusSync(/*writable=*/false, handle.get())); @@ -498,7 +498,7 @@ storage::AsyncFileTestHelper::CreateFile(file_system_context_.get(), test_swap_url)); - mojo::Remote<blink::mojom::NativeFileSystemFileWriter> writer_remote( + mojo::Remote<blink::mojom::FileSystemAccessFileWriter> writer_remote( manager_->CreateFileWriter(kBindingContext, test_file_url, test_swap_url, NativeFileSystemManagerImpl::SharedHandleState( allow_grant_, allow_grant_, {}), @@ -531,7 +531,7 @@ storage::AsyncFileTestHelper::CreateFileWithData( file_system_context_.get(), test_swap_url, "foo", 3)); - mojo::Remote<blink::mojom::NativeFileSystemFileWriter> writer_remote( + mojo::Remote<blink::mojom::FileSystemAccessFileWriter> writer_remote( manager_->CreateFileWriter(kBindingContext, test_file_url, test_swap_url, NativeFileSystemManagerImpl::SharedHandleState( allow_grant_, allow_grant_, {}), @@ -575,7 +575,7 @@ storage::AsyncFileTestHelper::CreateFileWithData( file_system_context_.get(), test_swap_url, "foo", 3)); - mojo::Remote<blink::mojom::NativeFileSystemFileWriter> writer_remote( + mojo::Remote<blink::mojom::FileSystemAccessFileWriter> writer_remote( manager_->CreateFileWriter(kBindingContext, test_file_url, test_swap_url, NativeFileSystemManagerImpl::SharedHandleState( allow_grant_, allow_grant_, {}), @@ -608,7 +608,7 @@ storage::AsyncFileTestHelper::CreateFileWithData( file_system_context_.get(), test_swap_url, "foo", 3)); - mojo::Remote<blink::mojom::NativeFileSystemFileWriter> writer_remote( + mojo::Remote<blink::mojom::FileSystemAccessFileWriter> writer_remote( manager_->CreateFileWriter(kBindingContext, test_file_url, test_swap_url, NativeFileSystemManagerImpl::SharedHandleState( allow_grant_, allow_grant_, {}), @@ -645,7 +645,7 @@ NativeFileSystemFileHandleImpl file(manager_.get(), kBindingContext, test_file_url, {ask_grant_, ask_grant_, {}}); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; manager_->CreateTransferToken(file, token_remote.InitWithNewPipeAndPassReceiver()); @@ -670,7 +670,7 @@ NativeFileSystemDirectoryHandleImpl directory(manager_.get(), kBindingContext, test_file_url, {ask_grant_, ask_grant_, {}}); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; manager_->CreateTransferToken(directory, token_remote.InitWithNewPipeAndPassReceiver()); @@ -707,14 +707,14 @@ NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(grant)); - blink::mojom::NativeFileSystemEntryPtr entry = + blink::mojom::FileSystemAccessEntryPtr entry = manager_->CreateFileEntryFromPath( kBindingContext, NativeFileSystemEntryFactory::PathType::kLocal, kTestPath, NativeFileSystemPermissionContext::UserAction::kOpen); - mojo::Remote<blink::mojom::NativeFileSystemFileHandle> handle( + mojo::Remote<blink::mojom::FileSystemAccessFileHandle> handle( std::move(entry->entry_handle->get_file())); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; handle->Transfer(token_remote.InitWithNewPipeAndPassReceiver()); // Deserializing tokens should re-request grants, with correct user action. @@ -747,10 +747,10 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_Native_SingleDirectory) { const base::FilePath kTestPath(dir_.GetPath().AppendASCII("foobar")); - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> handle = + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> handle = GetHandleForDirectory(kTestPath); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; handle->Transfer(token_remote.InitWithNewPipeAndPassReceiver()); // Deserializing tokens should re-request grants, with correct user action. @@ -786,26 +786,26 @@ const std::string kTestName = "test file name ☺"; base::CreateDirectory(kDirectoryPath); - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> directory_handle = + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> directory_handle = GetHandleForDirectory(kDirectoryPath); - mojo::Remote<blink::mojom::NativeFileSystemFileHandle> file_handle; + mojo::Remote<blink::mojom::FileSystemAccessFileHandle> file_handle; base::RunLoop get_file_loop; directory_handle->GetFile( kTestName, /*create=*/true, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemFileHandle> + [&](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessFileHandle> handle) { get_file_loop.Quit(); - ASSERT_EQ(blink::mojom::NativeFileSystemStatus::kOk, + ASSERT_EQ(blink::mojom::FileSystemAccessStatus::kOk, result->status); file_handle.Bind(std::move(handle)); })); get_file_loop.Run(); ASSERT_TRUE(file_handle.is_bound()); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; file_handle->Transfer(token_remote.InitWithNewPipeAndPassReceiver()); // Deserializing tokens should re-request grants, with correct user action. @@ -842,26 +842,26 @@ const std::string kTestName = "test dir name"; base::CreateDirectory(kDirectoryPath); - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> directory_handle = + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> directory_handle = GetHandleForDirectory(kDirectoryPath); - mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> child_handle; + mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> child_handle; base::RunLoop get_directory_loop; directory_handle->GetDirectory( kTestName, /*create=*/true, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - mojo::PendingRemote<blink::mojom::NativeFileSystemDirectoryHandle> + [&](blink::mojom::FileSystemAccessErrorPtr result, + mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle> handle) { get_directory_loop.Quit(); - ASSERT_EQ(blink::mojom::NativeFileSystemStatus::kOk, + ASSERT_EQ(blink::mojom::FileSystemAccessStatus::kOk, result->status); child_handle.Bind(std::move(handle)); })); get_directory_loop.Run(); ASSERT_TRUE(child_handle.is_bound()); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; child_handle->Transfer(token_remote.InitWithNewPipeAndPassReceiver()); // Deserializing tokens should re-request grants, with correct user action. @@ -911,14 +911,14 @@ NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(grant)); - blink::mojom::NativeFileSystemEntryPtr entry = + blink::mojom::FileSystemAccessEntryPtr entry = manager_->CreateFileEntryFromPath( kBindingContext, NativeFileSystemEntryFactory::PathType::kExternal, kTestPath, NativeFileSystemPermissionContext::UserAction::kOpen); - mojo::Remote<blink::mojom::NativeFileSystemFileHandle> handle( + mojo::Remote<blink::mojom::FileSystemAccessFileHandle> handle( std::move(entry->entry_handle->get_file())); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote; handle->Transfer(token_remote.InitWithNewPipeAndPassReceiver()); // Deserializing tokens should re-request grants, with correct user action. @@ -949,7 +949,7 @@ // NativeFileSystemManager should successfully resolve a // NativeFileSystemDragDropToken representing a file in the user's file system -// into a valid Remote<blink::mojom::NativeFileSystemFileHandle>, given +// into a valid Remote<blink::mojom::FileSystemAccessFileHandle>, given // that the PID is valid. TEST_F(NativeFileSystemManagerImplTest, GetEntryFromDragDropToken_File_ValidPID) { @@ -964,7 +964,7 @@ // NativeFileSystemManager should successfully resolve a // NativeFileSystemDragDropToken representing a NativeFileSystemDirectoryEntry -// into a valid Remote<blink::mojom::NativeFileSystemDirectoryHandle>, given +// into a valid Remote<blink::mojom::FileSystemAccessDirectoryHandle>, given // that the PID is valid. TEST_F(NativeFileSystemManagerImplTest, GetEntryFromDragDropToken_Directory_ValidPID) { @@ -982,7 +982,7 @@ // NativeFileSystemManager should successfully resolve a // NativeFileSystemDragDropToken representing a file in the user's file system -// into a valid Remote<blink::mojom::NativeFileSystemFileHandle>, given +// into a valid Remote<blink::mojom::FileSystemAccessFileHandle>, given // that the PID is valid. TEST_F(NativeFileSystemManagerImplTest, GetEntryFromDragDropToken_File_ExternalPath) { @@ -1002,7 +1002,7 @@ // NativeFileSystemManager should successfully resolve a // NativeFileSystemDragDropToken representing a NativeFileSystemDirectoryEntry -// into a valid Remote<blink::mojom::NativeFileSystemDirectoryHandle>, given +// into a valid Remote<blink::mojom::FileSystemAccessDirectoryHandle>, given // that the PID is valid. TEST_F(NativeFileSystemManagerImplTest, GetEntryFromDragDropToken_Directory_ExternalPath) { @@ -1033,7 +1033,7 @@ // Create a NativeFileSystemDragDropToken with a PID different than the // process attempting to redeem to the token. - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> token_remote; manager_->CreateNativeFileSystemDragDropToken( NativeFileSystemEntryFactory::PathType::kLocal, file_path, /*renderer_id=*/kBindingContext.process_id() - 1, @@ -1059,7 +1059,7 @@ // Create a NativeFileSystemDragDropToken with an PID different than the // process attempting to redeem to the token. - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> token_remote; manager_->CreateNativeFileSystemDragDropToken( NativeFileSystemEntryFactory::PathType::kLocal, kDirPath, /*renderer_id=*/kBindingContext.process_id() - 1, @@ -1084,7 +1084,7 @@ // Create a NativeFileSystemDragDropToken without registering it to the // NativeFileSystemManager. - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> token_remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> token_remote; auto drag_drop_token_impl = std::make_unique<NativeFileSystemDragDropTokenImpl>( manager_.get(), NativeFileSystemEntryFactory::PathType::kLocal, @@ -1113,7 +1113,7 @@ static_cast<TestRenderFrameHost*>(web_contents_->GetMainFrame()) ->SimulateUserActivation(); - mojo::Remote<blink::mojom::NativeFileSystemManager> manager_remote; + mojo::Remote<blink::mojom::FileSystemAccessManager> manager_remote; NativeFileSystemManagerImpl::BindingContext binding_context = { kTestOrigin, kTestURL, web_contents_->GetMainFrame()->GetGlobalFrameRoutingId()}; @@ -1159,8 +1159,8 @@ blink::mojom::ChooseFileSystemEntryType::kOpenFile, /*accepts=*/{}, blink::mojom::CommonDirectory::kDefault, /*include_accepts_all=*/true, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - std::vector<blink::mojom::NativeFileSystemEntryPtr> entries) { + [&](blink::mojom::FileSystemAccessErrorPtr result, + std::vector<blink::mojom::FileSystemAccessEntryPtr> entries) { loop.Quit(); })); loop.Run(); @@ -1178,7 +1178,7 @@ static_cast<TestRenderFrameHost*>(web_contents_->GetMainFrame()) ->SimulateUserActivation(); - mojo::Remote<blink::mojom::NativeFileSystemManager> manager_remote; + mojo::Remote<blink::mojom::FileSystemAccessManager> manager_remote; NativeFileSystemManagerImpl::BindingContext binding_context = { kTestOrigin, kTestURL, web_contents_->GetMainFrame()->GetGlobalFrameRoutingId()}; @@ -1226,8 +1226,8 @@ blink::mojom::ChooseFileSystemEntryType::kSaveFile, /*accepts=*/{}, blink::mojom::CommonDirectory::kDefault, /*include_accepts_all=*/true, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - std::vector<blink::mojom::NativeFileSystemEntryPtr> entries) { + [&](blink::mojom::FileSystemAccessErrorPtr result, + std::vector<blink::mojom::FileSystemAccessEntryPtr> entries) { loop.Quit(); })); loop.Run(); @@ -1244,7 +1244,7 @@ static_cast<TestRenderFrameHost*>(web_contents_->GetMainFrame()) ->SimulateUserActivation(); - mojo::Remote<blink::mojom::NativeFileSystemManager> manager_remote; + mojo::Remote<blink::mojom::FileSystemAccessManager> manager_remote; NativeFileSystemManagerImpl::BindingContext binding_context = { kTestOrigin, kTestURL, web_contents_->GetMainFrame()->GetGlobalFrameRoutingId()}; @@ -1289,8 +1289,8 @@ blink::mojom::ChooseFileSystemEntryType::kOpenDirectory, {}, blink::mojom::CommonDirectory::kDefault, true, base::BindLambdaForTesting( - [&](blink::mojom::NativeFileSystemErrorPtr result, - std::vector<blink::mojom::NativeFileSystemEntryPtr> entries) { + [&](blink::mojom::FileSystemAccessErrorPtr result, + std::vector<blink::mojom::FileSystemAccessEntryPtr> entries) { loop.Quit(); })); loop.Run();
diff --git a/content/browser/file_system_access/native_file_system_transfer_token_impl.cc b/content/browser/file_system_access/native_file_system_transfer_token_impl.cc index a71fcee..cf434959 100644 --- a/content/browser/file_system_access/native_file_system_transfer_token_impl.cc +++ b/content/browser/file_system_access/native_file_system_transfer_token_impl.cc
@@ -6,7 +6,7 @@ #include "content/browser/file_system_access/native_file_system_directory_handle_impl.h" #include "content/browser/file_system_access/native_file_system_file_handle_impl.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom.h" namespace content { @@ -19,7 +19,7 @@ const NativeFileSystemManagerImpl::SharedHandleState& handle_state, HandleType handle_type, NativeFileSystemManagerImpl* manager, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> receiver) + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver) : token_(base::UnguessableToken::Create()), handle_type_(handle_type), manager_(manager), @@ -77,7 +77,7 @@ } void NativeFileSystemTransferTokenImpl::Clone( - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> clone_receiver) { receivers_.Add(this, std::move(clone_receiver)); }
diff --git a/content/browser/file_system_access/native_file_system_transfer_token_impl.h b/content/browser/file_system_access/native_file_system_transfer_token_impl.h index 1751378..9dcf8fb5 100644 --- a/content/browser/file_system_access/native_file_system_transfer_token_impl.h +++ b/content/browser/file_system_access/native_file_system_transfer_token_impl.h
@@ -11,11 +11,11 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/file_system/isolated_context.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom.h" namespace content { -// This is the browser side implementation of the NativeFileSystemTransferToken +// This is the browser side implementation of the FileSystemAccessTransferToken // mojom interface. These tokens are tied to a particular origin // and use the permission grants in their `handle_state_` member when creating // new handles. They are used for postMessage and IndexedDB, serialization as @@ -24,7 +24,7 @@ // Instances of this class should always be used from the sequence they were // created on. class CONTENT_EXPORT NativeFileSystemTransferTokenImpl - : public blink::mojom::NativeFileSystemTransferToken { + : public blink::mojom::FileSystemAccessTransferToken { public: NativeFileSystemTransferTokenImpl( const storage::FileSystemURL& url, @@ -32,7 +32,7 @@ const NativeFileSystemManagerImpl::SharedHandleState& handle_state, NativeFileSystemPermissionContext::HandleType handle_type, NativeFileSystemManagerImpl* manager, - mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> receiver); ~NativeFileSystemTransferTokenImpl() override; @@ -53,9 +53,9 @@ std::unique_ptr<NativeFileSystemDirectoryHandleImpl> CreateDirectoryHandle( const NativeFileSystemManagerImpl::BindingContext& binding_context) const; - // blink::mojom::NativeFileSystemTransferToken: + // blink::mojom::FileSystemAccessTransferToken: void GetInternalID(GetInternalIDCallback callback) override; - void Clone(mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + void Clone(mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> clone_receiver) override; private: @@ -72,7 +72,7 @@ const storage::FileSystemURL url_; const url::Origin origin_; const NativeFileSystemManagerImpl::SharedHandleState handle_state_; - mojo::ReceiverSet<blink::mojom::NativeFileSystemTransferToken> receivers_; + mojo::ReceiverSet<blink::mojom::FileSystemAccessTransferToken> receivers_; DISALLOW_COPY_AND_ASSIGN(NativeFileSystemTransferTokenImpl); };
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index b442052f2..490777704 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -627,7 +627,7 @@ const base::FilePath& blob_path, std::unique_ptr<TransactionalLevelDBDatabase> db, storage::mojom::BlobStorageContext* blob_storage_context, - storage::mojom::NativeFileSystemContext* native_file_system_context, + storage::mojom::FileSystemAccessContext* native_file_system_context, std::unique_ptr<storage::FilesystemProxy> filesystem_proxy, BlobFilesCleanedCallback blob_files_cleaned, ReportOutstandingBlobsCallback report_outstanding_blobs, @@ -3611,7 +3611,7 @@ // TODO(dmurph): Refactor IndexedDBExternalObject to not use a // SharedRemote, so this code can just move the remote, instead of // cloning. - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_clone; entry.native_file_system_token_remote()->Clone( token_clone.InitWithNewPipeAndPassReceiver());
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index 996235314..bb53130 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -28,7 +28,7 @@ #include "components/services/storage/indexed_db/scopes/scope_lock.h" #include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h" #include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h" -#include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h" +#include "components/services/storage/public/mojom/file_system_access_context.mojom-forward.h" #include "content/browser/indexed_db/indexed_db.h" #include "content/browser/indexed_db/indexed_db_external_object.h" #include "content/browser/indexed_db/indexed_db_external_object_storage.h" @@ -390,7 +390,7 @@ const base::FilePath& blob_path, std::unique_ptr<TransactionalLevelDBDatabase> db, storage::mojom::BlobStorageContext* blob_storage_context, - storage::mojom::NativeFileSystemContext* native_file_system_context, + storage::mojom::FileSystemAccessContext* native_file_system_context, std::unique_ptr<storage::FilesystemProxy> filesystem_proxy, BlobFilesCleanedCallback blob_files_cleaned, ReportOutstandingBlobsCallback report_outstanding_blobs, @@ -670,7 +670,7 @@ // Raw pointers are safe because the bindings are owned by // IndexedDBContextImpl. storage::mojom::BlobStorageContext* const blob_storage_context_; - storage::mojom::NativeFileSystemContext* const native_file_system_context_; + storage::mojom::FileSystemAccessContext* const native_file_system_context_; // Filesystem proxy to use for file operations. nullptr if in memory. const std::unique_ptr<storage::FilesystemProxy> filesystem_proxy_;
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index 8e404aa1..9285f27 100644 --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -74,7 +74,7 @@ const base::FilePath& blob_path, std::unique_ptr<TransactionalLevelDBDatabase> db, storage::mojom::BlobStorageContext* blob_storage_context, - storage::mojom::NativeFileSystemContext* native_file_system_context, + storage::mojom::FileSystemAccessContext* native_file_system_context, std::unique_ptr<storage::FilesystemProxy> filesystem_proxy, BlobFilesCleanedCallback blob_files_cleaned, ReportOutstandingBlobsCallback report_outstanding_blobs, @@ -123,7 +123,7 @@ explicit TestIDBFactory( IndexedDBContextImpl* idb_context, storage::mojom::BlobStorageContext* blob_storage_context, - storage::mojom::NativeFileSystemContext* native_file_system_context) + storage::mojom::FileSystemAccessContext* native_file_system_context) : IndexedDBFactoryImpl(idb_context, IndexedDBClassFactory::Get(), base::DefaultClock::GetInstance()), @@ -143,7 +143,7 @@ const base::FilePath& blob_path, std::unique_ptr<TransactionalLevelDBDatabase> db, storage::mojom::BlobStorageContext*, - storage::mojom::NativeFileSystemContext*, + storage::mojom::FileSystemAccessContext*, std::unique_ptr<storage::FilesystemProxy> filesystem_proxy, IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned, IndexedDBBackingStore::ReportOutstandingBlobsCallback @@ -161,7 +161,7 @@ private: storage::mojom::BlobStorageContext* blob_storage_context_; - storage::mojom::NativeFileSystemContext* native_file_system_context_; + storage::mojom::FileSystemAccessContext* native_file_system_context_; }; struct BlobWrite { @@ -229,20 +229,20 @@ bool write_files_to_disk_ = false; }; -class FakeNativeFileSystemTransferToken - : public ::blink::mojom::NativeFileSystemTransferToken { +class FakeFileSystemAccessTransferToken + : public ::blink::mojom::FileSystemAccessTransferToken { public: - explicit FakeNativeFileSystemTransferToken(const base::UnguessableToken& id) + explicit FakeFileSystemAccessTransferToken(const base::UnguessableToken& id) : id_(id) {} void GetInternalID(GetInternalIDCallback callback) override { std::move(callback).Run(id_); } - void Clone(mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + void Clone(mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> clone_receiver) override { mojo::MakeSelfOwnedReceiver( - std::make_unique<FakeNativeFileSystemTransferToken>(id_), + std::make_unique<FakeFileSystemAccessTransferToken>(id_), std::move(clone_receiver)); } @@ -251,12 +251,12 @@ }; class MockNativeFileSystemContext - : public ::storage::mojom::NativeFileSystemContext { + : public ::storage::mojom::FileSystemAccessContext { public: ~MockNativeFileSystemContext() override = default; void SerializeHandle( - mojo::PendingRemote<::blink::mojom::NativeFileSystemTransferToken> + mojo::PendingRemote<::blink::mojom::FileSystemAccessTransferToken> pending_token, SerializeHandleCallback callback) override { writes_.emplace_back(std::move(pending_token)); @@ -268,20 +268,20 @@ void DeserializeHandle( const url::Origin& origin, const std::vector<uint8_t>& bits, - mojo::PendingReceiver<::blink::mojom::NativeFileSystemTransferToken> + mojo::PendingReceiver<::blink::mojom::FileSystemAccessTransferToken> token) override { NOTREACHED(); } const std::vector< - mojo::Remote<::blink::mojom::NativeFileSystemTransferToken>>& + mojo::Remote<::blink::mojom::FileSystemAccessTransferToken>>& writes() { return writes_; } void ClearWrites() { writes_.clear(); } private: - std::vector<mojo::Remote<::blink::mojom::NativeFileSystemTransferToken>> + std::vector<mojo::Remote<::blink::mojom::FileSystemAccessTransferToken>> writes_; }; @@ -547,16 +547,16 @@ IndexedDBExternalObject CreateNativeFileSystemHandle() { auto id = base::UnguessableToken::Create(); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> remote; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> remote; base::ThreadPool::CreateSequencedTaskRunner({})->PostTask( FROM_HERE, base::BindOnce( [](base::UnguessableToken id, mojo::PendingReceiver< - blink::mojom::NativeFileSystemTransferToken> + blink::mojom::FileSystemAccessTransferToken> pending_receiver) { mojo::MakeSelfOwnedReceiver( - std::make_unique<FakeNativeFileSystemTransferToken>(id), + std::make_unique<FakeFileSystemAccessTransferToken>(id), std::move(pending_receiver)); }, id, remote.InitWithNewPipeAndPassReceiver()));
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc index e053270..d11344cc 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.cc +++ b/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -122,7 +122,7 @@ base::Clock* clock, mojo::PendingRemote<storage::mojom::BlobStorageContext> blob_storage_context, - mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + mojo::PendingRemote<storage::mojom::FileSystemAccessContext> native_file_system_context, scoped_refptr<base::SequencedTaskRunner> io_task_runner, scoped_refptr<base::SequencedTaskRunner> custom_task_runner) @@ -155,11 +155,11 @@ base::BindOnce( [](mojo::Remote<storage::mojom::BlobStorageContext>* blob_storage_context, - mojo::Remote<storage::mojom::NativeFileSystemContext>* + mojo::Remote<storage::mojom::FileSystemAccessContext>* native_file_system_context, mojo::PendingRemote<storage::mojom::BlobStorageContext> pending_blob_storage_context, - mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + mojo::PendingRemote<storage::mojom::FileSystemAccessContext> pending_native_file_system_context) { if (pending_blob_storage_context) { blob_storage_context->Bind(
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h index c0b29f8..c53e4632 100644 --- a/content/browser/indexed_db/indexed_db_context_impl.h +++ b/content/browser/indexed_db/indexed_db_context_impl.h
@@ -20,9 +20,9 @@ #include "base/memory/ref_counted.h" #include "base/strings/string16.h" #include "components/services/storage/public/mojom/blob_storage_context.mojom.h" +#include "components/services/storage/public/mojom/file_system_access_context.mojom.h" #include "components/services/storage/public/mojom/indexed_db_control.mojom.h" #include "components/services/storage/public/mojom/indexed_db_control_test.mojom.h" -#include "components/services/storage/public/mojom/native_file_system_context.mojom.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_dispatcher_host.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -69,7 +69,7 @@ base::Clock* clock, mojo::PendingRemote<storage::mojom::BlobStorageContext> blob_storage_context, - mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + mojo::PendingRemote<storage::mojom::FileSystemAccessContext> native_file_system_context, scoped_refptr<base::SequencedTaskRunner> io_task_runner, scoped_refptr<base::SequencedTaskRunner> custom_task_runner); @@ -188,7 +188,7 @@ storage::mojom::BlobStorageContext* blob_storage_context() const { return blob_storage_context_ ? blob_storage_context_.get() : nullptr; } - storage::mojom::NativeFileSystemContext* native_file_system_context() const { + storage::mojom::FileSystemAccessContext* native_file_system_context() const { return native_file_system_context_ ? native_file_system_context_.get() : nullptr; } @@ -237,7 +237,7 @@ // Bound and accessed on the |idb_task_runner_|. mojo::Remote<storage::mojom::BlobStorageContext> blob_storage_context_; - mojo::Remote<storage::mojom::NativeFileSystemContext> + mojo::Remote<storage::mojom::FileSystemAccessContext> native_file_system_context_; std::unique_ptr<IndexedDBFactoryImpl> indexeddb_factory_;
diff --git a/content/browser/indexed_db/indexed_db_control_wrapper.cc b/content/browser/indexed_db/indexed_db_control_wrapper.cc index b43def3d..1ab2ffa9 100644 --- a/content/browser/indexed_db/indexed_db_control_wrapper.cc +++ b/content/browser/indexed_db/indexed_db_control_wrapper.cc
@@ -50,7 +50,7 @@ base::Clock* clock, mojo::PendingRemote<storage::mojom::BlobStorageContext> blob_storage_context, - mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + mojo::PendingRemote<storage::mojom::FileSystemAccessContext> native_file_system_context, scoped_refptr<base::SequencedTaskRunner> io_task_runner, scoped_refptr<base::SequencedTaskRunner> custom_task_runner)
diff --git a/content/browser/indexed_db/indexed_db_control_wrapper.h b/content/browser/indexed_db/indexed_db_control_wrapper.h index 9673077..80ccab30 100644 --- a/content/browser/indexed_db/indexed_db_control_wrapper.h +++ b/content/browser/indexed_db/indexed_db_control_wrapper.h
@@ -22,7 +22,7 @@ base::Clock* clock, mojo::PendingRemote<storage::mojom::BlobStorageContext> blob_storage_context, - mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + mojo::PendingRemote<storage::mojom::FileSystemAccessContext> native_file_system_context, scoped_refptr<base::SequencedTaskRunner> io_task_runner, scoped_refptr<base::SequencedTaskRunner> custom_task_runner);
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.cc b/content/browser/indexed_db/indexed_db_dispatcher_host.cc index ade99e5..b622d589b 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -261,7 +261,7 @@ return indexed_db_context_->blob_storage_context(); } -storage::mojom::NativeFileSystemContext* +storage::mojom::FileSystemAccessContext* IndexedDBDispatcherHost::native_file_system_context() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return indexed_db_context_->native_file_system_context(); @@ -444,9 +444,9 @@ break; } case IndexedDBExternalObject::ObjectType::kNativeFileSystemHandle: { - DCHECK(mojo_object->is_native_file_system_token()); + DCHECK(mojo_object->is_file_system_access_token()); - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> mojo_token; if (blob_info.is_native_file_system_remote_valid()) { @@ -458,7 +458,7 @@ origin, blob_info.native_file_system_token(), mojo_token.InitWithNewPipeAndPassReceiver()); } - mojo_object->get_native_file_system_token() = std::move(mojo_token); + mojo_object->get_file_system_access_token() = std::move(mojo_token); break; } }
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host.h b/content/browser/indexed_db/indexed_db_dispatcher_host.h index caa986d..fa47b67 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host.h +++ b/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -16,7 +16,7 @@ #include "base/sequence_checker.h" #include "base/strings/string16.h" #include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h" -#include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h" +#include "components/services/storage/public/mojom/file_system_access_context.mojom-forward.h" #include "content/browser/indexed_db/indexed_db_external_object.h" #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" @@ -102,7 +102,7 @@ friend class IndexedDBDispatcherHostTest; storage::mojom::BlobStorageContext* mojo_blob_storage_context(); - storage::mojom::NativeFileSystemContext* native_file_system_context(); + storage::mojom::FileSystemAccessContext* native_file_system_context(); // blink::mojom::IDBFactory implementation: void GetDatabaseInfo(mojo::PendingAssociatedRemote<blink::mojom::IDBCallbacks>
diff --git a/content/browser/indexed_db/indexed_db_external_object.cc b/content/browser/indexed_db/indexed_db_external_object.cc index 62ba3c32..a347438 100644 --- a/content/browser/indexed_db/indexed_db_external_object.cc +++ b/content/browser/indexed_db/indexed_db_external_object.cc
@@ -43,7 +43,7 @@ // Contents of token will be filled in later by // IndexedDBDispatcherHost::CreateAllExternalObjects. mojo_objects->push_back( - blink::mojom::IDBExternalObject::NewNativeFileSystemToken( + blink::mojom::IDBExternalObject::NewFileSystemAccessToken( mojo::NullRemote())); break; } @@ -101,7 +101,7 @@ blob_number_(blob_number) {} IndexedDBExternalObject::IndexedDBExternalObject( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote) : object_type_(ObjectType::kNativeFileSystemHandle), token_remote_(std::move(token_remote)) {}
diff --git a/content/browser/indexed_db/indexed_db_external_object.h b/content/browser/indexed_db/indexed_db_external_object.h index 868c86092..accdbdb 100644 --- a/content/browser/indexed_db/indexed_db_external_object.h +++ b/content/browser/indexed_db/indexed_db_external_object.h
@@ -65,7 +65,7 @@ const int64_t size); // These are for Native File System handles. explicit IndexedDBExternalObject( - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote); explicit IndexedDBExternalObject( std::vector<uint8_t> native_file_system_token); @@ -103,7 +103,7 @@ bool is_native_file_system_remote_valid() const { return token_remote_.is_bound(); } - blink::mojom::NativeFileSystemTransferToken* native_file_system_token_remote() + blink::mojom::FileSystemAccessTransferToken* native_file_system_token_remote() const { return token_remote_.get(); } @@ -142,7 +142,7 @@ base::Time last_modified_; // Only for Native File System handle. - mojo::SharedRemote<blink::mojom::NativeFileSystemTransferToken> token_remote_; + mojo::SharedRemote<blink::mojom::FileSystemAccessTransferToken> token_remote_; std::vector<uint8_t> native_file_system_token_; // Valid only when this comes out of the database. Only for Blob and File.
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc index dcf254bd..915d2611 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.cc +++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -779,7 +779,7 @@ const base::FilePath& blob_path, std::unique_ptr<TransactionalLevelDBDatabase> db, storage::mojom::BlobStorageContext* blob_storage_context, - storage::mojom::NativeFileSystemContext* native_file_system_context, + storage::mojom::FileSystemAccessContext* native_file_system_context, std::unique_ptr<storage::FilesystemProxy> filesystem_proxy, IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned, IndexedDBBackingStore::ReportOutstandingBlobsCallback
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.h b/content/browser/indexed_db/indexed_db_factory_impl.h index e4d9077..1f0f03a6 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.h +++ b/content/browser/indexed_db/indexed_db_factory_impl.h
@@ -25,7 +25,7 @@ #include "base/trace_event/memory_dump_provider.h" #include "components/services/storage/indexed_db/scopes/leveldb_scopes_factory.h" #include "components/services/storage/public/mojom/blob_storage_context.mojom-forward.h" -#include "components/services/storage/public/mojom/native_file_system_context.mojom-forward.h" +#include "components/services/storage/public/mojom/file_system_access_context.mojom-forward.h" #include "content/browser/indexed_db/indexed_db_backing_store.h" #include "content/browser/indexed_db/indexed_db_data_loss_info.h" #include "content/browser/indexed_db/indexed_db_database_error.h" @@ -149,7 +149,7 @@ const base::FilePath& blob_path, std::unique_ptr<TransactionalLevelDBDatabase> db, storage::mojom::BlobStorageContext* blob_storage_context, - storage::mojom::NativeFileSystemContext* native_file_system_context, + storage::mojom::FileSystemAccessContext* native_file_system_context, std::unique_ptr<storage::FilesystemProxy> filesystem_proxy, IndexedDBBackingStore::BlobFilesCleanedCallback blob_files_cleaned, IndexedDBBackingStore::ReportOutstandingBlobsCallback
diff --git a/content/browser/indexed_db/transaction_impl.cc b/content/browser/indexed_db/transaction_impl.cc index 7254b33c..9f97786 100644 --- a/content/browser/indexed_db/transaction_impl.cc +++ b/content/browser/indexed_db/transaction_impl.cc
@@ -258,9 +258,9 @@ } break; } - case blink::mojom::IDBExternalObject::Tag::NATIVE_FILE_SYSTEM_TOKEN: + case blink::mojom::IDBExternalObject::Tag::FILE_SYSTEM_ACCESS_TOKEN: (*external_objects)[i] = IndexedDBExternalObject( - std::move(object->get_native_file_system_token())); + std::move(object->get_file_system_access_token())); break; } }
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc index 08bfe138..8b00413 100644 --- a/content/browser/media/capture/frame_sink_video_capture_device.cc +++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -17,6 +17,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/surface_utils.h" #include "content/public/browser/browser_task_traits.h" @@ -120,7 +121,7 @@ constraints.fixed_aspect_ratio); if (target_.is_valid()) { - capturer_->ChangeTarget(target_); + capturer_->ChangeTarget(target_, viz::SubtreeCaptureId()); } #if !defined(OS_ANDROID) @@ -300,11 +301,10 @@ target_ = frame_sink_id; if (capturer_) { - if (target_.is_valid()) { - capturer_->ChangeTarget(target_); - } else { - capturer_->ChangeTarget(base::nullopt); - } + capturer_->ChangeTarget(target_.is_valid() + ? base::make_optional<viz::FrameSinkId>(target_) + : base::nullopt, + viz::SubtreeCaptureId()); } }
diff --git a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc index 7589cce..38dca34bd 100644 --- a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc +++ b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -101,8 +101,8 @@ const gfx::Size& max_size, bool use_fixed_aspect_ratio)); MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool)); - void ChangeTarget( - const base::Optional<viz::FrameSinkId>& frame_sink_id) final { + void ChangeTarget(const base::Optional<viz::FrameSinkId>& frame_sink_id, + const viz::SubtreeCaptureId& subtree_capture_id) final { DCHECK_NOT_ON_DEVICE_THREAD(); MockChangeTarget(frame_sink_id ? *frame_sink_id : viz::FrameSinkId()); }
diff --git a/content/browser/media/capture/slow_window_capturer_chromeos.cc b/content/browser/media/capture/slow_window_capturer_chromeos.cc index c52d00d..98014b68 100644 --- a/content/browser/media/capture/slow_window_capturer_chromeos.cc +++ b/content/browser/media/capture/slow_window_capturer_chromeos.cc
@@ -101,7 +101,8 @@ } void SlowWindowCapturerChromeOS::ChangeTarget( - const base::Optional<viz::FrameSinkId>& frame_sink_id) { + const base::Optional<viz::FrameSinkId>& frame_sink_id, + const viz::SubtreeCaptureId& subtree_capture_id) { // The SlowWindowCapturerChromeOS does not capture from compositor frame // sinks. }
diff --git a/content/browser/media/capture/slow_window_capturer_chromeos.h b/content/browser/media/capture/slow_window_capturer_chromeos.h index 6b402d1..3a2ec7f7 100644 --- a/content/browser/media/capture/slow_window_capturer_chromeos.h +++ b/content/browser/media/capture/slow_window_capturer_chromeos.h
@@ -67,8 +67,8 @@ const gfx::Size& max_size, bool use_fixed_aspect_ratio) final; void SetAutoThrottlingEnabled(bool enabled) final; - void ChangeTarget( - const base::Optional<viz::FrameSinkId>& frame_sink_id) final; + void ChangeTarget(const base::Optional<viz::FrameSinkId>& frame_sink_id, + const viz::SubtreeCaptureId& subtree_capture_id) final; void Start( mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumer> consumer) final; void Stop() final;
diff --git a/content/browser/media/session/pepper_player_delegate.cc b/content/browser/media/session/pepper_player_delegate.cc index 44b546e..d0b7f1d 100644 --- a/content/browser/media/session/pepper_player_delegate.cc +++ b/content/browser/media/session/pepper_player_delegate.cc
@@ -94,8 +94,8 @@ } void PepperPlayerDelegate::SetVolume(int player_id, double volume) { - render_frame_host_->Send(new FrameMsg_SetPepperVolume( - render_frame_host_->GetRoutingID(), pp_instance_, volume)); + static_cast<RenderFrameHostImpl*>(render_frame_host_) + ->PepperSetVolume(pp_instance_, volume); } bool PepperPlayerDelegate::HasAudio(int player_id) const {
diff --git a/content/browser/renderer_host/drop_data_util.cc b/content/browser/renderer_host/drop_data_util.cc index 4fc471b..eb507e8 100644 --- a/content/browser/renderer_host/drop_data_util.cc +++ b/content/browser/renderer_host/drop_data_util.cc
@@ -18,7 +18,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/referrer_policy.mojom-shared.h" #include "storage/browser/file_system/external_mount_points.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom.h" #include "third_party/blink/public/mojom/page/drag.mojom.h" #include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/dragdrop/file_info/file_info.h" @@ -83,8 +83,7 @@ blink::mojom::DragItemFilePtr item = blink::mojom::DragItemFile::New(); item->path = file.path; item->display_name = file.display_name; - - mojo::PendingRemote<blink::mojom::NativeFileSystemDragDropToken> + mojo::PendingRemote<blink::mojom::FileSystemAccessDragDropToken> pending_token; base::FilePath entry_path = file.path; NativeFileSystemManagerImpl::PathType path_type = @@ -92,7 +91,7 @@ native_file_system_manager->CreateNativeFileSystemDragDropToken( path_type, entry_path, child_id, pending_token.InitWithNewPipeAndPassReceiver()); - item->native_file_system_token = std::move(pending_token); + item->file_system_access_token = std::move(pending_token); items.push_back(blink::mojom::DragItem::NewFile(std::move(item))); }
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 1c0ea75..31a4513e 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -49,6 +49,7 @@ #include "content/browser/browser_main_loop.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/contacts/contacts_manager_impl.h" +#include "content/browser/coop_coep_cross_origin_isolated_info.h" #include "content/browser/data_url_loader_factory.h" #include "content/browser/devtools/devtools_instrumentation.h" #include "content/browser/devtools/protocol/audits.h" @@ -886,6 +887,8 @@ frame_host_->delegate()->OnPepperStopsPlayback(frame_host_, instance_id_); } + void SetVolume(double volume) { remote_->SetVolume(volume); } + private: int32_t const instance_id_; RenderFrameHostImpl* const frame_host_; @@ -1596,6 +1599,20 @@ return GetSiteInstance() != parent_->GetSiteInstance(); } +RenderFrameHost::CrossOriginIsolationStatus +RenderFrameHostImpl::GetCrossOriginIsolationStatus() { + ProcessLock process_lock = GetSiteInstance()->GetProcessLock(); + if (process_lock.is_invalid() || + !process_lock.coop_coep_cross_origin_isolated_info().is_isolated()) { + // Cross-origin isolated frames must be hosted in cross-origin isolated + // processes. + return RenderFrameHost::CrossOriginIsolationStatus::kNotIsolated; + } + // TODO(crbug.com/1159832): Check the document policy once it's available to + // find out if this frame is actually isolated. + return RenderFrameHost::CrossOriginIsolationStatus::kMaybeIsolated; +} + const GURL& RenderFrameHostImpl::GetLastCommittedURL() { return last_committed_url_; } @@ -8093,7 +8110,7 @@ } void RenderFrameHostImpl::GetNativeFileSystemManager( - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver) { + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) { DCHECK_CURRENTLY_ON(BrowserThread::UI); auto* storage_partition = static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition()); @@ -10220,6 +10237,13 @@ delegate()->OnPepperInstanceDeleted(this, instance_id); pepper_instance_map_.erase(instance_id); } + +void RenderFrameHostImpl::PepperSetVolume(int32_t instance_id, double volume) { + auto plugin_instance_host = pepper_instance_map_.find(instance_id); + DCHECK(plugin_instance_host != pepper_instance_map_.end()); + plugin_instance_host->second->SetVolume(volume); +} + #endif // BUILDFLAG(ENABLE_PLUGINS) void RenderFrameHostImpl::OnCookiesAccessed(
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 3dbe9e5..2166f90 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -107,7 +107,7 @@ #include "third_party/blink/public/mojom/devtools/devtools_agent.mojom.h" #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-forward.h" #include "third_party/blink/public/mojom/font_access/font_access.mojom.h" #include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom.h" #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h" @@ -320,6 +320,7 @@ const base::Optional<gfx::Size>& GetFrameSize() override; size_t GetFrameDepth() override; bool IsCrossProcessSubframe() override; + CrossOriginIsolationStatus GetCrossOriginIsolationStatus() override; const GURL& GetLastCommittedURL() override; const url::Origin& GetLastCommittedOrigin() override; const net::NetworkIsolationKey& GetNetworkIsolationKey() override; @@ -1351,7 +1352,7 @@ mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver); void GetNativeFileSystemManager( - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver); + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver); #if !defined(OS_ANDROID) void GetHidService(mojo::PendingReceiver<blink::mojom::HidService> receiver); @@ -1882,6 +1883,7 @@ #if BUILDFLAG(ENABLE_PLUGINS) void PepperInstanceClosed(int32_t instance_id); + void PepperSetVolume(int32_t instance_id, double volume); #endif protected:
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc index 3406857..0fe24ca 100644 --- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -6360,4 +6360,21 @@ web_contents()->GetFaviconURLs()[0]->icon_url.path()); } +IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, + GetCrossOriginIsolationStatus) { + EXPECT_TRUE( + NavigateToURL(shell(), embedded_test_server()->GetURL("/empty.html"))); + EXPECT_EQ(RenderFrameHost::CrossOriginIsolationStatus::kNotIsolated, + root_frame_host()->GetCrossOriginIsolationStatus()); + + EXPECT_TRUE(NavigateToURL(shell(), + embedded_test_server()->GetURL( + "/set-header?" + "Cross-Origin-Opener-Policy: same-origin&" + "Cross-Origin-Embedder-Policy: require-corp"))); + // Status can be kIsolated or kMaybeIsolated. + EXPECT_NE(RenderFrameHost::CrossOriginIsolationStatus::kNotIsolated, + root_frame_host()->GetCrossOriginIsolationStatus()); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index b5e34e7..b3d7f24 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1987,7 +1987,7 @@ void RenderProcessHostImpl::BindNativeFileSystemManager( const url::Origin& origin, - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver) { + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // This code path is only for workers, hence always pass in // MSG_ROUTING_NONE as frame ID. Frames themselves go through
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 7cef8b1..e2b3d5f 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -553,7 +553,7 @@ // render process host, and is used by workers via BrowserInterfaceBroker. void BindNativeFileSystemManager( const url::Origin& origin, - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver) + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) override; // Binds |receiver| to a NativeIOHost instance indirectly owned by the
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 380df39e..3118dfd 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -111,7 +111,6 @@ #include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/common/web_preferences/web_preferences.h" #include "third_party/blink/public/common/widget/visual_properties.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom.h" #include "third_party/blink/public/mojom/input/touch_event.mojom.h" #include "third_party/blink/public/mojom/page/drag.mojom.h" #include "ui/base/clipboard/clipboard_constants.h"
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index e8c6d3e8..7a90002e 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -9,6 +9,7 @@ #include "base/unguessable_token.h" #include "build/build_config.h" #include "components/viz/common/features.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/gpu/gpu_data_manager_impl.h" @@ -275,7 +276,7 @@ RenderWidgetHostViewBase::CreateVideoCapturer() { std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer = GetHostFrameSinkManager()->CreateVideoCapturer(); - video_capturer->ChangeTarget(GetFrameSinkId()); + video_capturer->ChangeTarget(GetFrameSinkId(), viz::SubtreeCaptureId()); return video_capturer; }
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 92225b5..a23458b 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -1208,7 +1208,7 @@ browser_context_->GetNativeFileSystemPermissionContext(), browser_context_->IsOffTheRecord()); - mojo::PendingRemote<storage::mojom::NativeFileSystemContext> + mojo::PendingRemote<storage::mojom::FileSystemAccessContext> native_file_system_context; native_file_system_manager_->BindInternalsReceiver( native_file_system_context.InitWithNewPipeAndPassReceiver());
diff --git a/content/browser/worker_host/worker_browsertest.cc b/content/browser/worker_host/worker_browsertest.cc index fd8fe59..9e0ca78 100644 --- a/content/browser/worker_host/worker_browsertest.cc +++ b/content/browser/worker_host/worker_browsertest.cc
@@ -335,6 +335,8 @@ shell()->web_contents()->GetMainFrame()); auto page_lock = page_rfh->GetSiteInstance()->GetProcessLock(); EXPECT_TRUE(page_lock.coop_coep_cross_origin_isolated_info().is_isolated()); + EXPECT_NE(page_rfh->GetCrossOriginIsolationStatus(), + RenderFrameHost::CrossOriginIsolationStatus::kNotIsolated); // Create a shared worker from the cross-origin-isolated page. // The worker must be in a different process because shared workers isn't
diff --git a/content/common/content_param_traits.cc b/content/common/content_param_traits.cc index 20ef2f8..d63050c 100644 --- a/content/common/content_param_traits.cc +++ b/content/common/content_param_traits.cc
@@ -178,12 +178,12 @@ template <> struct ParamTraits< - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken>> { + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken>> { using param_type = - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken>; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken>; static void Write(base::Pickle* m, const param_type& p) { // Move the Mojo pipe to serialize the - // PendingRemote<NativeFileSystemTransferToken> for a postMessage() target. + // PendingRemote<FileSystemAccessTransferToken> for a postMessage() target. WriteParam(m, const_cast<param_type&>(p).PassPipe().release()); } @@ -194,9 +194,9 @@ if (!ReadParam(m, iter, &handle)) { return false; } - *r = mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken>( + *r = mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken>( mojo::ScopedMessagePipeHandle(handle), - blink::mojom::NativeFileSystemTransferToken::Version_); + blink::mojom::FileSystemAccessTransferToken::Version_); return true; } };
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index d6665b5..c3862de86e 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -244,14 +244,6 @@ content::CustomContextMenuContext /* custom_context */, unsigned /* action */) -#if BUILDFLAG(ENABLE_PLUGINS) -// This message notifies that the frame that the volume of the Pepper instance -// for |pp_instance| should be changed to |volume|. -IPC_MESSAGE_ROUTED2(FrameMsg_SetPepperVolume, - int32_t /* pp_instance */, - double /* volume */) -#endif // BUILDFLAG(ENABLE_PLUGINS) - // ----------------------------------------------------------------------------- // Messages sent from the renderer to the browser.
diff --git a/content/common/pepper_plugin.mojom b/content/common/pepper_plugin.mojom index eab70efe..bcd7ac3 100644 --- a/content/common/pepper_plugin.mojom +++ b/content/common/pepper_plugin.mojom
@@ -23,4 +23,6 @@ // Plugin instance specific messages. Implemented by the renderer. interface PepperPluginInstance { + // Set the volume of a plugin. |volume| should be in the [0, 1] range. + SetVolume(double volume); };
diff --git a/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePort.java b/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePort.java index 6c4f3d6e..d7907fb 100644 --- a/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePort.java +++ b/content/public/android/java/src/org/chromium/content/browser/AppWebMessagePort.java
@@ -12,8 +12,8 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; import org.chromium.blink.mojom.CloneableMessage; +import org.chromium.blink.mojom.FileSystemAccessTransferToken; import org.chromium.blink.mojom.MessagePortDescriptor; -import org.chromium.blink.mojom.NativeFileSystemTransferToken; import org.chromium.blink.mojom.SerializedArrayBufferContents; import org.chromium.blink.mojom.SerializedBlob; import org.chromium.blink.mojom.TransferableMessage; @@ -296,7 +296,7 @@ msg.message.encodedMessage = BigBufferUtil.createBigBufferFromBytes( AppWebMessagePortJni.get().encodeStringMessage(message)); msg.message.blobs = new SerializedBlob[0]; - msg.message.nativeFileSystemTokens = new NativeFileSystemTransferToken[0]; + msg.message.fileSystemAccessTokens = new FileSystemAccessTransferToken[0]; msg.message.senderOrigin = null; msg.arrayBufferContentsArray = new SerializedArrayBufferContents[0]; msg.imageBitmapContentsArray = new BitmapN32[0];
diff --git a/content/public/browser/native_file_system_entry_factory.h b/content/public/browser/native_file_system_entry_factory.h index bd54a9f6..4ec6369 100644 --- a/content/public/browser/native_file_system_entry_factory.h +++ b/content/public/browser/native_file_system_entry_factory.h
@@ -12,13 +12,13 @@ #include "content/public/browser/global_routing_id.h" #include "content/public/browser/native_file_system_permission_context.h" #include "ipc/ipc_message.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-forward.h" #include "url/gurl.h" #include "url/origin.h" namespace content { -// Exposes methods for creating NativeFileSystemEntries. All these methods need +// Exposes methods for creating FileSystemAccessEntries. All these methods need // to be called on the UI thread. class CONTENT_EXPORT NativeFileSystemEntryFactory : public base::RefCountedThreadSafe<NativeFileSystemEntryFactory, @@ -49,17 +49,17 @@ int process_id() const { return frame_id.child_id; } }; - // Creates a new NativeFileSystemEntryPtr from the path to a file. Assumes the + // Creates a new FileSystemAccessEntryPtr from the path to a file. Assumes the // passed in path is valid and represents a file. - virtual blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPath( + virtual blink::mojom::FileSystemAccessEntryPtr CreateFileEntryFromPath( const BindingContext& binding_context, PathType path_type, const base::FilePath& file_path, UserAction user_action) = 0; - // Creates a new NativeFileSystemEntryPtr from the path to a directory. + // Creates a new FileSystemAccessEntryPtr from the path to a directory. // Assumes the passed in path is valid and represents a directory. - virtual blink::mojom::NativeFileSystemEntryPtr CreateDirectoryEntryFromPath( + virtual blink::mojom::FileSystemAccessEntryPtr CreateDirectoryEntryFromPath( const BindingContext& binding_context, PathType path_type, const base::FilePath& directory_path,
diff --git a/content/public/browser/native_file_system_permission_context.h b/content/public/browser/native_file_system_permission_context.h index 6de71430..0e6f377 100644 --- a/content/public/browser/native_file_system_permission_context.h +++ b/content/public/browser/native_file_system_permission_context.h
@@ -9,7 +9,7 @@ #include "content/public/browser/global_routing_id.h" #include "content/public/browser/native_file_system_permission_grant.h" #include "content/public/browser/native_file_system_write_item.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-shared.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-shared.h" #include "url/origin.h" namespace content {
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h index 8ba4627..3fe45b61 100644 --- a/content/public/browser/render_frame_host.h +++ b/content/public/browser/render_frame_host.h
@@ -251,6 +251,61 @@ // Returns true if the frame is out of process. virtual bool IsCrossProcessSubframe() = 0; + // Indicates whether this frame is in a cross-origin isolated agent cluster. + // See [1] and [2] for a description of what this means for web content. + // Specifically, an agent cluster may be cross-origin isolated if: + // - its top-level document has "Cross-Origin-Opener-Policy: same-origin" and + // "Cross-Origin-Embedder-Policy: require-corp" HTTP headers; or, + // - its top-level worker script has a + // "Cross-Origin-Embedder-Policy: require-corp" HTTP header. + // + // In practice this means that the frame is guaranteed to be hosted in a + // process that is isolated to the frame's origin. The process may also host + // cross-origin frames and workers only if they have opted in to being + // embedded with CORS or CORP headers. + // + // Certain advanced web platform APIs are gated behind this property. It will + // correspond to the value returned by accessing + // "WindowOrWorkerGlobalScope.crossOriginIsolated" in Javascript. + // + // NOTE: some of the information needed to fully determine a frame's + // cross-isolation status is currently not available in the browser process. + // Access to web platform API's must be checked in the renderer, with the + // CrossOriginIsolationStatus on the browser side only used as a backup to + // catch misbehaving renderers. + // + // [1] + // https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/crossOriginIsolated + // [2] https://w3c.github.io/webappsec-permissions-policy/ + enum class CrossOriginIsolationStatus { + // The frame is in a cross-origin isolated process and agent cluster. + // It is allowed to call web platform API's gated behind the + // crossOriginIsolated property. + kIsolated, + + // The frame is not in a cross-origin isolated agent cluster. It may be + // hosted in a cross-origin isolated process but it is not allowed to call + // web platform API's gated behind the crossOriginIsolated property. + kNotIsolated, + + // The frame is in a cross-origin isolated process, but it's not possible + // to determine whether it's in a cross-origin isolated agent cluster. The + // browser process should not prevent it from calling web platform API's + // gated behind the crossOriginIsolated property because it may be allowed. + // TODO(clamy): Remove this status once the document policy is available on + // the browser side. + kMaybeIsolated, + }; + + // Returns whether the frame is in a cross-origin isolated agent cluster. + // + // Note that this is a property of the document so can change as the frame + // navigates. + // + // TODO(https://936696): Once RenderDocument ships this should be exposed as + // an invariant of the document host. + virtual CrossOriginIsolationStatus GetCrossOriginIsolationStatus() = 0; + // Returns the last committed URL of the frame. virtual const GURL& GetLastCommittedURL() = 0;
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index 1c0c0de..ef51dcc 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h
@@ -35,7 +35,7 @@ #include "third_party/blink/public/mojom/appcache/appcache.mojom.h" #include "third_party/blink/public/mojom/background_sync/background_sync.mojom.h" #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom-forward.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-forward.h" #include "third_party/blink/public/mojom/filesystem/file_system.mojom-forward.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-forward.h" #include "third_party/blink/public/mojom/locks/lock_manager.mojom-forward.h" @@ -487,7 +487,7 @@ mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver) = 0; virtual void BindNativeFileSystemManager( const url::Origin& origin, - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) = 0; // |render_frame_id| is the frame associated with |receiver|, or
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index 859a361..4630d2a 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -176,7 +176,7 @@ override {} void BindNativeFileSystemManager( const url::Origin& origin, - mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver) + mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) override {} void BindIndexedDB( const url::Origin& origin,
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index 777978c2..e230aafc 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -3175,4 +3175,8 @@ composition_text_.clear(); } +void PepperPluginInstanceImpl::SetVolume(double volume) { + audio_controller().SetVolume(volume); +} + } // namespace content
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h index 4cb7ef06..c9d08a2 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -497,6 +497,9 @@ // Delete should be called by the WebPlugin before this destructor. ~PepperPluginInstanceImpl() override; + // mojom::PepperPluginInstance overrides: + void SetVolume(double volume) override; + // Class to record document load notifications and play them back once the // real document loader becomes available. Used only by external instances. class ExternalDocumentLoader : public blink::WebAssociatedURLLoaderClient {
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index bc421a3..4ea1b2f 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -2179,9 +2179,6 @@ IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed) IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction, OnCustomContextMenuAction) -#if BUILDFLAG(ENABLE_PLUGINS) - IPC_MESSAGE_HANDLER(FrameMsg_SetPepperVolume, OnSetPepperVolume) -#endif IPC_MESSAGE_HANDLER(UnfreezableFrameMsg_Delete, OnDeleteFrame) IPC_END_MESSAGE_MAP() @@ -6290,12 +6287,6 @@ GetLocalRootWebFrameWidget()->UpdateSelectionBounds(); } -void RenderFrameImpl::OnSetPepperVolume(int32_t pp_instance, double volume) { - PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( - PepperPluginInstance::Get(pp_instance)); - if (instance) - instance->audio_controller().SetVolume(volume); -} #endif // ENABLE_PLUGINS blink::WebComputedAXTree* RenderFrameImpl::GetOrCreateWebComputedAXTree() {
diff --git a/content/test/data/accessibility/html/iframe-coordinates-cross-process-expected-mac.txt b/content/test/data/accessibility/html/iframe-coordinates-cross-process-expected-mac.txt index 6a54699..0cfe194 100644 --- a/content/test/data/accessibility/html/iframe-coordinates-cross-process-expected-mac.txt +++ b/content/test/data/accessibility/html/iframe-coordinates-cross-process-expected-mac.txt
@@ -1,15 +1,15 @@ -AXWebArea position=(0, 0) AXSize={h: 600, w: 800} -++AXGroup position=(0, 0) AXSize={h: 150, w: 300} -++++AXButton position=(25, 25) AXSize={h: 50, w: 250} -++AXGroup position=(0, 150) AXSize={h: 150, w: 300} -++++AXButton position=(25, 175) AXSize={h: 50, w: 250} -++AXGroup position=(0, 300) AXSize={h: 150, w: 300} -++++AXGroup position=(0, 300) AXSize={h: 100, w: 300} -++++++AXWebArea position=(0, 300) AXSize={h: 100, w: 300} -++++++++AXGroup position=(0, 300) AXSize={h: 100, w: 300} -++++++++++AXButton position=(25, 325) AXSize={h: 50, w: 250} -++AXGroup position=(0, 450) AXSize={h: 150, w: 300} -++++AXGroup position=(0, 450) AXSize={h: 50, w: 150} -++++++AXWebArea position=(0, 450) AXSize={h: 50, w: 150} -++++++++AXGroup position=(0, 450) AXSize={h: 50, w: 150} -++++++++++AXButton position=(0, 450) AXSize={h: 25, w: 125} \ No newline at end of file +AXWebArea AXSize={h: 600, w: 800} LocalPosition={x: 0, y: 0} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 0} +++++AXButton AXSize={h: 50, w: 250} LocalPosition={x: 25, y: 25} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 150} +++++AXButton AXSize={h: 50, w: 250} LocalPosition={x: 25, y: 175} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 300} +++++AXGroup AXSize={h: 100, w: 300} LocalPosition={x: 0, y: 300} +++++++AXWebArea AXSize={h: 100, w: 300} LocalPosition={x: 0, y: 300} +++++++++AXGroup AXSize={h: 100, w: 300} LocalPosition={x: 0, y: 300} +++++++++++AXButton AXSize={h: 50, w: 250} LocalPosition={x: 25, y: 325} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 450} +++++AXGroup AXSize={h: 50, w: 150} LocalPosition={x: 0, y: 450} +++++++AXWebArea AXSize={h: 50, w: 150} LocalPosition={x: 0, y: 450} +++++++++AXGroup AXSize={h: 50, w: 150} LocalPosition={x: 0, y: 450} +++++++++++AXButton AXSize={h: 25, w: 125} LocalPosition={x: 0, y: 450} \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-coordinates-cross-process.html b/content/test/data/accessibility/html/iframe-coordinates-cross-process.html index d2b2491..134c669 100644 --- a/content/test/data/accessibility/html/iframe-coordinates-cross-process.html +++ b/content/test/data/accessibility/html/iframe-coordinates-cross-process.html
@@ -1,7 +1,7 @@ <!-- @MAC-DENY:AXTitle @MAC-DENY:AXValue -@MAC-ALLOW:position* +@MAC-ALLOW:LocalPosition @MAC-ALLOW:AXSize @WIN-DENY:title*
diff --git a/content/test/data/accessibility/html/iframe-coordinates-expected-mac.txt b/content/test/data/accessibility/html/iframe-coordinates-expected-mac.txt index 205cd1b..3a362e1c 100644 --- a/content/test/data/accessibility/html/iframe-coordinates-expected-mac.txt +++ b/content/test/data/accessibility/html/iframe-coordinates-expected-mac.txt
@@ -1,15 +1,15 @@ -AXWebArea AXSize={h: 600, w: 800} position=(0, 0) -++AXGroup AXSize={h: 150, w: 300} position=(0, 0) -++++AXButton AXSize={h: 50, w: 250} position=(25, 25) -++AXGroup AXSize={h: 150, w: 300} position=(0, 150) -++++AXButton AXSize={h: 50, w: 250} position=(25, 175) -++AXGroup AXSize={h: 150, w: 300} position=(0, 300) -++++AXGroup AXSize={h: 100, w: 300} position=(0, 300) -++++++AXWebArea AXSize={h: 100, w: 300} position=(0, 300) -++++++++AXGroup AXSize={h: 100, w: 300} position=(0, 300) -++++++++++AXButton AXSize={h: 50, w: 250} position=(25, 325) -++AXGroup AXSize={h: 150, w: 300} position=(0, 450) -++++AXGroup AXSize={h: 50, w: 150} position=(0, 450) -++++++AXWebArea AXSize={h: 50, w: 150} position=(0, 450) -++++++++AXGroup AXSize={h: 50, w: 150} position=(0, 450) -++++++++++AXButton AXSize={h: 25, w: 125} position=(0, 450) +AXWebArea AXSize={h: 600, w: 800} LocalPosition={x: 0, y: 0} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 0} +++++AXButton AXSize={h: 50, w: 250} LocalPosition={x: 25, y: 25} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 150} +++++AXButton AXSize={h: 50, w: 250} LocalPosition={x: 25, y: 175} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 300} +++++AXGroup AXSize={h: 100, w: 300} LocalPosition={x: 0, y: 300} +++++++AXWebArea AXSize={h: 100, w: 300} LocalPosition={x: 0, y: 300} +++++++++AXGroup AXSize={h: 100, w: 300} LocalPosition={x: 0, y: 300} +++++++++++AXButton AXSize={h: 50, w: 250} LocalPosition={x: 25, y: 325} +++AXGroup AXSize={h: 150, w: 300} LocalPosition={x: 0, y: 450} +++++AXGroup AXSize={h: 50, w: 150} LocalPosition={x: 0, y: 450} +++++++AXWebArea AXSize={h: 50, w: 150} LocalPosition={x: 0, y: 450} +++++++++AXGroup AXSize={h: 50, w: 150} LocalPosition={x: 0, y: 450} +++++++++++AXButton AXSize={h: 25, w: 125} LocalPosition={x: 0, y: 450}
diff --git a/content/test/data/accessibility/html/iframe-coordinates.html b/content/test/data/accessibility/html/iframe-coordinates.html index 3632d213..d55f49a 100644 --- a/content/test/data/accessibility/html/iframe-coordinates.html +++ b/content/test/data/accessibility/html/iframe-coordinates.html
@@ -1,7 +1,7 @@ <!-- @MAC-DENY:AXTitle @MAC-DENY:AXValue -@MAC-ALLOW:position* +@MAC-ALLOW:LocalPosition @MAC-ALLOW:AXSize @WIN-DENY:title*
diff --git a/content/test/data/direct_sockets/index.html b/content/test/data/direct_sockets/index.html index ff23bfa..6d3d86b0 100644 --- a/content/test/data/direct_sockets/index.html +++ b/content/test/data/direct_sockets/index.html
@@ -8,7 +8,9 @@ async function openTcp(options) { try { let tcpSocket = await navigator.openTCPSocket(options); - return 'openTcp succeeded'; + return ('openTcp succeeded: ' + + '{remoteAddress: "' + tcpSocket.remoteAddress + + '", remotePort: ' + tcpSocket.remotePort + '}'); } catch(error) { return ('openTcp failed: ' + error); }
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 605699c..4df2d426 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -175,6 +175,7 @@ crbug.com/883500 [ android-chromium android-nexus-5x ] Pixel_BackgroundImage [ RetryOnFailure ] crbug.com/1065514 [ android android-chromium android-nexus-5x ] Pixel_WebGLReadPixelsTabSwitch [ RetryOnFailure ] crbug.com/1121476 [ android android-chromium android-nexus-5x ] Pixel_Canvas2DTabSwitch [ RetryOnFailure ] +crbug.com/1157136 [ android android-chromium android-nexus-5x skia-renderer-disabled ] Pixel_OffscreenCanvasWebGLDefault [ RetryOnFailure ] # We do not have software H.264 decoding on Android, so it can't survive a # context loss which results in hardware decoder loss.
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h index 8ccb918..602fc7e 100644 --- a/device/fido/fido_request_handler_base.h +++ b/device/fido/fido_request_handler_base.h
@@ -72,7 +72,12 @@ // relying party. base::flat_set<FidoTransportProtocol> available_transports; - bool has_recognized_mac_touch_id_credential = false; + // Whether the platform authenticator has a matching credential for the + // request. This is only set for a GetAssertion request and if a platform + // authenticator has been added to the request handler. (The Windows + // WebAuthn API does NOT count as a platform authenticator in this case.) + base::Optional<bool> has_recognized_platform_authenticator_credential; + bool is_ble_powered = false; bool can_power_on_ble_adapter = false;
diff --git a/device/fido/fido_request_handler_unittest.cc b/device/fido/fido_request_handler_unittest.cc index e54967f..ef3b2b7 100644 --- a/device/fido/fido_request_handler_unittest.cc +++ b/device/fido/fido_request_handler_unittest.cc
@@ -82,15 +82,12 @@ void WaitForAndExpectAvailableTransportsAre( base::flat_set<FidoTransportProtocol> expected_transports, - base::Optional<bool> has_recognized_mac_touch_id_credential = - base::nullopt) { + base::Optional<bool> has_platform_credential = base::nullopt) { auto result = WaitForTransportAvailabilityInfo(); EXPECT_THAT(result.available_transports, ::testing::UnorderedElementsAreArray(expected_transports)); - if (has_recognized_mac_touch_id_credential) { - EXPECT_EQ(*has_recognized_mac_touch_id_credential, - result.has_recognized_mac_touch_id_credential); - } + EXPECT_EQ(result.has_recognized_platform_authenticator_credential, + has_platform_credential); } protected: @@ -205,6 +202,11 @@ } ~FakeFidoRequestHandler() override = default; + void set_has_platform_credential(bool has_platform_credential) { + has_platform_credential_ = has_platform_credential; + } + + private: void DispatchRequest(FidoAuthenticator* authenticator) override { // FidoRequestHandlerTest uses FakeDiscovery to inject mock devices // that get wrapped in a FidoDeviceAuthenticator, so we can safely cast @@ -220,7 +222,18 @@ weak_factory_.GetWeakPtr(), authenticator))); } - private: + void AuthenticatorAdded(FidoDiscoveryBase* discovery, + FidoAuthenticator* authenticator) override { + if (authenticator->AuthenticatorTransport() == + FidoTransportProtocol::kInternal) { + transport_availability_info() + .has_recognized_platform_authenticator_credential = + has_platform_credential_; + } + + FidoRequestHandlerBase::AuthenticatorAdded(discovery, authenticator); + } + void HandleResponse(FidoAuthenticator* authenticator, CtapDeviceResponseCode status, base::Optional<std::vector<uint8_t>> response) { @@ -246,6 +259,8 @@ } CompletionCallback completion_callback_; + bool has_platform_credential_ = false; + base::WeakPtrFactory<FakeFidoRequestHandler> weak_factory_{this}; }; @@ -567,12 +582,13 @@ &fake_discovery_factory_, base::flat_set<FidoTransportProtocol>({FidoTransportProtocol::kInternal}), callback().callback()); + request_handler->set_has_platform_credential(true); request_handler->set_observer(&observer); fake_discovery->AddDevice(std::move(device)); observer.WaitForAndExpectAvailableTransportsAre( {FidoTransportProtocol::kInternal}, - false /* has_recognized_mac_touch_id_credential */); + /*has_platform_credential=*/true); callback().WaitForCallback(); EXPECT_TRUE(callback().status());
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index 9dbc4d4..5cf550d 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -387,17 +387,21 @@ // or not. This needs to happen before the base AuthenticatorAdded() // implementation runs |notify_observer_callback_| for this callback. if (authenticator->IsTouchIdAuthenticator()) { - transport_availability_info().has_recognized_mac_touch_id_credential = + DCHECK(!transport_availability_info() + .has_recognized_platform_authenticator_credential.has_value()); + transport_availability_info() + .has_recognized_platform_authenticator_credential = static_cast<fido::mac::TouchIdAuthenticator*>(authenticator) ->HasCredentialForGetAssertionRequest(request_); } #endif // defined(OS_MAC) #if BUILDFLAG(IS_CHROMEOS_ASH) - // TODO(martinkr): Put this boolean in a ChromeOS equivalent of - // "has_recognized_mac_touch_id_credential". if (authenticator->IsChromeOSAuthenticator()) { - transport_availability_info().has_recognized_mac_touch_id_credential = + DCHECK(!transport_availability_info() + .has_recognized_platform_authenticator_credential.has_value()); + transport_availability_info() + .has_recognized_platform_authenticator_credential = static_cast<ChromeOSAuthenticator*>(authenticator) ->HasCredentialForGetAssertionRequest(request_); }
diff --git a/docs/gpu/gpu_testing_bot_details.md b/docs/gpu/gpu_testing_bot_details.md index a5a4eff..fe3240c 100644 --- a/docs/gpu/gpu_testing_bot_details.md +++ b/docs/gpu/gpu_testing_bot_details.md
@@ -468,6 +468,23 @@ add a manually-triggered trybot at the same time that the CI bot is added. This is described in [How to add a new manually-triggered trybot]. +While the above instructions assume that an existing parent builder will be +be used, a new one can be set up by performing a modified version of the steps: + +1. Make a [`tools/build`][tools/build] CL that adds the config for *only* the + new builder and land it. +1. Make and land Chromium CL that makes the above changes in addition to the + following: + 1. Add the new builder to the necessary `//infra/config` files in the same + way as the tester. + 1. Add the new builder to [`src/tools/mb/mb_config.pyl`][mb_config.pyl]. +1. Make a [`tools/build`][tools/build] CL that adds the config for *only* the + new tester and land it. + +Attempting to set up the builder/tester pair without first landing the +[`tools/build`][tools/build] CL for the new builder will result in things +breaking as seen in [this bug][misconfigured builder bug]. + [How to add a new manually-triggered trybot]: https://chromium.googlesource.com/chromium/src/+/master/docs/gpu/gpu_testing_bot_details.md#How-to-add-a-new-manually_triggered-trybot [ci.star]: https://chromium.googlesource.com/chromium/src/+/master/infra/config/subprojects/ci.star @@ -477,6 +494,7 @@ [luci-scheduler.cfg]: https://chromium.googlesource.com/chromium/src/+/master/infra/config/generated/luci-scheduler.cfg [luci-milo.cfg]: https://chromium.googlesource.com/chromium/src/+/master/infra/config/generated/luci-milo.cfg [GPU FYI Win Builder]: https://ci.chromium.org/p/chromium/builders/luci.chromium.ci/GPU%20FYI%20Win%20Builder +[misconfigured builder bug]: https://bugs.chromium.org/p/chromium/issues/detail?id=1163657 ### How to start running tests on a new GPU type on an existing try bot
diff --git a/docs/win_cross.md b/docs/win_cross.md index 790f78c..560b4e0 100644 --- a/docs/win_cross.md +++ b/docs/win_cross.md
@@ -86,18 +86,11 @@ **Warning:** This is unsupported and known to not work at times. *** -For now, one needs to use the rbe backend, not the borg backend -(default for Googlers). -Use cloud backend instead. +This should be supported by the default (rbe) backend. However, there may be +issues with arbitrary toolchain support on Linux. This can be disabled via: ```shell - goma_auth.py login - - # GOMA_* are needed for Googlers only - export GOMA_SERVER_HOST=goma.chromium.org - export GOMA_RPC_EXTRA_PARAMS=?rbe - - goma_ctl.py ensure_start +GOMA_ARBITRARY_TOOLCHAIN_SUPPORT=false goma_ctl restart ```
diff --git a/extensions/browser/test_extensions_browser_client.cc b/extensions/browser/test_extensions_browser_client.cc index e8f34046..d5b64e58 100644 --- a/extensions/browser/test_extensions_browser_client.cc +++ b/extensions/browser/test_extensions_browser_client.cc
@@ -35,8 +35,8 @@ TestExtensionsBrowserClient::~TestExtensionsBrowserClient() = default; void TestExtensionsBrowserClient::SetUpdateClientFactory( - const base::Callback<update_client::UpdateClient*(void)>& factory) { - update_client_factory_ = factory; + base::RepeatingCallback<update_client::UpdateClient*(void)> factory) { + update_client_factory_ = std::move(factory); } void TestExtensionsBrowserClient::SetMainContext(
diff --git a/extensions/browser/test_extensions_browser_client.h b/extensions/browser/test_extensions_browser_client.h index 968af0b..b160e91 100644 --- a/extensions/browser/test_extensions_browser_client.h +++ b/extensions/browser/test_extensions_browser_client.h
@@ -55,7 +55,7 @@ // Sets a factory to respond to calls of the CreateUpdateClient method. void SetUpdateClientFactory( - const base::Callback<update_client::UpdateClient*(void)>& factory); + base::RepeatingCallback<update_client::UpdateClient*(void)> factory); // Sets the main browser context. Only call if a BrowserContext was not // already provided. |main_context| must not be an incognito context. @@ -168,7 +168,8 @@ std::unique_ptr<ExtensionCache> extension_cache_; - base::Callback<update_client::UpdateClient*(void)> update_client_factory_; + base::RepeatingCallback<update_client::UpdateClient*(void)> + update_client_factory_; }; } // namespace extensions
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc index a8a5fd5..bc477eda 100644 --- a/extensions/renderer/api/automation/automation_internal_custom_bindings.cc +++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.cc
@@ -675,6 +675,7 @@ ROUTE_FUNCTION(GetState); ROUTE_FUNCTION(CreateAutomationPosition); ROUTE_FUNCTION(GetAccessibilityFocus); + ROUTE_FUNCTION(SetDesktopID); #undef ROUTE_FUNCTION // Bindings that take a Tree ID and return a property of the tree. @@ -1913,26 +1914,33 @@ void AutomationInternalCustomBindings::GetFocus( const v8::FunctionCallbackInfo<v8::Value>& args) { - if (args.Length() != 1 || !args[0]->IsString()) { + if (args.Length() != 0) { ThrowInvalidArgumentsException(this); return; } - ui::AXTreeID tree_id = ui::AXTreeID::FromString( - *v8::String::Utf8Value(args.GetIsolate(), args[0])); - AutomationAXTreeWrapper* tree_wrapper = - GetAutomationAXTreeWrapperFromTreeID(tree_id); - if (!tree_wrapper) + AutomationAXTreeWrapper* desktop_tree = + GetAutomationAXTreeWrapperFromTreeID(desktop_tree_id_); + AutomationAXTreeWrapper* focused_wrapper = nullptr; + ui::AXNode* focused_node = nullptr; + if (desktop_tree && + !GetFocusInternal(desktop_tree, &focused_wrapper, &focused_node)) return; - AutomationAXTreeWrapper* focused_tree_wrapper = nullptr; - ui::AXNode* focused_node = nullptr; - if (!GetFocusInternal(tree_wrapper, &focused_tree_wrapper, &focused_node)) - return; + if (!desktop_tree) { + focused_wrapper = GetAutomationAXTreeWrapperFromTreeID(focus_tree_id_); + if (!focused_wrapper) + return; + + focused_node = focused_wrapper->GetNodeFromTree( + focused_wrapper->GetTreeID(), focus_id_); + if (!focused_node) + return; + } args.GetReturnValue().Set( gin::DataObjectBuilder(GetIsolate()) - .Set("treeId", focused_tree_wrapper->GetTreeID().ToString()) + .Set("treeId", focused_wrapper->GetTreeID().ToString()) .Set("nodeId", focused_node->id()) .Build()); } @@ -1955,6 +1963,17 @@ .Build()); } +void AutomationInternalCustomBindings::SetDesktopID( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsString()) { + ThrowInvalidArgumentsException(this); + return; + } + + desktop_tree_id_ = ui::AXTreeID::FromString( + *v8::String::Utf8Value(args.GetIsolate(), args[0])); +} + void AutomationInternalCustomBindings::GetHtmlAttributes( const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Isolate* isolate = GetIsolate(); @@ -2522,32 +2541,43 @@ bool lost_old_focus = old_node == nullptr; // Determine whether there's a focus or blur event and take its event from. + // Also, save the raw event target (tree + node). ax::mojom::EventFrom event_from = ax::mojom::EventFrom::kNone; - bool event_bundle_has_focus_or_blur; + ui::AXNodeData::AXID raw_focus_target_id = ui::AXNodeData::kInvalidAXID; + bool event_bundle_has_focus_or_blur = false; for (const auto& event : event_bundle.events) { - if (event.event_type == ax::mojom::Event::kBlur || - event.event_type == ax::mojom::Event::kFocus) { + bool is_blur = event.event_type == ax::mojom::Event::kBlur; + bool is_focus = event.event_type == ax::mojom::Event::kFocus; + if (is_blur || is_focus) { event_from = event.event_from; event_bundle_has_focus_or_blur = true; - break; } + + if (is_focus) + raw_focus_target_id = event.id; } bool is_from_desktop = tree->IsDesktopTree(); if (!event_bundle_has_focus_or_blur && !lost_old_focus && !is_from_desktop) return; - // Get the root-most tree. - AutomationAXTreeWrapper* root_tree = tree; - while ((tree = AutomationAXTreeWrapper::GetParentOfTreeId( - root_tree->GetTreeID()))) - root_tree = tree; - + AutomationAXTreeWrapper* desktop_tree = + GetAutomationAXTreeWrapperFromTreeID(desktop_tree_id_); ui::AXNode* new_node = nullptr; AutomationAXTreeWrapper* new_wrapper = nullptr; - if (!GetFocusInternal(root_tree, &new_wrapper, &new_node)) + if (desktop_tree && !GetFocusInternal(desktop_tree, &new_wrapper, &new_node)) return; + if (!desktop_tree) { + // Can occur if the extension does not have desktop permission, + // chrome.automation.getDesktop has yet to be called, or if this platform + // does not support Aura. + new_wrapper = tree; + new_node = tree->tree()->GetFromId(raw_focus_target_id); + if (!new_node) + return; + } + if (new_wrapper == old_wrapper && new_node == old_node) return;
diff --git a/extensions/renderer/api/automation/automation_internal_custom_bindings.h b/extensions/renderer/api/automation/automation_internal_custom_bindings.h index 9493d49..a5d9054 100644 --- a/extensions/renderer/api/automation/automation_internal_custom_bindings.h +++ b/extensions/renderer/api/automation/automation_internal_custom_bindings.h
@@ -202,6 +202,9 @@ // accessibility focus. void GetAccessibilityFocus(const v8::FunctionCallbackInfo<v8::Value>& args); + // Args: string ax_tree_id. + void SetDesktopID(const v8::FunctionCallbackInfo<v8::Value>& args); + // Args: string ax_tree_id, int node_id // Returns: JS object with a map from html attribute key to value. void GetHtmlAttributes(const v8::FunctionCallbackInfo<v8::Value>& args); @@ -261,6 +264,9 @@ // as used in ui::AXTree. ui::AXTreeID accessibility_focused_tree_id_ = ui::AXTreeIDUnknown(); + // Keeps track of the single desktop tree, if it exists. + ui::AXTreeID desktop_tree_id_ = ui::AXTreeIDUnknown(); + DISALLOW_COPY_AND_ASSIGN(AutomationInternalCustomBindings); };
diff --git a/extensions/renderer/resources/automation/automation_custom_bindings.js b/extensions/renderer/resources/automation/automation_custom_bindings.js index ffa97b7..789f5a84 100644 --- a/extensions/renderer/resources/automation/automation_custom_bindings.js +++ b/extensions/renderer/resources/automation/automation_custom_bindings.js
@@ -18,6 +18,8 @@ var GetFocusNative = nativeAutomationInternal.GetFocus; var GetAccessibilityFocusNative = nativeAutomationInternal.GetAccessibilityFocus; +var SetDesktopID = + nativeAutomationInternal.SetDesktopID; /** * A namespace to export utility functions to other files in automation. @@ -102,10 +104,12 @@ if (bindingUtil.hasLastError()) { AutomationRootNode.destroy(treeId); desktopId = undefined; + SetDesktopID(''); callback(); return; } desktopId = treeId; + SetDesktopID(desktopId); desktopTree = AutomationRootNode.getOrCreate(desktopId); callback(desktopTree); @@ -118,10 +122,7 @@ }); apiFunctions.setHandleRequest('getFocus', function(callback) { - if (desktopId === undefined) - return; - - var focusedNodeInfo = GetFocusNative(desktopId); + var focusedNodeInfo = GetFocusNative(); if (!focusedNodeInfo) { callback(null); return;
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index 10e1dd2..2441d5d 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn
@@ -66,7 +66,6 @@ "//extensions/common/api", "//extensions/renderer", "//extensions/shell/browser/system_logs", - "//extensions/shell/common/api", "//extensions/shell/common/api:extensions_features", "//services/network/public/mojom", "//third_party/blink/public:blink", @@ -92,8 +91,6 @@ "app/shell_main_delegate.h", "browser/api/feedback_private/shell_feedback_private_delegate.cc", "browser/api/feedback_private/shell_feedback_private_delegate.h", - "browser/api/identity/identity_api.cc", - "browser/api/identity/identity_api.h", "browser/api/runtime/shell_runtime_api_delegate.cc", "browser/api/runtime/shell_runtime_api_delegate.h", "browser/default_shell_browser_main_delegate.cc", @@ -131,8 +128,6 @@ "browser/shell_extension_web_contents_observer.h", "browser/shell_extensions_api_client.cc", "browser/shell_extensions_api_client.h", - "browser/shell_extensions_browser_api_provider.cc", - "browser/shell_extensions_browser_api_provider.h", "browser/shell_extensions_browser_client.cc", "browser/shell_extensions_browser_client.h", "browser/shell_keep_alive_requester.cc", @@ -293,7 +288,6 @@ sources = [ "../test/extensions_unittests_main.cc", - "browser/api/identity/identity_api_unittest.cc", "browser/shell_content_browser_client_unittest.cc", "browser/shell_extension_loader_unittest.cc", "browser/shell_keep_alive_requester_unittest.cc",
diff --git a/extensions/shell/README b/extensions/shell/README index c080677..ceb4f042 100644 --- a/extensions/shell/README +++ b/extensions/shell/README
@@ -14,7 +14,7 @@ # For example, you can try the calculator app: -$ app_shell --load-apps=chrome/common/extensions/docs/examples/apps/calculator/app/ +$ app_shell --load-apps=chrome/test/data/extensions/calculator_app/app/ # To load multiple apps, specify them in a comma separated list. The first app # will be launched:
diff --git a/extensions/shell/browser/api/identity/identity_api.cc b/extensions/shell/browser/api/identity/identity_api.cc deleted file mode 100644 index cbc98e3..0000000 --- a/extensions/shell/browser/api/identity/identity_api.cc +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2014 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 "extensions/shell/browser/api/identity/identity_api.h" - -#include "extensions/shell/common/api/identity.h" - -namespace extensions { -namespace shell { - -IdentityRemoveCachedAuthTokenFunction::IdentityRemoveCachedAuthTokenFunction() = - default; - -IdentityRemoveCachedAuthTokenFunction:: - ~IdentityRemoveCachedAuthTokenFunction() = default; - -ExtensionFunction::ResponseAction IdentityRemoveCachedAuthTokenFunction::Run() { - std::unique_ptr<api::identity::RemoveCachedAuthToken::Params> params( - api::identity::RemoveCachedAuthToken::Params::Create(*args_)); - EXTENSION_FUNCTION_VALIDATE(params.get()); - // This stub identity API does not maintain a token cache, so there is nothing - // to remove. - return RespondNow(NoArguments()); -} - -} // namespace shell -} // namespace extensions
diff --git a/extensions/shell/browser/api/identity/identity_api.h b/extensions/shell/browser/api/identity/identity_api.h deleted file mode 100644 index 27ce43f0..0000000 --- a/extensions/shell/browser/api/identity/identity_api.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2014 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 EXTENSIONS_SHELL_BROWSER_API_IDENTITY_IDENTITY_API_H_ -#define EXTENSIONS_SHELL_BROWSER_API_IDENTITY_IDENTITY_API_H_ - -#include "base/macros.h" -#include "extensions/browser/extension_function.h" - -namespace extensions { -namespace shell { - -// Stub. See the IDL file for documentation. -class IdentityRemoveCachedAuthTokenFunction : public ExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("identity.removeCachedAuthToken", UNKNOWN) - - IdentityRemoveCachedAuthTokenFunction(); - - protected: - ~IdentityRemoveCachedAuthTokenFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - private: - DISALLOW_COPY_AND_ASSIGN(IdentityRemoveCachedAuthTokenFunction); -}; - -} // namespace shell -} // namespace extensions - -#endif // EXTENSIONS_SHELL_BROWSER_API_IDENTITY_IDENTITY_API_H_
diff --git a/extensions/shell/browser/api/identity/identity_api_unittest.cc b/extensions/shell/browser/api/identity/identity_api_unittest.cc deleted file mode 100644 index 5b23246..0000000 --- a/extensions/shell/browser/api/identity/identity_api_unittest.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright 2014 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 "extensions/shell/browser/api/identity/identity_api.h" - -#include "base/values.h" -#include "extensions/browser/api_unittest.h" -#include "extensions/common/extension_builder.h" -#include "extensions/common/value_builder.h" - -namespace extensions { -namespace shell { - -class IdentityApiTest : public ApiUnitTest { - public: - IdentityApiTest() {} - ~IdentityApiTest() override {} - - // testing::Test: - void SetUp() override { - ApiUnitTest::SetUp(); - DictionaryBuilder oauth2; - oauth2.Set("client_id", "123456.apps.googleusercontent.com") - .Set("scopes", ListBuilder() - .Append("https://www.googleapis.com/auth/drive") - .Build()); - // Create an extension with OAuth2 scopes. - set_extension(ExtensionBuilder("Test") - .SetManifestKey("oauth2", oauth2.Build()) - .Build()); - } -}; - -// Verifies that the removeCachedAuthToken function exists and can be called -// without crashing. -TEST_F(IdentityApiTest, RemoveCachedAuthToken) { - // Function succeeds and returns nothing (for its callback). - std::unique_ptr<base::Value> result = RunFunctionAndReturnValue( - new IdentityRemoveCachedAuthTokenFunction, "[{}]"); - EXPECT_FALSE(result.get()); -} - -} // namespace shell -} // namespace extensions
diff --git a/extensions/shell/browser/shell_extensions_browser_api_provider.cc b/extensions/shell/browser/shell_extensions_browser_api_provider.cc deleted file mode 100644 index 9003d699..0000000 --- a/extensions/shell/browser/shell_extensions_browser_api_provider.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 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 "extensions/shell/browser/shell_extensions_browser_api_provider.h" - -#include "extensions/shell/browser/api/generated_api_registration.h" - -namespace extensions { - -ShellExtensionsBrowserAPIProvider::ShellExtensionsBrowserAPIProvider() = - default; -ShellExtensionsBrowserAPIProvider::~ShellExtensionsBrowserAPIProvider() = - default; - -void ShellExtensionsBrowserAPIProvider::RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) { - shell::api::ShellGeneratedFunctionRegistry::RegisterAll(registry); -} - -} // namespace extensions
diff --git a/extensions/shell/browser/shell_extensions_browser_api_provider.h b/extensions/shell/browser/shell_extensions_browser_api_provider.h deleted file mode 100644 index 9dcce51..0000000 --- a/extensions/shell/browser/shell_extensions_browser_api_provider.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2018 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 EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_API_PROVIDER_H_ -#define EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_API_PROVIDER_H_ - -#include "extensions/browser/extensions_browser_api_provider.h" - -namespace extensions { - -class ShellExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider { - public: - ShellExtensionsBrowserAPIProvider(); - ShellExtensionsBrowserAPIProvider(const ShellExtensionsBrowserAPIProvider&) = - delete; - ShellExtensionsBrowserAPIProvider& operator=( - const ShellExtensionsBrowserAPIProvider&) = delete; - ~ShellExtensionsBrowserAPIProvider() override; - - void RegisterExtensionFunctions(ExtensionFunctionRegistry* registry) override; -}; - -} // namespace extensions - -#endif // EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_API_PROVIDER_H_
diff --git a/extensions/shell/browser/shell_extensions_browser_client.cc b/extensions/shell/browser/shell_extensions_browser_client.cc index 936f7b2..4a799ce 100644 --- a/extensions/shell/browser/shell_extensions_browser_client.cc +++ b/extensions/shell/browser/shell_extensions_browser_client.cc
@@ -30,7 +30,6 @@ #include "extensions/shell/browser/shell_extension_system_factory.h" #include "extensions/shell/browser/shell_extension_web_contents_observer.h" #include "extensions/shell/browser/shell_extensions_api_client.h" -#include "extensions/shell/browser/shell_extensions_browser_api_provider.h" #include "extensions/shell/browser/shell_navigation_ui_data.h" #include "services/network/public/mojom/url_loader.mojom.h" @@ -51,7 +50,6 @@ SetCurrentChannel(version_info::Channel::UNKNOWN); AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>()); - AddAPIProvider(std::make_unique<ShellExtensionsBrowserAPIProvider>()); } ShellExtensionsBrowserClient::~ShellExtensionsBrowserClient() {
diff --git a/extensions/shell/common/api/BUILD.gn b/extensions/shell/common/api/BUILD.gn index d6952ca..5ad2808 100644 --- a/extensions/shell/common/api/BUILD.gn +++ b/extensions/shell/common/api/BUILD.gn
@@ -4,38 +4,12 @@ import("//extensions/buildflags/buildflags.gni") import("//tools/json_schema_compiler/json_features.gni") -import("//tools/json_schema_compiler/json_schema_api.gni") assert(enable_extensions, "Cannot depend on extensions because enable_extensions=false.") # TODO(devlin): Enforce visibility restrictions on more of these targets? -schema_sources = [ "identity.idl" ] -root_namespace = "extensions::shell::api::%(namespace)s" - -function_registration("generated_api_registration") { - sources = schema_sources - impl_dir = "//extensions/shell/browser/api" - bundle_name = "Shell" - - deps = [ "//extensions/common" ] - - visibility = [ ":api" ] -} - -generated_json_strings("generated_api_json_strings") { - sources = schema_sources - bundle_name = "Shell" - visibility = [ ":api" ] -} - -generated_types("generated_api_types") { - sources = schema_sources - - visibility = [ ":api" ] -} - json_features("shell_api_features") { feature_type = "APIFeature" method_name = "AddShellAPIFeatures" @@ -44,14 +18,6 @@ # Public Targets -group("api") { - public_deps = [ - ":generated_api_json_strings", - ":generated_api_registration", - ":generated_api_types", - ] -} - group("extensions_features") { public_deps = [ ":shell_api_features",
diff --git a/extensions/shell/common/api/_api_features.json b/extensions/shell/common/api/_api_features.json index c3b1471..1a4b599 100644 --- a/extensions/shell/common/api/_api_features.json +++ b/extensions/shell/common/api/_api_features.json
@@ -7,16 +7,10 @@ // feature.h, simple_feature.h, and feature_provider.h. { - // Stub implementation of chrome.identity for app_shell. - "identity": { - "channel": "dev", - "contexts": ["blessed_extension"], - "extension_types": ["platform_app"] - }, // Setup related functions for a Google Cloud Devices (GCD) target device. "shell.gcd": { "channel": "dev", "contexts": ["blessed_extension"], - "extension_types": ["platform_app"] + "extension_types": ["platform_app"] } }
diff --git a/extensions/shell/common/api/identity.idl b/extensions/shell/common/api/identity.idl deleted file mode 100644 index e8ac69a8..0000000 --- a/extensions/shell/common/api/identity.idl +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2014 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. - -// Simplified implementation of the <code>chrome.identity</code> for app_shell. -namespace identity { - - dictionary InvalidTokenDetails { - // Ignored parameter. Exists only for compatibility. - DOMString? token; - }; - - // Called by removeCachedAuthToken(). - callback InvalidateAuthTokenCallback = void (); - - interface Functions { - // Stub. Calls callback immediately because app_shell does not cache access - // tokens the way Chrome does. - static void removeCachedAuthToken(InvalidTokenDetails details, - InvalidateAuthTokenCallback callback); - }; - - interface Events { - // Stub. Never fired because app_shell only supports a single user account. - static void onSignInChanged(object account, boolean signedIn); - }; -};
diff --git a/extensions/shell/common/shell_extensions_api_provider.cc b/extensions/shell/common/shell_extensions_api_provider.cc index 716ce790..eae9e6b 100644 --- a/extensions/shell/common/shell_extensions_api_provider.cc +++ b/extensions/shell/common/shell_extensions_api_provider.cc
@@ -4,8 +4,7 @@ #include "extensions/shell/common/shell_extensions_api_provider.h" -#include "extensions/common/features/json_feature_provider_source.h" -#include "extensions/shell/common/api/generated_schemas.h" +#include "base/strings/string_piece.h" #include "extensions/shell/common/api/shell_api_features.h" #include "extensions/shell/grit/app_shell_resources.h" @@ -35,16 +34,16 @@ void ShellExtensionsAPIProvider::AddAPIJSONSources( JSONFeatureProviderSource* json_source) { - json_source->LoadJSON(IDR_SHELL_EXTENSION_API_FEATURES); + // No shell-specific APIs. } bool ShellExtensionsAPIProvider::IsAPISchemaGenerated(const std::string& name) { - return shell::api::ShellGeneratedSchemas::IsGenerated(name); + return false; } base::StringPiece ShellExtensionsAPIProvider::GetAPISchema( const std::string& name) { - return shell::api::ShellGeneratedSchemas::Get(name); + return base::StringPiece(); } void ShellExtensionsAPIProvider::RegisterPermissions(
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index f73b093..82ca90b 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -196,7 +196,6 @@ "//components/history/core/browser", "//components/keyed_service/core", "//components/language/core/browser", - "//components/language_usage_metrics", "//components/metrics", "//components/metrics:child_call_stack_profile_builder", "//components/metrics_services_manager",
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index b594a43..4051f15 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -40,7 +40,6 @@ "+components/keyed_service/core", "+components/keyed_service/ios", "+components/language", - "+components/language_usage_metrics", "+components/leveldb_proto", "+components/lookalikes/core", "+components/metrics",
diff --git a/ios/chrome/browser/ios_chrome_main_parts.mm b/ios/chrome/browser/ios_chrome_main_parts.mm index 5ee714e..66ef6f54 100644 --- a/ios/chrome/browser/ios_chrome_main_parts.mm +++ b/ios/chrome/browser/ios_chrome_main_parts.mm
@@ -21,8 +21,8 @@ #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/flags_ui/pref_service_flags_storage.h" #include "components/heap_profiling/in_process/heap_profiler_controller.h" +#include "components/language/core/browser/language_usage_metrics.h" #include "components/language/core/browser/pref_names.h" -#include "components/language_usage_metrics/language_usage_metrics.h" #include "components/metrics/call_stack_profile_builder.h" #include "components/metrics/call_stack_profile_metrics_provider.h" #include "components/metrics/expired_histogram_util.h" @@ -277,10 +277,10 @@ #endif // BUILDFLAG(ENABLE_RLZ) TranslateServiceIOS::Initialize(); - language_usage_metrics::LanguageUsageMetrics::RecordAcceptLanguages( + language::LanguageUsageMetrics::RecordAcceptLanguages( last_used_browser_state->GetPrefs()->GetString( language::prefs::kAcceptLanguages)); - language_usage_metrics::LanguageUsageMetrics::RecordApplicationLanguage( + language::LanguageUsageMetrics::RecordApplicationLanguage( application_context_->GetApplicationLocale()); // Request new variations seed information from server.
diff --git a/ios/chrome/browser/ui/settings/cells/BUILD.gn b/ios/chrome/browser/ui/settings/cells/BUILD.gn index 18b02ee..ce830fd3 100644 --- a/ios/chrome/browser/ui/settings/cells/BUILD.gn +++ b/ios/chrome/browser/ui/settings/cells/BUILD.gn
@@ -44,6 +44,7 @@ "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/icons", + "//ios/chrome/browser/ui/settings:constants", "//ios/chrome/browser/ui/table_view:styler", "//ios/chrome/browser/ui/table_view/cells", "//ios/chrome/browser/ui/table_view/cells:cells_constants",
diff --git a/ios/chrome/browser/ui/settings/cells/account_sign_in_item.mm b/ios/chrome/browser/ui/settings/cells/account_sign_in_item.mm index 45a2b97..0cca1f9 100644 --- a/ios/chrome/browser/ui/settings/cells/account_sign_in_item.mm +++ b/ios/chrome/browser/ui/settings/cells/account_sign_in_item.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/settings/cells/account_sign_in_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_cell.h" +#import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" @@ -15,13 +16,6 @@ #error "This file requires ARC support." #endif -namespace { - -// Account profile picture size. -const CGFloat kAccountProfilePhotoDimension = 40.0f; - -} // namespace - @implementation AccountSignInItem - (instancetype)initWithType:(NSInteger)type {
diff --git a/ios/chrome/browser/ui/settings/google_services/BUILD.gn b/ios/chrome/browser/ui/settings/google_services/BUILD.gn index fec7b25..6be9a76 100644 --- a/ios/chrome/browser/ui/settings/google_services/BUILD.gn +++ b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
@@ -60,11 +60,13 @@ "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/authentication/cells", + "//ios/chrome/browser/ui/authentication/signin:signin_headers", "//ios/chrome/browser/ui/authentication/signin:signin_protected", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/icons", "//ios/chrome/browser/ui/list_model", + "//ios/chrome/browser/ui/settings:constants", "//ios/chrome/browser/ui/settings:settings_root", "//ios/chrome/browser/ui/settings/cells", "//ios/chrome/browser/ui/settings/elements:enterprise_info_popover_view_controller", @@ -144,7 +146,9 @@ "//components/password_manager/core/common", "//components/safe_browsing/core:features", "//components/safe_browsing/core/common:safe_browsing_prefs", + "//components/signin/public/base", "//ios/chrome/app/strings", + "//ios/chrome/browser:utils", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/authentication:eg_test_support+eg2", "//ios/chrome/browser/ui/bookmarks:eg_test_support+eg2",
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm index 5bf1fe1..2696d71 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm
@@ -4,6 +4,8 @@ #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" +#include "components/signin/public/base/signin_pref_names.h" +#import "ios/chrome/browser/chrome_switches.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h" #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_app_interface.h" @@ -46,6 +48,16 @@ @implementation GoogleServicesSettingsTestCase +- (AppLaunchConfiguration)appConfigurationForTestCase { + // Adds the command-line switch to enable support for the BrowserSignin + // policy. + AppLaunchConfiguration config; + config.additional_args.push_back(std::string("--") + + switches::kInstallBrowserSigninHandler); + config.relaunch_policy = NoForceRelaunchAndResetState; + return config; +} + // Opens the Google services settings view, and closes it. - (void)testOpenGoogleServicesSettings { [self openGoogleServicesSettings]; @@ -312,6 +324,38 @@ [SigninEarlGrey verifySignedInWithFakeIdentity:fakeIdentity]; } +// Tests that the sign-in button can't be used when sign-in is disabled. +- (void)testSigninDisabled { + // Disable browser sign-in. + [ChromeEarlGrey setBoolValue:NO forUserPref:prefs::kSigninAllowed]; + + // Open Google services settings and verify the sign-in cell shows the + // "sign-in disabled" text. + [self openGoogleServicesSettings]; + id<GREYMatcher> signinMatcher = + [self cellMatcherWithTitleID:IDS_IOS_SIGN_IN_TO_CHROME_SETTING_TITLE + detailTextID:IDS_IOS_SETTINGS_SIGNIN_DISABLED]; + [[EarlGrey selectElementWithMatcher:signinMatcher] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Attempt to tap the sign-in cell. + FakeChromeIdentity* fakeIdentity = [SigninEarlGrey fakeIdentity1]; + [SigninEarlGrey addFakeIdentity:fakeIdentity]; + + [[EarlGrey selectElementWithMatcher:signinMatcher] performAction:grey_tap()]; + + // Verify the sync view isn't showing. + id<GREYMatcher> syncTitleMatcher = grey_allOf( + grey_accessibilityLabel( + GetNSString(IDS_IOS_ACCOUNT_UNIFIED_CONSENT_SYNC_TITLE)), + grey_kindOfClass([UILabel class]), grey_sufficientlyVisible(), nil); + [[EarlGrey selectElementWithMatcher:syncTitleMatcher] + assertWithMatcher:grey_nil()]; + + // Prefs clean-up. + [ChromeEarlGrey setBoolValue:YES forUserPref:prefs::kSigninAllowed]; +} + #pragma mark - Helpers // Opens the Google services settings.
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm index 4e29d22f..cfa25b0 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_mediator.mm
@@ -23,6 +23,7 @@ #include "ios/chrome/browser/sync/sync_observer_bridge.h" #import "ios/chrome/browser/ui/authentication/cells/table_view_account_item.h" #import "ios/chrome/browser/ui/authentication/resized_avatar_cache.h" +#import "ios/chrome/browser/ui/authentication/signin/signin_utils.h" #import "ios/chrome/browser/ui/settings/cells/account_sign_in_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_image_detail_text_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" @@ -30,6 +31,7 @@ #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_command_handler.h" #import "ios/chrome/browser/ui/settings/google_services/google_services_settings_constants.h" #import "ios/chrome/browser/ui/settings/google_services/sync_error_settings_command_handler.h" +#import "ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h" #import "ios/chrome/browser/ui/settings/sync/utils/sync_util.h" #import "ios/chrome/browser/ui/settings/utils/observable_boolean.h" #import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h" @@ -39,9 +41,12 @@ #import "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" +#import "ios/chrome/common/ui/colors/semantic_color_names.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" +#import "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/signin/chrome_identity.h" +#import "ios/public/provider/chrome/browser/signin/signin_resources_provider.h" #include "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -91,6 +96,7 @@ ImproveChromeItemType, BetterSearchAndBrowsingItemType, ItemTypePasswordLeakCheckSwitch, + SignInDisabledItemType, }; // Enterprise icon. @@ -364,6 +370,29 @@ if (hasAccountSignInItem) return NO; + + if (!signin::IsSigninAllowed(self.userPrefService)) { + // Sign-in is disabled by policy. + TableViewInfoButtonItem* signinDisabledItem = + [[TableViewInfoButtonItem alloc] initWithType:SignInDisabledItemType]; + signinDisabledItem.text = + l10n_util::GetNSString(IDS_IOS_SIGN_IN_TO_CHROME_SETTING_TITLE); + signinDisabledItem.detailText = + l10n_util::GetNSString(IDS_IOS_SETTINGS_SIGNIN_DISABLED); + signinDisabledItem.accessibilityHint = l10n_util::GetNSString( + IDS_IOS_TOGGLE_SETTING_MANAGED_ACCESSIBILITY_HINT); + signinDisabledItem.image = + CircularImageFromImage(ios::GetChromeBrowserProvider() + ->GetSigninResourcesProvider() + ->GetDefaultAvatar(), + kAccountProfilePhotoDimension); + signinDisabledItem.textColor = [UIColor colorNamed:kTextSecondaryColor]; + signinDisabledItem.tintColor = [UIColor colorNamed:kGrey300Color]; + [model addItem:signinDisabledItem + toSectionWithIdentifier:SyncSectionIdentifier]; + return YES; + } + AccountSignInItem* accountSignInItem = [[AccountSignInItem alloc] initWithType:SignInItemType]; accountSignInItem.detailText = @@ -573,6 +602,7 @@ case SyncSettingsNotCofirmedErrorItemType: case SyncChromeDataItemType: case ManageSyncItemType: + case SignInDisabledItemType: NOTREACHED(); break; } @@ -887,6 +917,7 @@ case SyncDisabledByAdministratorErrorItemType: case SyncSettingsNotCofirmedErrorItemType: case ManageSyncItemType: + case SignInDisabledItemType: NOTREACHED(); break; } @@ -929,6 +960,7 @@ case ImproveChromeItemType: case BetterSearchAndBrowsingItemType: case SyncChromeDataItemType: + case SignInDisabledItemType: break; } }
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm index 84c4b0f..f6eada0 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -109,8 +109,6 @@ namespace { -const CGFloat kAccountProfilePhotoDimension = 40.0f; - NSString* const kSyncAndGoogleServicesImageName = @"sync_and_google_services"; NSString* const kSyncAndGoogleServicesSyncErrorImageName = @"sync_and_google_services_sync_error";
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h b/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h index c0f33f97..5ecf547 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.h
@@ -49,6 +49,9 @@ SettingsItemTypeSigninDisabled, }; +// The radius of the profile photo in the sign-in cell. +extern const CGFloat kAccountProfilePhotoDimension; + // The accessibility identifier of the settings TableView. extern NSString* const kSettingsTableViewId;
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.mm index c02e7fb0..43e57d8 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller_constants.mm
@@ -8,6 +8,8 @@ #error "This file requires ARC support." #endif +const CGFloat kAccountProfilePhotoDimension = 40.0f; + NSString* const kSettingsTableViewId = @"kSettingsTableViewId"; NSString* const kSettingsSignInCellId = @"kSettingsSignInCellId"; NSString* const kSettingsSignInDisabledCellId =
diff --git a/media/base/video_encoder.h b/media/base/video_encoder.h index 1513367..d1a590a 100644 --- a/media/base/video_encoder.h +++ b/media/base/video_encoder.h
@@ -34,6 +34,11 @@ class MEDIA_EXPORT VideoEncoder { public: + // TODO: Move this to a new file if there are more codec specific options. + struct MEDIA_EXPORT AvcOptions { + bool produce_annexb = false; + }; + struct MEDIA_EXPORT Options { Options(); Options(const Options&); @@ -44,6 +49,9 @@ gfx::Size frame_size; base::Optional<int> keyframe_interval = 10000; + + // Only used for H264 encoding. + AvcOptions avc; }; // A sequence of codec specific bytes, commonly known as extradata.
diff --git a/media/base/video_util.cc b/media/base/video_util.cc index 2439640..86ed815e 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc
@@ -507,6 +507,71 @@ if (!src_frame.IsMappable() || !dst_frame.IsMappable()) return Status(StatusCode::kUnsupportedFrameFormatError); + if ((dst_frame.format() == PIXEL_FORMAT_I420 || + dst_frame.format() == PIXEL_FORMAT_NV12) && + (src_frame.format() == PIXEL_FORMAT_XBGR || + src_frame.format() == PIXEL_FORMAT_XRGB || + src_frame.format() == PIXEL_FORMAT_ABGR || + src_frame.format() == PIXEL_FORMAT_ARGB)) { + // libyuv's RGB to YUV methods always output BT.601. + dst_frame.set_color_space(gfx::ColorSpace::CreateREC601()); + + size_t src_stride = src_frame.stride(VideoFrame::kARGBPlane); + const uint8_t* src_data = src_frame.visible_data(VideoFrame::kARGBPlane); + if (src_frame.visible_rect() != dst_frame.visible_rect()) { + size_t tmp_buffer_size = VideoFrame::AllocationSize( + src_frame.format(), dst_frame.coded_size()); + if (tmp_buf.size() < tmp_buffer_size) + tmp_buf.resize(tmp_buffer_size); + + size_t stride = + VideoFrame::RowBytes(VideoFrame::kARGBPlane, src_frame.format(), + dst_frame.visible_rect().width()); + int error = libyuv::ARGBScale( + src_data, src_stride, src_frame.visible_rect().width(), + src_frame.visible_rect().height(), tmp_buf.data(), stride, + dst_frame.visible_rect().width(), dst_frame.visible_rect().height(), + kDefaultFiltering); + if (error) + return Status(StatusCode::kInvalidArgument); + src_data = tmp_buf.data(); + src_stride = stride; + } + + if (dst_frame.format() == PIXEL_FORMAT_I420) { + auto convert_fn = (src_frame.format() == PIXEL_FORMAT_XBGR || + src_frame.format() == PIXEL_FORMAT_ABGR) + ? libyuv::ABGRToI420 + : libyuv::ARGBToI420; + int error = convert_fn(src_data, src_stride, + dst_frame.visible_data(media::VideoFrame::kYPlane), + dst_frame.stride(media::VideoFrame::kYPlane), + dst_frame.visible_data(media::VideoFrame::kUPlane), + dst_frame.stride(media::VideoFrame::kUPlane), + dst_frame.visible_data(media::VideoFrame::kVPlane), + dst_frame.stride(media::VideoFrame::kVPlane), + dst_frame.visible_rect().width(), + dst_frame.visible_rect().height()); + return error ? Status(StatusCode::kInvalidArgument) : Status(); + } + + auto convert_fn = (src_frame.format() == PIXEL_FORMAT_XBGR || + src_frame.format() == PIXEL_FORMAT_ABGR) + ? libyuv::ABGRToNV12 + : libyuv::ARGBToNV12; + int error = convert_fn(src_data, src_stride, + dst_frame.visible_data(media::VideoFrame::kYPlane), + dst_frame.stride(media::VideoFrame::kYPlane), + dst_frame.visible_data(media::VideoFrame::kUVPlane), + dst_frame.stride(media::VideoFrame::kUVPlane), + dst_frame.visible_rect().width(), + dst_frame.visible_rect().height()); + return error ? Status(StatusCode::kInvalidArgument) : Status(); + } + + // Converting between YUV formats doesn't change the color space. + dst_frame.set_color_space(src_frame.ColorSpace()); + // Both frames are I420, only scaling is required. if (dst_frame.format() == PIXEL_FORMAT_I420 && src_frame.format() == PIXEL_FORMAT_I420) {
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index a7f73e88..fc0ff827 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -386,7 +386,8 @@ uint8_t* pixels = static_cast<uint8_t*>(rgb_pixels) + row_bytes * chunk_start * rows_per_chunk; - if (format == PIXEL_FORMAT_ARGB) { + if (format == PIXEL_FORMAT_ARGB || format == PIXEL_FORMAT_XRGB || + format == PIXEL_FORMAT_ABGR || format == PIXEL_FORMAT_XBGR) { DCHECK_LE(width, static_cast<int>(row_bytes)); const uint8_t* data = plane_meta[VideoFrame::kARGBPlane].data; for (size_t i = 0; i < rows; i++) { @@ -928,8 +929,11 @@ // frame has an unexpected format. if (!video_frame.get() || video_frame->natural_size().IsEmpty() || !(media::IsYuvPlanar(video_frame->format()) || - video_frame->format() == media::PIXEL_FORMAT_Y16 || - video_frame->format() == media::PIXEL_FORMAT_ARGB || + video_frame->format() == PIXEL_FORMAT_Y16 || + video_frame->format() == PIXEL_FORMAT_ARGB || + video_frame->format() == PIXEL_FORMAT_XRGB || + video_frame->format() == PIXEL_FORMAT_ABGR || + video_frame->format() == PIXEL_FORMAT_XBGR || video_frame->HasTextures())) { cc::PaintFlags black_with_alpha_flags; black_with_alpha_flags.setAlpha(flags.getAlpha());
diff --git a/media/video/openh264_video_encoder.cc b/media/video/openh264_video_encoder.cc index 9ad7538..bc75f01 100644 --- a/media/video/openh264_video_encoder.cc +++ b/media/video/openh264_video_encoder.cc
@@ -132,10 +132,13 @@ return; } + if (!options.avc.produce_annexb) + h264_converter_ = std::make_unique<H264AnnexBToAvcBitstreamConverter>(); + options_ = options; output_cb_ = BindToCurrentLoop(std::move(output_cb)); codec_ = std::move(codec); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(OkStatus()); } void OpenH264VideoEncoder::Encode(scoped_refptr<VideoFrame> frame, @@ -153,8 +156,12 @@ "No frame provided for encoding.")); return; } - const bool supported_format = (frame->format() == PIXEL_FORMAT_NV12) || - (frame->format() == PIXEL_FORMAT_I420); + const bool supported_format = frame->format() == PIXEL_FORMAT_NV12 || + frame->format() == PIXEL_FORMAT_I420 || + frame->format() == PIXEL_FORMAT_XBGR || + frame->format() == PIXEL_FORMAT_XRGB || + frame->format() == PIXEL_FORMAT_ABGR || + frame->format() == PIXEL_FORMAT_ARGB; if ((!frame->IsMappable() && !frame->HasGpuMemoryBuffer()) || !supported_format) { status = @@ -175,7 +182,7 @@ } } - if (frame->format() == PIXEL_FORMAT_NV12) { + if (frame->format() != PIXEL_FORMAT_I420) { // OpenH264 can resize frame automatically, but since we're converting // pixel fromat anyway we can do resize as well. auto i420_frame = frame_pool_.CreateFrame( @@ -229,7 +236,16 @@ DCHECK_GT(frame_info.iFrameSizeInBytes, 0); size_t total_chunk_size = frame_info.iFrameSizeInBytes; - conversion_buffer_.resize(total_chunk_size); + + result.data.reset(new uint8_t[total_chunk_size]); + + auto* gather_buffer = result.data.get(); + + if (h264_converter_) { + // Copy data to a temporary buffer instead. + conversion_buffer_.resize(total_chunk_size); + gather_buffer = conversion_buffer_.data(); + } size_t written_size = 0; for (int layer_idx = 0; layer_idx < frame_info.iLayerNum; ++layer_idx) { @@ -243,16 +259,22 @@ return; } - memcpy(conversion_buffer_.data() + written_size, layer_info.pBsBuf, - layer_len); + memcpy(gather_buffer + written_size, layer_info.pBsBuf, layer_len); written_size += layer_len; } DCHECK_EQ(written_size, total_chunk_size); + if (!h264_converter_) { + result.size = total_chunk_size; + + output_cb_.Run(std::move(result), base::Optional<CodecDescription>()); + std::move(done_cb).Run(OkStatus()); + return; + } + size_t converted_output_size = 0; bool config_changed = false; - result.data.reset(new uint8_t[total_chunk_size]); - status = h264_converter_.ConvertChunk( + status = h264_converter_->ConvertChunk( conversion_buffer_, base::span<uint8_t>(result.data.get(), total_chunk_size), &config_changed, &converted_output_size); @@ -261,11 +283,12 @@ std::move(done_cb).Run(std::move(status).AddHere(FROM_HERE)); return; } + result.size = converted_output_size; base::Optional<CodecDescription> desc; if (config_changed) { - const auto& config = h264_converter_.GetCurrentConfig(); + const auto& config = h264_converter_->GetCurrentConfig(); desc = CodecDescription(); if (!config.Serialize(desc.value())) { std::move(done_cb).Run(Status(StatusCode::kEncoderFailedEncode, @@ -275,7 +298,7 @@ } output_cb_.Run(std::move(result), std::move(desc)); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(OkStatus()); } void OpenH264VideoEncoder::ChangeOptions(const Options& options, @@ -312,9 +335,15 @@ return; } + if (options.avc.produce_annexb) { + h264_converter_.reset(); + } else if (!h264_converter_) { + h264_converter_ = std::make_unique<H264AnnexBToAvcBitstreamConverter>(); + } + if (!output_cb.is_null()) output_cb_ = BindToCurrentLoop(std::move(output_cb)); - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(OkStatus()); } void OpenH264VideoEncoder::Flush(StatusCB done_cb) { @@ -325,7 +354,7 @@ } // Nothing to do really. - std::move(done_cb).Run(Status()); + std::move(done_cb).Run(OkStatus()); } } // namespace media
diff --git a/media/video/openh264_video_encoder.h b/media/video/openh264_video_encoder.h index 77afa25..d737b3d 100644 --- a/media/video/openh264_video_encoder.h +++ b/media/video/openh264_video_encoder.h
@@ -59,8 +59,11 @@ OutputCB output_cb_; std::vector<uint8_t> conversion_buffer_; VideoFramePool frame_pool_; - H264AnnexBToAvcBitstreamConverter h264_converter_; + + // If |h264_converter_| is null, we output in annexb format. Otherwise, we + // output in avc format. + std::unique_ptr<H264AnnexBToAvcBitstreamConverter> h264_converter_; }; } // namespace media -#endif // MEDIA_VIDEO_OPENH264_VIDEO_ENCODER_H_ \ No newline at end of file +#endif // MEDIA_VIDEO_OPENH264_VIDEO_ENCODER_H_
diff --git a/media/video/video_encode_accelerator_adapter.cc b/media/video/video_encode_accelerator_adapter.cc index f37f5d0..7ce8ce7 100644 --- a/media/video/video_encode_accelerator_adapter.cc +++ b/media/video/video_encode_accelerator_adapter.cc
@@ -41,9 +41,20 @@ opts.bitrate.value_or(opts.frame_size.width() * opts.frame_size.height() * kVEADefaultBitratePerPixel)); + const bool is_rgb = + format == PIXEL_FORMAT_XBGR || format == PIXEL_FORMAT_XRGB || + format == PIXEL_FORMAT_ABGR || format == PIXEL_FORMAT_ARGB; + + // Override the provided format if incoming frames are RGB -- they'll be + // converted to I420 or NV12 depending on the VEA configuration. + if (is_rgb) + config.input_format = PIXEL_FORMAT_I420; + #if defined(OS_LINUX) || defined(OS_CHROMEOS) if (storage_type == VideoFrame::STORAGE_DMABUFS || storage_type == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) { + if (is_rgb) + config.input_format = PIXEL_FORMAT_NV12; config.storage_type = VideoEncodeAccelerator::Config::StorageType::kDmabuf; } #endif @@ -206,8 +217,10 @@ state_ = State::kWaitingForFirstFrame; #if BUILDFLAG(USE_PROPRIETARY_CODECS) - if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) + if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX && + !options_.avc.produce_annexb) { h264_converter_ = std::make_unique<H264AnnexBToAvcBitstreamConverter>(); + } #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) std::move(done_cb).Run(Status()); @@ -223,9 +236,13 @@ // We use the first frame to setup the VEA config so that we can ensure that // zero copy hardware encoding from the camera can be used. const auto& first_frame = pending_encodes_.front()->frame; - auto format = first_frame->format(); - - if (format != PIXEL_FORMAT_I420 && format != PIXEL_FORMAT_NV12) { + const auto format = first_frame->format(); + const bool is_rgb = + format == PIXEL_FORMAT_XBGR || format == PIXEL_FORMAT_XRGB || + format == PIXEL_FORMAT_ABGR || format == PIXEL_FORMAT_ARGB; + const bool supported_format = + format == PIXEL_FORMAT_NV12 || format == PIXEL_FORMAT_I420 || is_rgb; + if (!supported_format) { auto status = Status(StatusCode::kEncoderFailedEncode, "Unexpected frame format.") .WithData("frame", first_frame->AsHumanReadableString()); @@ -259,7 +276,7 @@ } state_ = State::kInitializing; - format_ = format; + format_ = vea_config.input_format; } void VideoEncodeAcceleratorAdapter::Encode(scoped_refptr<VideoFrame> frame, @@ -363,9 +380,20 @@ options.framerate.value_or(VideoEncodeAccelerator::kDefaultFramerate))}; accelerator_->RequestEncodingParametersChange(bitrate, framerate); + +#if BUILDFLAG(USE_PROPRIETARY_CODECS) + if (profile_ >= H264PROFILE_MIN && profile_ <= H264PROFILE_MAX) { + if (options.avc.produce_annexb) { + h264_converter_.reset(); + } else if (!h264_converter_) { + h264_converter_ = std::make_unique<H264AnnexBToAvcBitstreamConverter>(); + } + } +#endif // BUILDFLAG(USE_PROPRIETARY_CODECS) + options_ = options; if (!output_cb.is_null()) - output_cb_ = BindToCurrentLoop(std::move(output_cb)); + output_cb_ = std::move(output_cb); std::move(done_cb).Run(Status()); } @@ -409,7 +437,7 @@ // If flush is not supported FlushCompleted() will be called by // BitstreamBufferReady() when |active_encodes_| is empty. - if (flush_support_ && state_ == State::kFlushing) { + if (state_ == State::kFlushing && flush_support_.value()) { accelerator_->Flush( base::BindOnce(&VideoEncodeAcceleratorAdapter::FlushCompleted, base::Unretained(this))); @@ -438,7 +466,6 @@ accelerator_->UseOutputBitstreamBuffer( BitstreamBuffer(buffer_id, region->Duplicate(), region->GetSize())); InitCompleted(Status()); - flush_support_ = accelerator_->IsFlushSupported(); } void VideoEncodeAcceleratorAdapter::BitstreamBufferReady( @@ -516,7 +543,7 @@ } } output_cb_.Run(std::move(result), std::move(desc)); - if (active_encodes_.empty() && !flush_support_) { + if (active_encodes_.empty() && !flush_support_.value()) { // Manually call FlushCompleted(), since |accelerator_| won't do it for us. FlushCompleted(true); } @@ -571,6 +598,7 @@ } state_ = State::kReadyToEncode; + flush_support_ = accelerator_->IsFlushSupported(); // Send off the encodes that came in while we were waiting for initialization. for (auto& encode : pending_encodes_) { @@ -583,7 +611,7 @@ // all the pending encodes have been sent. if (pending_flush_) { state_ = State::kFlushing; - if (flush_support_) { + if (flush_support_.value()) { accelerator_->Flush( base::BindOnce(&VideoEncodeAcceleratorAdapter::FlushCompleted, base::Unretained(this))); @@ -610,8 +638,8 @@ return BindToLoop(callback_task_runner_.get(), std::move(cb)); } -// Copy a frame into a shared mem buffer and resize it as the same time. -// Input frames can I420 or NV12, they'll be converted to I420 if needed. +// Copy a frame into a shared mem buffer and resize it as the same time. Input +// frames can I420, NV12, or RGB -- they'll be converted to I420 if needed. StatusOr<scoped_refptr<VideoFrame>> VideoEncodeAcceleratorAdapter::PrepareCpuFrame( const gfx::Size& size, @@ -646,8 +674,8 @@ return shared_frame; } -// Copy a frame into a GPU buffer and resize it as the same time. -// Input frames can I420 or NV12, they'll be converted to NV12 if needed. +// Copy a frame into a GPU buffer and resize it as the same time. Input frames +// can I420, NV12, or RGB -- they'll be converted to NV12 if needed. StatusOr<scoped_refptr<VideoFrame>> VideoEncodeAcceleratorAdapter::PrepareGpuFrame( const gfx::Size& size,
diff --git a/media/video/video_encode_accelerator_adapter.h b/media/video/video_encode_accelerator_adapter.h index 1afefdfd..18651e39 100644 --- a/media/video/video_encode_accelerator_adapter.h +++ b/media/video/video_encode_accelerator_adapter.h
@@ -11,6 +11,7 @@ #include "base/containers/circular_deque.h" #include "base/containers/queue.h" #include "base/memory/scoped_refptr.h" +#include "base/optional.h" #include "base/synchronization/lock.h" #include "media/base/media_export.h" #include "media/base/video_encoder.h" @@ -118,6 +119,8 @@ GpuVideoAcceleratorFactories* gpu_factories_; #if BUILDFLAG(USE_PROPRIETARY_CODECS) + // If |h264_converter_| is null, we output in annexb format. Otherwise, we + // output in avc format. std::unique_ptr<H264AnnexBToAvcBitstreamConverter> h264_converter_; #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) @@ -135,7 +138,7 @@ scoped_refptr<base::SequencedTaskRunner> callback_task_runner_; State state_ = State::kNotInitialized; - bool flush_support_ = false; + base::Optional<bool> flush_support_; struct PendingEncode { PendingEncode(); @@ -152,10 +155,10 @@ InputBufferKind input_buffer_preference_ = InputBufferKind::Any; std::vector<uint8_t> resize_buf_; - VideoCodecProfile profile_; + VideoCodecProfile profile_ = VIDEO_CODEC_PROFILE_UNKNOWN; Options options_; OutputCB output_cb_; }; } // namespace media -#endif // MEDIA_VIDEO_VIDEO_ENCODE_ACCELERATOR_ADAPTER_H_ \ No newline at end of file +#endif // MEDIA_VIDEO_VIDEO_ENCODE_ACCELERATOR_ADAPTER_H_
diff --git a/media/video/video_encode_accelerator_adapter_test.cc b/media/video/video_encode_accelerator_adapter_test.cc index 7666aab7..fbef0f3 100644 --- a/media/video/video_encode_accelerator_adapter_test.cc +++ b/media/video/video_encode_accelerator_adapter_test.cc
@@ -112,6 +112,23 @@ return frame; } + scoped_refptr<VideoFrame> CreateGreenCpuFrameARGB(gfx::Size size, + base::TimeDelta timestamp) { + auto frame = VideoFrame::CreateFrame(PIXEL_FORMAT_XRGB, size, + gfx::Rect(size), size, timestamp); + + // Green XRGB frame (R:0x3B, G:0xD9, B:0x24) + libyuv::ARGBRect(frame->data(VideoFrame::kARGBPlane), + frame->stride(VideoFrame::kARGBPlane), + 0, // left + 0, // top + frame->visible_rect().width(), // right + frame->visible_rect().height(), // bottom + 0x24D93B00); // V color + + return frame; + } + scoped_refptr<VideoFrame> CreateGreenFrame(gfx::Size size, VideoPixelFormat format, base::TimeDelta timestamp) { @@ -120,6 +137,8 @@ return CreateGreenCpuFrame(size, timestamp); case PIXEL_FORMAT_NV12: return CreateGreenGpuFrame(size, timestamp); + case PIXEL_FORMAT_XRGB: + return CreateGreenCpuFrameARGB(size, timestamp); default: EXPECT_TRUE(false) << "not supported pixel format"; return nullptr; @@ -194,6 +213,36 @@ EXPECT_EQ(outputs_count, 1); } +TEST_F(VideoEncodeAcceleratorAdapterTest, FlushDuringInitialize) { + VideoEncoder::Options options; + options.frame_size = gfx::Size(640, 480); + int outputs_count = 0; + auto pixel_format = PIXEL_FORMAT_I420; + VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting( + [&](VideoEncoderOutput, base::Optional<VideoEncoder::CodecDescription>) { + outputs_count++; + }); + + vea()->SetEncodingCallback(base::BindLambdaForTesting( + [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) { + EXPECT_EQ(keyframe, true); + EXPECT_EQ(frame->format(), pixel_format); + EXPECT_EQ(frame->coded_size(), options.frame_size); + return BitstreamBufferMetadata(1, keyframe, frame->timestamp()); + })); + adapter()->Initialize(profile_, options, std::move(output_cb), + ValidatingStatusCB()); + + auto frame = CreateGreenFrame(options.frame_size, pixel_format, + base::TimeDelta::FromMilliseconds(1)); + adapter()->Encode(frame, true, ValidatingStatusCB()); + adapter()->Flush(base::BindLambdaForTesting([&](Status s) { + EXPECT_TRUE(s.is_ok()); + EXPECT_EQ(outputs_count, 1); + })); + RunUntilIdle(); +} + TEST_F(VideoEncodeAcceleratorAdapterTest, InitializationError) { VideoEncoder::Options options; options.frame_size = gfx::Size(640, 480); @@ -237,7 +286,8 @@ vea()->SetEncodingCallback(base::BindLambdaForTesting( [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) { #if defined(OS_LINUX) || defined(OS_CHROMEOS) - EXPECT_EQ(frame->format(), pixel_format); + EXPECT_EQ(frame->format(), + IsYuvPlanar(pixel_format) ? pixel_format : PIXEL_FORMAT_I420); #else // Everywhere except on Linux resize switches frame into CPU mode. EXPECT_EQ(frame->format(), PIXEL_FORMAT_I420); @@ -280,7 +330,8 @@ vea()->SetEncodingCallback(base::BindLambdaForTesting( [&](BitstreamBuffer&, bool keyframe, scoped_refptr<VideoFrame> frame) { - EXPECT_EQ(frame->format(), pixel_format); + EXPECT_EQ(frame->format(), + IsYuvPlanar(pixel_format) ? pixel_format : PIXEL_FORMAT_I420); EXPECT_EQ(frame->coded_size(), options.frame_size); return BitstreamBufferMetadata(1, keyframe, frame->timestamp()); })); @@ -295,13 +346,17 @@ size = small_size; else size = same_size; - auto create_func = - (frame_index & 4) - ? &VideoEncodeAcceleratorAdapterTest::CreateGreenGpuFrame - : &VideoEncodeAcceleratorAdapterTest::CreateGreenCpuFrame; + + // Every 4 frames switch between the 3 supported formats. + const int rem = frame_index % 12; + auto format = PIXEL_FORMAT_XRGB; + if (rem < 4) + format = PIXEL_FORMAT_I420; + else if (rem < 8) + format = PIXEL_FORMAT_NV12; bool key = frame_index % 9 == 0; - auto frame = (this->*create_func)( - size, base::TimeDelta::FromMilliseconds(frame_index)); + auto frame = CreateGreenFrame( + size, format, base::TimeDelta::FromMilliseconds(frame_index)); adapter()->Encode(frame, key, ValidatingStatusCB()); } @@ -312,6 +367,7 @@ INSTANTIATE_TEST_SUITE_P(VideoEncodeAcceleratorAdapterTest, VideoEncodeAcceleratorAdapterTest, ::testing::Values(PIXEL_FORMAT_I420, - PIXEL_FORMAT_NV12)); + PIXEL_FORMAT_NV12, + PIXEL_FORMAT_XRGB)); } // namespace media
diff --git a/media/video/vpx_video_encoder.cc b/media/video/vpx_video_encoder.cc index e1eea9b..1a9dad2 100644 --- a/media/video/vpx_video_encoder.cc +++ b/media/video/vpx_video_encoder.cc
@@ -251,8 +251,12 @@ "No frame provided for encoding.")); return; } - bool supported_format = (frame->format() == PIXEL_FORMAT_NV12) || - (frame->format() == PIXEL_FORMAT_I420); + bool supported_format = frame->format() == PIXEL_FORMAT_NV12 || + frame->format() == PIXEL_FORMAT_I420 || + frame->format() == PIXEL_FORMAT_XBGR || + frame->format() == PIXEL_FORMAT_XRGB || + frame->format() == PIXEL_FORMAT_ABGR || + frame->format() == PIXEL_FORMAT_ARGB; if ((!frame->IsMappable() && !frame->HasGpuMemoryBuffer()) || !supported_format) { status = @@ -273,10 +277,12 @@ } } - if (frame->visible_rect().size() != options_.frame_size) { + const bool is_yuv = IsYuvPlanar(frame->format()); + if (frame->visible_rect().size() != options_.frame_size || !is_yuv) { auto resized_frame = frame_pool_.CreateFrame( - frame->format(), options_.frame_size, gfx::Rect(options_.frame_size), - options_.frame_size, frame->timestamp()); + is_yuv ? frame->format() : PIXEL_FORMAT_I420, options_.frame_size, + gfx::Rect(options_.frame_size), options_.frame_size, + frame->timestamp()); if (resized_frame) { status = ConvertAndScaleFrame(*frame, *resized_frame, resize_buf_); } else {
diff --git a/mojo/public/java/base/src/org/chromium/mojo_base/BigBufferUtil.java b/mojo/public/java/base/src/org/chromium/mojo_base/BigBufferUtil.java index 1256bbb..1190493 100644 --- a/mojo/public/java/base/src/org/chromium/mojo_base/BigBufferUtil.java +++ b/mojo/public/java/base/src/org/chromium/mojo_base/BigBufferUtil.java
@@ -18,6 +18,33 @@ public final class BigBufferUtil { public static final int MAX_INLINE_ARRAY_SIZE = 64 * 1024; + /** + * A mapping to a BigBuffer. + * + * If it is backed by shared memory, this will be a direct mapping which must be closed and will + * be invalid thereafter. The simplest way to do this is by using try-with-resources. + */ + public static class Mapping implements AutoCloseable { + private final SharedBufferHandle mHandle; + private final ByteBuffer mBuffer; + + Mapping(SharedBufferHandle handle, ByteBuffer buffer) { + mHandle = handle; + mBuffer = buffer; + } + + public ByteBuffer getBuffer() { + return mBuffer; + } + + @Override + public void close() { + if (mHandle != null) { + mHandle.unmap(mBuffer); + } + } + } + // Retrives a copy of the buffer's contents regardless of what type was backing it (i.e. array // or shared memory). public static byte[] getBytesFromBigBuffer(BigBuffer buffer) { @@ -34,6 +61,20 @@ } } + // Opens a mapping to an existing buffer for direct reading, without a copy. + // This must be used with a try-with-resources so that close is called to prevent a leak. + // The direct buffer must not be used after close is called. + public static Mapping map(BigBuffer buffer) { + if (buffer.which() == BigBuffer.Tag.Bytes) { + return new Mapping(null, ByteBuffer.wrap(buffer.getBytes())); + } else { + BigBufferSharedMemoryRegion region = buffer.getSharedMemory(); + ByteBuffer byteBuffer = + region.bufferHandle.map(0, region.size, SharedBufferHandle.MapFlags.NONE); + return new Mapping(region.bufferHandle, byteBuffer); + } + } + // Creates a new mojom.BigBuffer for IPC from a set of bytes. If the byte array is larger than // MAX_INLINE_ARRAY_SIZE, shared memory will be used instead of an inline array. public static BigBuffer createBigBufferFromBytes(byte[] bytes) {
diff --git a/mojo/public/tools/mojom/mojom_parser.py b/mojo/public/tools/mojom/mojom_parser.py index 2a6261ce..453cebd 100755 --- a/mojo/public/tools/mojom/mojom_parser.py +++ b/mojo/public/tools/mojom/mojom_parser.py
@@ -15,6 +15,7 @@ import errno import json import logging +import multiprocessing import os import os.path import sys @@ -26,6 +27,10 @@ from mojom.parse import conditional_features +# Disable this for easier debugging. +ENABLE_MULTIPROCESSING = True + + def _ResolveRelativeImportPath(path, roots): """Attempts to resolve a relative import path against a set of possible roots. @@ -157,6 +162,56 @@ return allowed_imports +# multiprocessing helper. +def _ParseAstHelper(args): + mojom_abspath, enabled_features = args + with codecs.open(mojom_abspath, encoding='utf-8') as f: + ast = parser.Parse(f.read(), mojom_abspath) + conditional_features.RemoveDisabledDefinitions(ast, enabled_features) + return mojom_abspath, ast + + +# multiprocessing helper. +def _SerializeHelper(args): + mojom_abspath, mojom_path = args + module_path = os.path.join(_SerializeHelper.output_root_path, + _GetModuleFilename(mojom_path)) + module_dir = os.path.dirname(module_path) + if not os.path.exists(module_dir): + try: + # Python 2 doesn't support exist_ok on makedirs(), so we just ignore + # that failure if it happens. It's possible during build due to races + # among build steps with module outputs in the same directory. + os.makedirs(module_dir) + except OSError as e: + if e.errno != errno.EEXIST: + raise + with open(module_path, 'wb') as f: + _SerializeHelper.loaded_modules[mojom_abspath].Dump(f) + + +def _Shard(target_func, args, processes=None): + args = list(args) + if processes is None: + processes = multiprocessing.cpu_count() + # Seems optimal to have each process perform at least 2 tasks. + processes = min(processes, len(args) // 2) + # Don't spin up processes unless there is enough work to merit doing so. + if not ENABLE_MULTIPROCESSING or processes < 2: + for result in map(target_func, args): + yield result + return + + pool = multiprocessing.Pool(processes=processes) + try: + for result in pool.imap_unordered(target_func, args): + yield result + finally: + pool.close() + pool.join() # Needed on Windows to avoid WindowsError during terminate. + pool.terminate() + + def _ParseMojoms(mojom_files, input_root_paths, output_root_path, @@ -194,14 +249,14 @@ mojom_files_to_parse = dict((os.path.normcase(abs_path), _RebaseAbsolutePath(abs_path, input_root_paths)) for abs_path in mojom_files) - logging.info('Parsing %d .mojom into ASTs', len(mojom_files_to_parse)) abs_paths = dict( (path, abs_path) for abs_path, path in mojom_files_to_parse.items()) - for mojom_abspath in mojom_files_to_parse: - with codecs.open(mojom_abspath, encoding='utf-8') as f: - ast = parser.Parse(''.join(f.readlines()), mojom_abspath) - conditional_features.RemoveDisabledDefinitions(ast, enabled_features) - loaded_mojom_asts[mojom_abspath] = ast + + logging.info('Parsing %d .mojom into ASTs', len(mojom_files_to_parse)) + map_args = ((mojom_abspath, enabled_features) + for mojom_abspath in mojom_files_to_parse) + for mojom_abspath, ast in _Shard(_ParseAstHelper, map_args): + loaded_mojom_asts[mojom_abspath] = ast logging.info('Processing dependencies') for mojom_abspath, ast in loaded_mojom_asts.items(): @@ -249,21 +304,18 @@ # Now we have fully translated modules for every input and every transitive # dependency. We can dump the modules to disk for other tools to use. - logging.info('Serializeing %d modules', len(mojom_files_to_parse)) - for mojom_abspath, mojom_path in mojom_files_to_parse.items(): - module_path = os.path.join(output_root_path, _GetModuleFilename(mojom_path)) - module_dir = os.path.dirname(module_path) - if not os.path.exists(module_dir): - try: - # Python 2 doesn't support exist_ok on makedirs(), so we just ignore - # that failure if it happens. It's possible during build due to races - # among build steps with module outputs in the same directory. - os.makedirs(module_dir) - except OSError as e: - if e.errno != errno.EEXIST: - raise - with open(module_path, 'wb') as f: - loaded_modules[mojom_abspath].Dump(f) + logging.info('Serializing %d modules', len(mojom_files_to_parse)) + + # Windows does not use fork() for multiprocessing, so we'd need to pass + # loaded_module via IPC rather than via globals. Doing so is slower than not + # using multiprocessing. + _SerializeHelper.loaded_modules = loaded_modules + _SerializeHelper.output_root_path = output_root_path + # Doesn't seem to help past 4. Perhaps IO bound here? + processes = 0 if sys.platform == 'win32' else 4 + map_args = mojom_files_to_parse.items() + for _ in _Shard(_SerializeHelper, map_args, processes=processes): + pass def Run(command_line):
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index 9b8297d..696a380 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -63,6 +63,7 @@ #include "base/strings/stringprintf.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/process_memory_dump.h" +#include "net/base/isolation_info.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/url_util.h" #include "net/cookies/canonical_cookie.h" @@ -1018,6 +1019,10 @@ if (cookie_ptr->IsSameParty()) { UMA_HISTOGRAM_BOOLEAN("Cookie.SamePartyReadIncluded.IsHTTP", !options.exclude_httponly()); + UMA_HISTOGRAM_EXACT_LINEAR( + "Cookie.SamePartyReadIncluded.PartyContextSize", + options.full_party_context_size(), + 1 + IsolationInfo::kPartyContextMaxSize); } included_cookies->push_back({*cookie_ptr, access_result}); @@ -1236,7 +1241,11 @@ if (cc->IsSameParty()) { UMA_HISTOGRAM_BOOLEAN("Cookie.SamePartySetIncluded.IsHTTP", !options.exclude_httponly()); + UMA_HISTOGRAM_EXACT_LINEAR("Cookie.SamePartySetIncluded.PartyContextSize", + options.full_party_context_size(), + 1 + IsolationInfo::kPartyContextMaxSize); } + // Realize that we might be setting an expired cookie, and the only point // was to delete the cookie which we've already done. if (!already_expired) {
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index 15649f2..3ada2318 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc
@@ -121,10 +121,14 @@ constexpr char kJSProgressPercentage[] = "progress"; // Document print preview loaded (Plugin -> Page) constexpr char kJSPreviewLoadedType[] = "printPreviewLoaded"; -// Metadata +// Attachments (Plugin -> Page) +constexpr char kJSAttachmentsType[] = "attachments"; +constexpr char kJSAttachmentsData[] = "attachmentsData"; +// Bookmarks (Plugin -> Page) +constexpr char kJSBookmarksType[] = "bookmarks"; +constexpr char kJSBookmarksData[] = "bookmarksData"; +// Metadata (Plugin -> Page) constexpr char kJSMetadataType[] = "metadata"; -constexpr char kJSAttachments[] = "attachments"; -constexpr char kJSBookmarks[] = "bookmarks"; constexpr char kJSTitle[] = "title"; constexpr char kJSCanSerializeDocument[] = "canSerializeDocument"; // Get password (Plugin -> Page) @@ -1615,7 +1619,9 @@ OnGeometryChanged(0, 0); } - SendDocumentMetadata(); + SendAttachments(); + SendBookmarks(); + SendMetadata(); SendLoadingProgress(/*percentage=*/100); if (accessibility_state_ == ACCESSIBILITY_STATE_PENDING) @@ -2339,7 +2345,32 @@ PostMessage(loaded_message); } -void OutOfProcessInstance::SendDocumentMetadata() { +void OutOfProcessInstance::SendAttachments() { + pp::VarArray attachments = GetDocumentAttachments(); + if (attachments.GetLength() == 0) + return; + + pp::VarDictionary attachments_message; + attachments_message.Set(pp::Var(kType), pp::Var(kJSAttachmentsType)); + attachments_message.Set(pp::Var(kJSAttachmentsData), attachments); + + PostMessage(attachments_message); +} + +void OutOfProcessInstance::SendBookmarks() { + base::Value bookmarks = engine()->GetBookmarks(); + DCHECK(bookmarks.is_list()); + if (bookmarks.GetList().empty()) + return; + + pp::VarDictionary bookmarks_message; + bookmarks_message.Set(pp::Var(kType), pp::Var(kJSBookmarksType)); + bookmarks_message.Set(pp::Var(kJSBookmarksData), VarFromValue(bookmarks)); + + PostMessage(bookmarks_message); +} + +void OutOfProcessInstance::SendMetadata() { pp::VarDictionary metadata_message; metadata_message.Set(pp::Var(kType), pp::Var(kJSMetadataType)); @@ -2347,12 +2378,6 @@ if (!base::TrimWhitespace(base::UTF8ToUTF16(title), base::TRIM_ALL).empty()) metadata_message.Set(pp::Var(kJSTitle), pp::Var(title)); - metadata_message.Set(pp::Var(kJSAttachments), GetDocumentAttachments()); - - base::Value bookmarks = engine()->GetBookmarks(); - DCHECK(bookmarks.is_list()); - metadata_message.Set(pp::Var(kJSBookmarks), VarFromValue(bookmarks)); - metadata_message.Set( pp::Var(kJSCanSerializeDocument), pp::Var(IsSaveDataSizeValid(engine()->GetLoadedByteSize())));
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h index 985cdd5..d66a82a 100644 --- a/pdf/out_of_process_instance.h +++ b/pdf/out_of_process_instance.h
@@ -278,8 +278,14 @@ // Send a notification that the print preview has loaded. void SendPrintPreviewLoadedNotification(); - // Send document metadata. (e.g. PDF title, attachments and bookmarks.) - void SendDocumentMetadata(); + // Send attachments. + void SendAttachments(); + + // Send bookmarks. + void SendBookmarks(); + + // Send document metadata. + void SendMetadata(); // Send the loading progress, where |percentage| represents the progress, or // -1 for loading error.
diff --git a/pdf/ppapi_migration/geometry_conversions.cc b/pdf/ppapi_migration/geometry_conversions.cc index de989c5..744e12d8 100644 --- a/pdf/ppapi_migration/geometry_conversions.cc +++ b/pdf/ppapi_migration/geometry_conversions.cc
@@ -55,12 +55,4 @@ return PP_MakeSize(size.width(), size.height()); } -gfx::Vector2d VectorFromPPPoint(const PP_Point& pp_point) { - return gfx::Vector2d(pp_point.x, pp_point.y); -} - -PP_Point PPPointFromVector(const gfx::Vector2d& vector) { - return PP_MakePoint(vector.x(), vector.y()); -} - } // namespace chrome_pdf
diff --git a/pdf/ppapi_migration/geometry_conversions.h b/pdf/ppapi_migration/geometry_conversions.h index a495d59..576dc52b 100644 --- a/pdf/ppapi_migration/geometry_conversions.h +++ b/pdf/ppapi_migration/geometry_conversions.h
@@ -17,7 +17,6 @@ class Rect; class RectF; class Size; -class Vector2d; } // namespace gfx namespace chrome_pdf { @@ -36,9 +35,6 @@ gfx::Size SizeFromPPSize(const PP_Size& pp_size); PP_Size PPSizeFromSize(const gfx::Size& size); -gfx::Vector2d VectorFromPPPoint(const PP_Point& pp_point); -PP_Point PPPointFromVector(const gfx::Vector2d& vector); - } // namespace chrome_pdf #endif // PDF_PPAPI_MIGRATION_GEOMETRY_CONVERSIONS_H_
diff --git a/pdf/ppapi_migration/geometry_conversions_unittest.cc b/pdf/ppapi_migration/geometry_conversions_unittest.cc index 598e813..19ff4ee 100644 --- a/pdf/ppapi_migration/geometry_conversions_unittest.cc +++ b/pdf/ppapi_migration/geometry_conversions_unittest.cc
@@ -112,22 +112,4 @@ EXPECT_EQ(pp_c_size.height, 3); } -TEST(GeometryConversionsTest, VectorFromPPPoint) { - gfx::Vector2d point = VectorFromPPPoint(pp::Point(-1, 2)); - EXPECT_EQ(point, gfx::Vector2d(-1, 2)); - - point = VectorFromPPPoint(PP_MakePoint(2, -1)); - EXPECT_EQ(point, gfx::Vector2d(2, -1)); -} - -TEST(GeometryConversionsTest, PPPointFromVector) { - pp::Point pp_cpp_point = PPPointFromVector(gfx::Vector2d(-1, 2)); - EXPECT_EQ(pp_cpp_point.x(), -1); - EXPECT_EQ(pp_cpp_point.y(), 2); - - PP_Point pp_c_point = PPPointFromVector(gfx::Vector2d(2, -1)); - EXPECT_EQ(pp_c_point.x, 2); - EXPECT_EQ(pp_c_point.y, -1); -} - } // namespace chrome_pdf
diff --git a/pdf/ppapi_migration/graphics.cc b/pdf/ppapi_migration/graphics.cc index 7595f74..73b19a8 100644 --- a/pdf/ppapi_migration/graphics.cc +++ b/pdf/ppapi_migration/graphics.cc
@@ -62,7 +62,8 @@ void PepperGraphics::Scroll(const gfx::Rect& clip, const gfx::Vector2d& amount) { - pepper_graphics_.Scroll(PPRectFromRect(clip), PPPointFromVector(amount)); + pepper_graphics_.Scroll(PPRectFromRect(clip), + pp::Point(amount.x(), amount.y())); } void PepperGraphics::SetScale(float scale) { @@ -74,7 +75,7 @@ const gfx::Point& origin, const gfx::Vector2d& translate) { bool result = pepper_graphics_.SetLayerTransform( - scale, PPPointFromPoint(origin), PPPointFromVector(translate)); + scale, PPPointFromPoint(origin), pp::Point(translate.x(), translate.y())); DCHECK(result); }
diff --git a/services/device/hid/hid_connection_win.cc b/services/device/hid/hid_connection_win.cc index bc0d77b..3d49007d 100644 --- a/services/device/hid/hid_connection_win.cc +++ b/services/device/hid/hid_connection_win.cc
@@ -229,10 +229,15 @@ scoped_refptr<base::RefCountedBytes> buffer, PendingHidTransfer* transfer_raw, bool signaled) { - std::unique_ptr<PendingHidTransfer> transfer = UnlinkTransfer(transfer_raw); + if (!signaled) { + HID_LOG(DEBUG) << "HID read failed."; + return; + } + + auto transfer = UnlinkTransfer(transfer_raw); DWORD bytes_transferred; - if (!signaled || !GetOverlappedResult(file_handle, transfer->GetOverlapped(), - &bytes_transferred, FALSE)) { + if (!GetOverlappedResult(file_handle, transfer->GetOverlapped(), + &bytes_transferred, FALSE)) { HID_PLOG(DEBUG) << "HID read failed"; return; } @@ -243,16 +248,13 @@ } uint8_t report_id = buffer->data()[0]; - if (IsReportIdProtected(report_id, HidReportType::kInput)) { - ReadNextInputReportOnHandle(file_handle); - return; + if (!IsReportIdProtected(report_id, HidReportType::kInput)) { + // Hold a reference to |this| to prevent a callback executed by + // ProcessInputReport from freeing this object. + scoped_refptr<HidConnection> self(this); + ProcessInputReport(buffer, bytes_transferred); } - // Hold a reference to |this| to prevent a callback executed by - // ProcessInputReport from freeing this object. - scoped_refptr<HidConnection> self(this); - ProcessInputReport(buffer, bytes_transferred); - ReadNextInputReportOnHandle(file_handle); } @@ -262,31 +264,45 @@ ReadCallback callback, PendingHidTransfer* transfer_raw, bool signaled) { - std::unique_ptr<PendingHidTransfer> transfer = UnlinkTransfer(transfer_raw); + if (!signaled) { + HID_LOG(DEBUG) << "HID read failed."; + std::move(callback).Run(false, nullptr, 0); + return; + } + + auto transfer = UnlinkTransfer(transfer_raw); DWORD bytes_transferred; - if (signaled && GetOverlappedResult(file_handle, transfer->GetOverlapped(), - &bytes_transferred, FALSE)) { - DCHECK_LE(bytes_transferred, buffer->size()); - std::move(callback).Run(true, buffer, bytes_transferred); - } else { + if (!GetOverlappedResult(file_handle, transfer->GetOverlapped(), + &bytes_transferred, FALSE)) { HID_PLOG(DEBUG) << "HID read failed"; std::move(callback).Run(false, nullptr, 0); + return; } + + DCHECK_LE(bytes_transferred, buffer->size()); + std::move(callback).Run(true, buffer, bytes_transferred); } void HidConnectionWin::OnWriteComplete(HANDLE file_handle, WriteCallback callback, PendingHidTransfer* transfer_raw, bool signaled) { - std::unique_ptr<PendingHidTransfer> transfer = UnlinkTransfer(transfer_raw); + if (!signaled) { + HID_LOG(DEBUG) << "HID write failed."; + std::move(callback).Run(false); + return; + } + + auto transfer = UnlinkTransfer(transfer_raw); DWORD bytes_transferred; - if (signaled && GetOverlappedResult(file_handle, transfer->GetOverlapped(), - &bytes_transferred, FALSE)) { - std::move(callback).Run(true); - } else { + if (!GetOverlappedResult(file_handle, transfer->GetOverlapped(), + &bytes_transferred, FALSE)) { HID_PLOG(DEBUG) << "HID write failed"; std::move(callback).Run(false); + return; } + + std::move(callback).Run(true); } std::unique_ptr<PendingHidTransfer> HidConnectionWin::UnlinkTransfer(
diff --git a/services/device/hid/hid_service_win.cc b/services/device/hid/hid_service_win.cc index e6180f2..4cea399 100644 --- a/services/device/hid/hid_service_win.cc +++ b/services/device/hid/hid_service_win.cc
@@ -715,7 +715,10 @@ // Create a HidCollectionInfo for |device_path| and update the relevant // HidDeviceInfo properties. auto collection = preparsed_data->CreateHidCollectionInfo(); - platform_device_id_map.emplace_back(collection->report_ids, device_path); + if (collection->report_ids.empty()) + platform_device_id_map.emplace_back(std::vector<uint8_t>{0}, device_path); + else + platform_device_id_map.emplace_back(collection->report_ids, device_path); collections.push_back(std::move(collection)); max_input_report_size = std::max( max_input_report_size, preparsed_data->GetReportByteLength(HidP_Input));
diff --git a/services/network/public/mojom/trust_tokens.mojom b/services/network/public/mojom/trust_tokens.mojom index f002cf7..2928c095 100644 --- a/services/network/public/mojom/trust_tokens.mojom +++ b/services/network/public/mojom/trust_tokens.mojom
@@ -247,6 +247,8 @@ // because the Java bindings append the suffix "Response" when generating // callback names. struct FulfillTrustTokenIssuanceAnswer { + // WARNING: Since these values are committed to histograms, please do not + // remove or reorder entries. enum Status { kOk, // It wasn't possible to route the issuance operation to the specified
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper.cc b/services/network/trust_tokens/trust_token_request_issuance_helper.cc index 11700bcd..5dfe0982 100644 --- a/services/network/trust_tokens/trust_token_request_issuance_helper.cc +++ b/services/network/trust_tokens/trust_token_request_issuance_helper.cc
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/command_line.h" #include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_functions.h" #include "base/stl_util.h" #include "base/task/thread_pool.h" #include "net/base/load_flags.h" @@ -351,6 +352,8 @@ void TrustTokenRequestIssuanceHelper::DoneRequestingLocallyFulfilledIssuance( base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done, mojom::FulfillTrustTokenIssuanceAnswerPtr answer) { + base::UmaHistogramEnumeration( + "Net.TrustTokens.IssuanceHelperLocalFulfillResult", answer->status); switch (answer->status) { case mojom::FulfillTrustTokenIssuanceAnswer::Status::kNotFound: { std::move(done).Run(mojom::TrustTokenOperationStatus::kUnavailable);
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc index bc22fc3..d949df57 100644 --- a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc +++ b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/no_destructor.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "build/build_config.h" @@ -694,6 +695,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, DiversionToOsSuccess) { + base::HistogramTester histograms; + // When an operation's diverted to the operating system and succeeds, we // should report kOperationSuccessfullyFulfilledLocally. std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); @@ -761,6 +764,11 @@ EXPECT_THAT( store->RetrieveMatchingTokens(issuer, std::move(match_all_keys)), ElementsAre(Property(&TrustToken::body, "a signed, unblinded token"))); + + histograms.ExpectUniqueSample( + "Net.TrustTokens.IssuanceHelperLocalFulfillResult", + mojom::FulfillTrustTokenIssuanceAnswer::Status::kOk, + /*expected_count=*/1); } TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, @@ -900,6 +908,8 @@ TEST_F(TrustTokenRequestIssuanceHelperTestWithPlatformIssuance, DivertsToAndroidOnAndroid) { + base::HistogramTester histograms; + // Test that, when an issuer specifies that we should attempt issuance locally // on Android, we do so. std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting(); @@ -962,6 +972,13 @@ mojom::TrustTokenOperationStatus::kUnavailable #endif // defined(OS_ANDROID) ); + +#if defined(OS_ANDROID) + histograms.ExpectUniqueSample( + "Net.TrustTokens.IssuanceHelperLocalFulfillResult", + mojom::FulfillTrustTokenIssuanceAnswer::Status::kUnknownError, + /*expected_count=*/1); +#endif // defined(OS_ANDROID) } } // namespace network
diff --git a/services/shape_detection/android/java/src/org/chromium/shape_detection/BitmapUtils.java b/services/shape_detection/android/java/src/org/chromium/shape_detection/BitmapUtils.java index ac4ce59..38a2d26 100644 --- a/services/shape_detection/android/java/src/org/chromium/shape_detection/BitmapUtils.java +++ b/services/shape_detection/android/java/src/org/chromium/shape_detection/BitmapUtils.java
@@ -32,16 +32,16 @@ return null; } - ByteBuffer imageBuffer = - ByteBuffer.wrap(BigBufferUtil.getBytesFromBigBuffer(bitmapData.pixelData)); - if (imageBuffer.capacity() <= 0) { - return null; + try (BigBufferUtil.Mapping mapping = BigBufferUtil.map(bitmapData.pixelData)) { + ByteBuffer imageBuffer = mapping.getBuffer(); + if (imageBuffer.capacity() <= 0) { + return null; + } + + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.copyPixelsFromBuffer(imageBuffer); + return bitmap; } - - Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bitmap.copyPixelsFromBuffer(imageBuffer); - - return bitmap; } public static Frame convertToFrame(org.chromium.skia.mojom.BitmapN32 bitmapData) {
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom index 8ede898..ee3bc6c 100644 --- a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom +++ b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
@@ -9,6 +9,7 @@ import "mojo/public/mojom/base/time.mojom"; import "mojo/public/mojom/base/shared_memory.mojom"; import "services/viz/public/mojom/compositing/frame_sink_id.mojom"; +import "services/viz/public/mojom/compositing/subtree_capture_id.mojom"; import "skia/public/mojom/bitmap.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; import "ui/gfx/mojom/color_space.mojom"; @@ -117,9 +118,13 @@ SetAutoThrottlingEnabled(bool enabled); // Targets a different compositor frame sink. This may be called anytime, - // before or after Start(). If the argument is null, capture will suspend - // until a new frame sink target is set. - ChangeTarget(FrameSinkId? frame_sink_id); + // before or after Start(). If |frame_sink_id| is null, capture will suspend + // until a new frame sink target is set. If the given |subtree_capture_id| is + // valid, the capturer will capture a render pass associated with a layer + // subtree under the target frame sink, which is identifiable by that + // |subtree_capture_id|. Otherwise, the capturer captures the root render pass + // of the target frame sink. + ChangeTarget(FrameSinkId? frame_sink_id, SubtreeCaptureId subtree_capture_id); // Starts emitting video frames to the given |consumer|. Start(pending_remote<FrameSinkVideoConsumer> consumer);
diff --git a/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc b/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc index 4f939e7..6b428e9 100644 --- a/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc +++ b/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.cc
@@ -8,6 +8,7 @@ #include "components/viz/common/quads/compositor_render_pass.h" #include "services/viz/public/cpp/compositing/compositor_render_pass_id_mojom_traits.h" #include "services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h" +#include "services/viz/public/cpp/compositing/subtree_capture_id_mojom_traits.h" #include "services/viz/public/cpp/crash_keys.h" #include "ui/gfx/mojom/display_color_spaces_mojom_traits.h" @@ -25,6 +26,7 @@ !data.ReadFilters(&(*out)->filters) || !data.ReadBackdropFilters(&(*out)->backdrop_filters) || !data.ReadBackdropFilterBounds(&(*out)->backdrop_filter_bounds) || + !data.ReadSubtreeCaptureId(&(*out)->subtree_capture_id) || !data.ReadCopyRequests(&(*out)->copy_requests) || !data.ReadId(&(*out)->id)) { return false;
diff --git a/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h b/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h index cf79f2b..cbb5a81 100644 --- a/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h +++ b/services/viz/public/cpp/compositing/compositor_render_pass_mojom_traits.h
@@ -10,6 +10,7 @@ #include "base/check.h" #include "components/viz/common/quads/compositor_render_pass.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "services/viz/public/cpp/compositing/copy_output_request_mojom_traits.h" #include "services/viz/public/cpp/compositing/quads_mojom_traits.h" #include "services/viz/public/mojom/compositing/compositor_render_pass.mojom-shared.h" @@ -58,6 +59,11 @@ return input->backdrop_filter_bounds; } + static viz::SubtreeCaptureId subtree_capture_id( + const std::unique_ptr<viz::CompositorRenderPass>& input) { + return input->subtree_capture_id; + } + static bool has_transparent_background( const std::unique_ptr<viz::CompositorRenderPass>& input) { return input->has_transparent_background;
diff --git a/services/viz/public/cpp/compositing/mojom_traits_perftest.cc b/services/viz/public/cpp/compositing/mojom_traits_perftest.cc index a740cc7..b7ba834 100644 --- a/services/viz/public/cpp/compositing/mojom_traits_perftest.cc +++ b/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
@@ -10,6 +10,7 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/texture_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/test/compositor_frame_helpers.h" #include "gpu/ipc/common/mailbox_holder_mojom_traits.h" #include "gpu/ipc/common/mailbox_mojom_traits.h" @@ -208,8 +209,8 @@ auto pass_in = CompositorRenderPass::Create(); pass_in->SetAll(root_id, arbitrary_rect1, arbitrary_rect2, arbitrary_matrix1, arbitrary_filters2, arbitrary_filters1, - arbitrary_rrectf1, arbitrary_bool1, arbitrary_bool1, - arbitrary_bool1, arbitrary_bool1); + arbitrary_rrectf1, SubtreeCaptureId(), arbitrary_bool1, + arbitrary_bool1, arbitrary_bool1, arbitrary_bool1); // Texture quads for (uint32_t i = 0; i < 10; ++i) {
diff --git a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc index 76b3558..4393f48 100644 --- a/services/viz/public/cpp/compositing/mojom_traits_unittest.cc +++ b/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
@@ -17,6 +17,7 @@ #include "components/viz/common/resources/resource_settings.h" #include "components/viz/common/resources/returned_resource.h" #include "components/viz/common/resources/transferable_resource.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/common/surfaces/surface_info.h" #include "components/viz/common/surfaces/surface_range.h" #include "components/viz/test/begin_frame_args_test.h" @@ -704,6 +705,7 @@ backdrop_filters.Append(cc::FilterOperation::CreateSaturateFilter(2.f)); base::Optional<gfx::RRectF> backdrop_filter_bounds( {10, 20, 130, 140, 1, 2, 3, 4, 5, 6, 7, 8}); + SubtreeCaptureId subtree_capture_id{22u}; const bool has_transparent_background = true; const bool cache_render_pass = true; const bool has_damage_from_contributing_content = true; @@ -711,8 +713,9 @@ auto input = CompositorRenderPass::Create(); input->SetAll(render_pass_id, output_rect, damage_rect, transform_to_root, filters, backdrop_filters, backdrop_filter_bounds, - has_transparent_background, cache_render_pass, - has_damage_from_contributing_content, generate_mipmap); + subtree_capture_id, has_transparent_background, + cache_render_pass, has_damage_from_contributing_content, + generate_mipmap); input->copy_requests.push_back(CopyOutputRequest::CreateStubForTesting()); const gfx::Rect copy_output_area(24, 42, 75, 57); input->copy_requests.back()->set_area(copy_output_area); @@ -778,6 +781,7 @@ EXPECT_EQ(filters, output->filters); EXPECT_EQ(backdrop_filters, output->backdrop_filters); EXPECT_EQ(backdrop_filter_bounds, output->backdrop_filter_bounds); + EXPECT_EQ(subtree_capture_id, output->subtree_capture_id); EXPECT_EQ(cache_render_pass, output->cache_render_pass); EXPECT_EQ(has_damage_from_contributing_content, output->has_damage_from_contributing_content); @@ -849,6 +853,7 @@ const gfx::Transform transform_to_root = gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0); const base::Optional<gfx::RRectF> backdrop_filter_bounds; + SubtreeCaptureId subtree_capture_id; const bool has_transparent_background = true; const bool cache_render_pass = false; const bool has_damage_from_contributing_content = false; @@ -856,9 +861,9 @@ auto input = CompositorRenderPass::Create(); input->SetAll(render_pass_id, output_rect, damage_rect, transform_to_root, cc::FilterOperations(), cc::FilterOperations(), - backdrop_filter_bounds, has_transparent_background, - cache_render_pass, has_damage_from_contributing_content, - generate_mipmap); + backdrop_filter_bounds, subtree_capture_id, + has_transparent_background, cache_render_pass, + has_damage_from_contributing_content, generate_mipmap); // Unlike the previous test, don't add any quads to the list; we need to // verify that the serialization code can deal with that. @@ -874,6 +879,8 @@ EXPECT_EQ(damage_rect, output->damage_rect); EXPECT_EQ(transform_to_root, output->transform_to_root_target); EXPECT_EQ(backdrop_filter_bounds, output->backdrop_filter_bounds); + EXPECT_EQ(subtree_capture_id, output->subtree_capture_id); + EXPECT_FALSE(output->subtree_capture_id.is_valid()); EXPECT_EQ(has_transparent_background, output->has_transparent_background); }
diff --git a/services/viz/public/cpp/compositing/subtree_capture_id_mojom_traits.h b/services/viz/public/cpp/compositing/subtree_capture_id_mojom_traits.h new file mode 100644 index 0000000..a9f44c7 --- /dev/null +++ b/services/viz/public/cpp/compositing/subtree_capture_id_mojom_traits.h
@@ -0,0 +1,29 @@ +// Copyright 2020 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 SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_SUBTREE_CAPTURE_ID_MOJOM_TRAITS_H_ +#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_SUBTREE_CAPTURE_ID_MOJOM_TRAITS_H_ + +#include "components/viz/common/surfaces/subtree_capture_id.h" +#include "services/viz/public/mojom/compositing/subtree_capture_id.mojom-shared.h" + +namespace mojo { + +template <> +struct StructTraits<viz::mojom::SubtreeCaptureIdDataView, + viz::SubtreeCaptureId> { + static uint32_t subtree_id(const viz::SubtreeCaptureId& subtree_capture_id) { + return subtree_capture_id.subtree_id(); + } + + static bool Read(viz::mojom::SubtreeCaptureIdDataView data, + viz::SubtreeCaptureId* out) { + *out = viz::SubtreeCaptureId(data.subtree_id()); + return true; + } +}; + +} // namespace mojo + +#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_SUBTREE_CAPTURE_ID_MOJOM_TRAITS_H_
diff --git a/services/viz/public/mojom/BUILD.gn b/services/viz/public/mojom/BUILD.gn index 3dc726d..2d20b18 100644 --- a/services/viz/public/mojom/BUILD.gn +++ b/services/viz/public/mojom/BUILD.gn
@@ -32,6 +32,7 @@ "compositing/returned_resource.mojom", "compositing/selection.mojom", "compositing/shared_quad_state.mojom", + "compositing/subtree_capture_id.mojom", "compositing/surface_id.mojom", "compositing/surface_info.mojom", "compositing/surface_range.mojom", @@ -109,6 +110,16 @@ { types = [ { + mojom = "viz.mojom.SubtreeCaptureId" + cpp = "::viz::SubtreeCaptureId" + }, + ] + traits_headers = [ "//services/viz/public/cpp/compositing/subtree_capture_id_mojom_traits.h" ] + traits_public_deps = [ "//components/viz/common" ] + }, + { + types = [ + { mojom = "viz.mojom.SurfaceId" cpp = "::viz::SurfaceId" },
diff --git a/services/viz/public/mojom/compositing/compositor_render_pass.mojom b/services/viz/public/mojom/compositing/compositor_render_pass.mojom index be3cfa7..1db67c6 100644 --- a/services/viz/public/mojom/compositing/compositor_render_pass.mojom +++ b/services/viz/public/mojom/compositing/compositor_render_pass.mojom
@@ -8,6 +8,7 @@ import "services/viz/public/mojom/compositing/copy_output_request.mojom"; import "services/viz/public/mojom/compositing/filter_operations.mojom"; import "services/viz/public/mojom/compositing/quads.mojom"; +import "services/viz/public/mojom/compositing/subtree_capture_id.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; import "ui/gfx/mojom/rrect_f.mojom"; import "ui/gfx/mojom/transform.mojom"; @@ -21,6 +22,7 @@ FilterOperations filters; FilterOperations backdrop_filters; gfx.mojom.RRectF? backdrop_filter_bounds; + SubtreeCaptureId subtree_capture_id; bool has_transparent_background; bool cache_render_pass = false; bool has_damage_from_contributing_content = false;
diff --git a/services/viz/public/mojom/compositing/subtree_capture_id.mojom b/services/viz/public/mojom/compositing/subtree_capture_id.mojom new file mode 100644 index 0000000..691c6080 --- /dev/null +++ b/services/viz/public/mojom/compositing/subtree_capture_id.mojom
@@ -0,0 +1,10 @@ +// Copyright 2020 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. + +module viz.mojom; + +// See SubtreeCaptureId in components/viz/common/surfaces/subtree_capture_id.h. +struct SubtreeCaptureId { + uint32 subtree_id; +};
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 194f99a..50cf137e 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -240,11 +240,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -254,7 +254,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -317,11 +317,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -331,7 +331,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -394,11 +394,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -408,7 +408,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -471,11 +471,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -485,7 +485,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -769,11 +769,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -783,7 +783,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -846,11 +846,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -860,7 +860,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -923,11 +923,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -937,7 +937,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1000,11 +1000,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -1014,7 +1014,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1298,11 +1298,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -1312,7 +1312,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1375,11 +1375,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -1389,7 +1389,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1452,11 +1452,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -1466,7 +1466,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1529,11 +1529,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -1543,7 +1543,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1827,11 +1827,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -1841,7 +1841,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1904,11 +1904,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Client Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -1918,7 +1918,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1981,11 +1981,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.141", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 87.0.4280.143", "resultdb": { "enable": true }, @@ -1995,7 +1995,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M87", - "revision": "version:87.0.4280.141" + "revision": "version:87.0.4280.143" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -2058,11 +2058,11 @@ "--bucket", "chromium-result-details", "--test-name", - "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76" + "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78" ], "script": "//build/android/pylib/results/presentation/test_results_presentation.py" }, - "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.76", + "name": "weblayer_instrumentation_test_versions_apk_Implementation Tests For 88.0.4324.78", "resultdb": { "enable": true }, @@ -2072,7 +2072,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M88", - "revision": "version:88.0.4324.76" + "revision": "version:88.0.4324.78" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index a25845a..4ffa6340 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -18079,6 +18079,180 @@ "gtest_tests": [ { "args": [ + "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_cardboard_skipdon_setupcomplete.json", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--remove-system-package=com.google.vr.vrcore", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_test_vr_apk-ddready-cardboard" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "chrome_public_test_vr_apk-ddready-cardboard", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "QP1A.190711.020", + "device_os_flavor": "google", + "device_os_type": "userdebug", + "device_type": "marlin", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "chrome_public_test_vr_apk", + "test_id_prefix": "ninja://chrome/android:chrome_public_test_vr_apk/" + }, + { + "args": [ + "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--git-revision=${got_revision}", + "--remove-system-package=com.google.vr.vrcore", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_test_vr_apk-ddready-ddview" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "chrome_public_test_vr_apk-ddready-ddview", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "QP1A.190711.020", + "device_os_flavor": "google", + "device_os_type": "userdebug", + "device_type": "marlin", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chrome-gold@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "chrome_public_test_vr_apk", + "test_id_prefix": "ninja://chrome/android:chrome_public_test_vr_apk/" + }, + { + "args": [ + "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_don_setupcomplete.json", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", + "--annotation=Restriction=VR_DON_Enabled", + "--vr-don-enabled", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--remove-system-package=com.google.vr.vrcore", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "chrome_public_test_vr_apk-ddready-don-enabled" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "chrome_public_test_vr_apk-ddready-don-enabled", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "device_os": "QP1A.190711.020", + "device_os_flavor": "google", + "device_os_type": "userdebug", + "device_type": "marlin", + "os": "Android" + } + ], + "output_links": [ + { + "link": [ + "https://luci-logdog.appspot.com/v/?s", + "=android%2Fswarming%2Flogcats%2F", + "${TASK_ID}%2F%2B%2Funified_logcats" + ], + "name": "shard #${SHARD_INDEX} logcats" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "chrome_public_test_vr_apk", + "test_id_prefix": "ninja://chrome/android:chrome_public_test_vr_apk/" + }, + { + "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices", "--remove-system-package=com.google.ar.core",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 5e8d9b4..1f4778b6 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -34135,7 +34135,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34147,7 +34147,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPhone X 14.2", + "name": "absl_hardening_tests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34180,7 +34180,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34192,7 +34192,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPad Air 2 14.2", + "name": "base_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -34225,7 +34225,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34237,7 +34237,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s Plus 14.2", + "name": "base_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -34270,7 +34270,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34282,7 +34282,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone X 14.2", + "name": "base_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34315,7 +34315,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34327,7 +34327,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPhone X 14.2", + "name": "boringssl_crypto_tests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34360,7 +34360,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34372,7 +34372,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPhone X 14.2", + "name": "boringssl_ssl_tests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34405,7 +34405,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34417,7 +34417,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPad Air 2 14.2", + "name": "components_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -34450,7 +34450,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34462,7 +34462,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s Plus 14.2", + "name": "components_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -34495,7 +34495,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34507,7 +34507,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone X 14.2", + "name": "components_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34540,7 +34540,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34552,7 +34552,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPhone X 14.2", + "name": "crypto_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34585,7 +34585,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34597,7 +34597,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPad Air 2 14.2", + "name": "gfx_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -34630,7 +34630,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34642,7 +34642,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s Plus 14.2", + "name": "gfx_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -34675,7 +34675,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34687,7 +34687,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone X 14.2", + "name": "gfx_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34720,7 +34720,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34732,7 +34732,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPhone X 14.2", + "name": "google_apis_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34765,7 +34765,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34778,7 +34778,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_chrome_bookmarks_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -34811,7 +34811,7 @@ "--platform", "iPad Air (3rd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34824,7 +34824,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air (3rd generation) 14.2", + "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air (3rd generation) 14.3", "resultdb": { "enable": true }, @@ -34857,7 +34857,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34870,7 +34870,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -34903,7 +34903,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34916,7 +34916,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -34949,7 +34949,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34962,7 +34962,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_chrome_integration_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -34996,7 +34996,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35009,7 +35009,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -35043,7 +35043,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35056,7 +35056,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_integration_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -35090,7 +35090,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35103,7 +35103,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -35137,7 +35137,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35150,7 +35150,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_chrome_settings_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -35184,7 +35184,7 @@ "--platform", "iPad Air (3rd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35197,7 +35197,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPad Air (3rd generation) 14.2", + "name": "ios_chrome_settings_eg2tests_module_iPad Air (3rd generation) 14.3", "resultdb": { "enable": true }, @@ -35231,7 +35231,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35244,7 +35244,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -35278,7 +35278,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35291,7 +35291,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -35325,7 +35325,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35338,7 +35338,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_chrome_signin_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -35371,7 +35371,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35384,7 +35384,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -35417,7 +35417,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35430,7 +35430,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_signin_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -35463,7 +35463,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35476,7 +35476,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -35509,7 +35509,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35522,7 +35522,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_chrome_smoke_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -35555,7 +35555,7 @@ "--platform", "iPad Air (3rd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35568,7 +35568,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPad Air (3rd generation) 14.2", + "name": "ios_chrome_smoke_eg2tests_module_iPad Air (3rd generation) 14.3", "resultdb": { "enable": true }, @@ -35601,7 +35601,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35614,7 +35614,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -35647,7 +35647,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35660,7 +35660,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -35693,7 +35693,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35706,7 +35706,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_chrome_ui_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -35740,7 +35740,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35753,7 +35753,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -35787,7 +35787,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35800,7 +35800,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_ui_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -35834,7 +35834,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35847,7 +35847,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -35881,7 +35881,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35893,7 +35893,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPad Air 2 14.2", + "name": "ios_chrome_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -35926,7 +35926,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35938,7 +35938,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s Plus 14.2", + "name": "ios_chrome_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -35971,7 +35971,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35983,7 +35983,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone X 14.2", + "name": "ios_chrome_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36016,7 +36016,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36029,7 +36029,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_chrome_web_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -36062,7 +36062,7 @@ "--platform", "iPad Air (3rd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36075,7 +36075,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPad Air (3rd generation) 14.2", + "name": "ios_chrome_web_eg2tests_module_iPad Air (3rd generation) 14.3", "resultdb": { "enable": true }, @@ -36108,7 +36108,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36121,7 +36121,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -36154,7 +36154,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36167,7 +36167,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_web_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36200,7 +36200,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36212,7 +36212,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPhone X 14.2", + "name": "ios_components_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36245,7 +36245,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36257,7 +36257,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPhone X 14.2", + "name": "ios_net_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36290,7 +36290,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36302,7 +36302,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPhone X 14.2", + "name": "ios_remoting_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36335,7 +36335,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36348,7 +36348,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_showcase_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -36381,7 +36381,7 @@ "--platform", "iPad Air (3rd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36394,7 +36394,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPad Air (3rd generation) 14.2", + "name": "ios_showcase_eg2tests_module_iPad Air (3rd generation) 14.3", "resultdb": { "enable": true }, @@ -36427,7 +36427,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36440,7 +36440,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone 7 14.2", + "name": "ios_showcase_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -36473,7 +36473,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36486,7 +36486,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone X 14.2", + "name": "ios_showcase_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36519,7 +36519,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36531,7 +36531,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPhone X 14.2", + "name": "ios_testing_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36564,7 +36564,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36576,7 +36576,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPad Air 2 14.2", + "name": "ios_web_inttests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -36609,7 +36609,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36621,7 +36621,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s Plus 14.2", + "name": "ios_web_inttests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -36654,7 +36654,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36666,7 +36666,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone X 14.2", + "name": "ios_web_inttests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36699,7 +36699,7 @@ "--platform", "iPad (6th generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36712,7 +36712,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad (6th generation) 14.2", + "name": "ios_web_shell_eg2tests_module_iPad (6th generation) 14.3", "resultdb": { "enable": true }, @@ -36745,7 +36745,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36758,7 +36758,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -36791,7 +36791,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36804,7 +36804,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone 7 14.2", + "name": "ios_web_shell_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -36837,7 +36837,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36850,7 +36850,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone X 14.2", + "name": "ios_web_shell_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -36883,7 +36883,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36895,7 +36895,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPad Air 2 14.2", + "name": "ios_web_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -36928,7 +36928,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36940,7 +36940,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s Plus 14.2", + "name": "ios_web_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -36973,7 +36973,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -36985,7 +36985,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone X 14.2", + "name": "ios_web_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37018,7 +37018,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37030,7 +37030,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPad Air 2 14.2", + "name": "ios_web_view_inttests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -37063,7 +37063,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37075,7 +37075,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s Plus 14.2", + "name": "ios_web_view_inttests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -37108,7 +37108,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37120,7 +37120,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone X 14.2", + "name": "ios_web_view_inttests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37153,7 +37153,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37165,7 +37165,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPad Air 2 14.2", + "name": "ios_web_view_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -37198,7 +37198,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37210,7 +37210,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s Plus 14.2", + "name": "ios_web_view_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -37243,7 +37243,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37255,7 +37255,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone X 14.2", + "name": "ios_web_view_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37288,7 +37288,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37300,7 +37300,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPhone X 14.2", + "name": "net_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37333,7 +37333,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37345,7 +37345,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPhone X 14.2", + "name": "services_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37378,7 +37378,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37390,7 +37390,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPad Air 2 14.2", + "name": "skia_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -37423,7 +37423,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37435,7 +37435,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s Plus 14.2", + "name": "skia_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -37468,7 +37468,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37480,7 +37480,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone X 14.2", + "name": "skia_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37513,7 +37513,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37525,7 +37525,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPhone X 14.2", + "name": "sql_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37558,7 +37558,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37570,7 +37570,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPad Air 2 14.2", + "name": "ui_base_unittests_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -37603,7 +37603,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37615,7 +37615,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s Plus 14.2", + "name": "ui_base_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -37648,7 +37648,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37660,7 +37660,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone X 14.2", + "name": "ui_base_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37693,7 +37693,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37705,7 +37705,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPhone X 14.2", + "name": "url_unittests_iPhone X 14.3", "resultdb": { "enable": true }, @@ -37745,7 +37745,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37757,7 +37757,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPhone 6s 14.2", + "name": "absl_hardening_tests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -37790,7 +37790,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37802,7 +37802,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s 14.2", + "name": "base_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -37835,7 +37835,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37847,7 +37847,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s Plus 14.2", + "name": "base_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -37880,7 +37880,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37892,7 +37892,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPhone 6s 14.2", + "name": "boringssl_crypto_tests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -37925,7 +37925,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37937,7 +37937,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPhone 6s 14.2", + "name": "boringssl_ssl_tests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -37970,7 +37970,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -37982,7 +37982,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s 14.2", + "name": "components_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -38015,7 +38015,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38027,7 +38027,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s Plus 14.2", + "name": "components_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -38060,7 +38060,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38072,7 +38072,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPhone 6s 14.2", + "name": "crypto_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -38105,7 +38105,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38117,7 +38117,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s 14.2", + "name": "gfx_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -38150,7 +38150,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38162,7 +38162,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s Plus 14.2", + "name": "gfx_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -38195,7 +38195,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38207,7 +38207,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPhone 6s 14.2", + "name": "google_apis_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -38240,7 +38240,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38253,7 +38253,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.2", + "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -38286,7 +38286,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38299,7 +38299,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -38332,7 +38332,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38345,7 +38345,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -38378,7 +38378,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38391,7 +38391,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.2", + "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -38425,7 +38425,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38438,7 +38438,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_chrome_integration_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -38472,7 +38472,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38485,7 +38485,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_integration_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -38519,7 +38519,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38532,7 +38532,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.2", + "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -38566,7 +38566,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38579,7 +38579,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_settings_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -38613,7 +38613,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38626,7 +38626,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_settings_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -38660,7 +38660,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38673,7 +38673,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.2", + "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -38706,7 +38706,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38719,7 +38719,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_chrome_signin_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -38752,7 +38752,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38765,7 +38765,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_signin_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -38798,7 +38798,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38811,7 +38811,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.2", + "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -38844,7 +38844,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38857,7 +38857,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -38890,7 +38890,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38903,7 +38903,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_smoke_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -38936,7 +38936,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38949,7 +38949,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.2", + "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -38983,7 +38983,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -38996,7 +38996,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_chrome_ui_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -39030,7 +39030,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39043,7 +39043,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_ui_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -39077,7 +39077,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39089,7 +39089,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s 14.2", + "name": "ios_chrome_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39122,7 +39122,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39134,7 +39134,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s Plus 14.2", + "name": "ios_chrome_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -39167,7 +39167,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39180,7 +39180,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.2", + "name": "ios_chrome_web_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -39213,7 +39213,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39226,7 +39226,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.2", + "name": "ios_chrome_web_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -39259,7 +39259,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39272,7 +39272,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone X 14.2", + "name": "ios_chrome_web_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -39305,7 +39305,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39317,7 +39317,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPhone 6s 14.2", + "name": "ios_components_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39350,7 +39350,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39362,7 +39362,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPhone 6s 14.2", + "name": "ios_net_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39395,7 +39395,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39407,7 +39407,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPhone 6s 14.2", + "name": "ios_remoting_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39440,7 +39440,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39453,7 +39453,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPad Air 2 14.2", + "name": "ios_showcase_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -39486,7 +39486,7 @@ "--platform", "iPhone 7", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39499,7 +39499,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone 7 14.2", + "name": "ios_showcase_eg2tests_module_iPhone 7 14.3", "resultdb": { "enable": true }, @@ -39532,7 +39532,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39545,7 +39545,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone X 14.2", + "name": "ios_showcase_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -39578,7 +39578,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39590,7 +39590,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPhone 6s 14.2", + "name": "ios_testing_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39623,7 +39623,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39635,7 +39635,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s 14.2", + "name": "ios_web_inttests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39668,7 +39668,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39680,7 +39680,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s Plus 14.2", + "name": "ios_web_inttests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -39713,7 +39713,7 @@ "--platform", "iPad Air 2", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39726,7 +39726,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.2", + "name": "ios_web_shell_eg2tests_module_iPad Air 2 14.3", "resultdb": { "enable": true }, @@ -39759,7 +39759,7 @@ "--platform", "iPad Pro (12.9-inch) (2nd generation)", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39772,7 +39772,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.2", + "name": "ios_web_shell_eg2tests_module_iPad Pro (12.9-inch) (2nd generation) 14.3", "resultdb": { "enable": true }, @@ -39805,7 +39805,7 @@ "--platform", "iPhone X", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39818,7 +39818,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone X 14.2", + "name": "ios_web_shell_eg2tests_module_iPhone X 14.3", "resultdb": { "enable": true }, @@ -39851,7 +39851,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39863,7 +39863,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s 14.2", + "name": "ios_web_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39896,7 +39896,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39908,7 +39908,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s Plus 14.2", + "name": "ios_web_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -39941,7 +39941,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39953,7 +39953,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s 14.2", + "name": "ios_web_view_inttests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -39986,7 +39986,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -39998,7 +39998,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s Plus 14.2", + "name": "ios_web_view_inttests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -40031,7 +40031,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40043,7 +40043,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s 14.2", + "name": "ios_web_view_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -40076,7 +40076,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40088,7 +40088,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s Plus 14.2", + "name": "ios_web_view_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -40121,7 +40121,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40133,7 +40133,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPhone 6s 14.2", + "name": "net_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -40166,7 +40166,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40178,7 +40178,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPhone 6s 14.2", + "name": "services_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -40211,7 +40211,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40223,7 +40223,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s 14.2", + "name": "skia_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -40256,7 +40256,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40268,7 +40268,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s Plus 14.2", + "name": "skia_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -40301,7 +40301,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40313,7 +40313,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPhone 6s 14.2", + "name": "sql_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -40346,7 +40346,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40358,7 +40358,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s 14.2", + "name": "ui_base_unittests_iPhone 6s 14.3", "resultdb": { "enable": true }, @@ -40391,7 +40391,7 @@ "--platform", "iPhone 6s Plus", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40403,7 +40403,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s Plus 14.2", + "name": "ui_base_unittests_iPhone 6s Plus 14.3", "resultdb": { "enable": true }, @@ -40436,7 +40436,7 @@ "--platform", "iPhone 6s", "--version", - "14.2", + "14.3", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40448,7 +40448,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPhone 6s 14.2", + "name": "url_unittests_iPhone 6s 14.3", "resultdb": { "enable": true },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 52962b6..c6268115 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -5081,6 +5081,7 @@ 'android_10_rel_gtests': [ 'android_trichrome_smoke_tests', 'android_ar_gtests', + 'android_ddready_vr_gtests', ], # This is the same as 'android_lollipop_marshmallow_gtests' @@ -6362,32 +6363,32 @@ 'ios14_beta_simulator_tests': { 'ios_common_tests': { 'variants': [ - 'SIM_IPHONE_X_14_2', + 'SIM_IPHONE_X_14_3', ], }, 'ios_eg2_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPHONE_X_14_2', - 'SIM_IPHONE_7_14_2', - 'SIM_IPAD_AIR_3RD_GEN_14_2', - 'SIM_IPAD_6_GEN_14_2', + 'SIM_IPHONE_X_14_3', + 'SIM_IPHONE_7_14_3', + 'SIM_IPAD_AIR_3RD_GEN_14_3', + 'SIM_IPAD_6_GEN_14_3', ] }, 'ios_eg2_cq_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPHONE_7_14_2', - 'SIM_IPHONE_X_14_2', - 'SIM_IPAD_PRO_2ND_GEN_14_2', - 'SIM_IPAD_6_GEN_14_2', + 'SIM_IPHONE_7_14_3', + 'SIM_IPHONE_X_14_3', + 'SIM_IPAD_PRO_2ND_GEN_14_3', + 'SIM_IPAD_6_GEN_14_3', ] }, 'ios_screen_size_dependent_tests': { 'variants': [ - 'SIM_IPHONE_6S_PLUS_14_2', - 'SIM_IPHONE_X_14_2', - 'SIM_IPAD_AIR_2_14_2', + 'SIM_IPHONE_6S_PLUS_14_3', + 'SIM_IPHONE_X_14_3', + 'SIM_IPAD_AIR_2_14_3', ], }, }, @@ -6395,33 +6396,33 @@ 'ios14_sdk_simulator_tests': { 'ios_common_tests': { 'variants': [ - # 14.2 Sims - 'SIM_IPHONE_6S_14_2', + # Latest beta iOS version Sims + 'SIM_IPHONE_6S_14_3', ], }, 'ios_eg2_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - # 14.2 Sims - 'SIM_IPHONE_7_14_2', - 'SIM_IPAD_AIR_2_14_2', - 'SIM_IPHONE_X_14_2', + # Latest beta iOS version Sims + 'SIM_IPHONE_7_14_3', + 'SIM_IPAD_AIR_2_14_3', + 'SIM_IPHONE_X_14_3', ] }, 'ios_eg2_cq_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - # 14.2 Sims - 'SIM_IPHONE_X_14_2', - 'SIM_IPAD_AIR_2_14_2', - 'SIM_IPAD_PRO_2ND_GEN_14_2', + # Latest beta iOS version Sims + 'SIM_IPHONE_X_14_3', + 'SIM_IPAD_AIR_2_14_3', + 'SIM_IPAD_PRO_2ND_GEN_14_3', ] }, 'ios_screen_size_dependent_tests': { 'variants': [ - # 14.2 Sims - 'SIM_IPHONE_6S_PLUS_14_2', - 'SIM_IPHONE_6S_14_2', + # Latest beta iOS version Sims + 'SIM_IPHONE_6S_PLUS_14_3', + 'SIM_IPHONE_6S_14_3', ], }, },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 4abce2d..f6b52975 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -89,43 +89,43 @@ ], 'identifier': 'iPad Air 2 14.0' }, - 'SIM_IPAD_AIR_2_14_2': { + 'SIM_IPAD_AIR_2_14_3': { 'args': [ '--platform', 'iPad Air 2', '--version', - '14.2' + '14.3' ], - 'identifier': 'iPad Air 2 14.2' + 'identifier': 'iPad Air 2 14.3' }, - 'SIM_IPAD_AIR_3RD_GEN_14_2': { + 'SIM_IPAD_AIR_3RD_GEN_14_3': { 'args': [ '--platform', 'iPad Air (3rd generation)', '--version', - '14.2' + '14.3' ], - 'identifier': 'iPad Air (3rd generation) 14.2' + 'identifier': 'iPad Air (3rd generation) 14.3' }, # In Xcode 12, "iPad Pro (12.9-inch)" requires a generation suffix in # "platform" arg. - 'SIM_IPAD_PRO_2ND_GEN_14_2': { + 'SIM_IPAD_PRO_2ND_GEN_14_3': { 'args': [ '--platform', 'iPad Pro (12.9-inch) (2nd generation)', '--version', - '14.2', + '14.3', ], - 'identifier': 'iPad Pro (12.9-inch) (2nd generation) 14.2' + 'identifier': 'iPad Pro (12.9-inch) (2nd generation) 14.3' }, - 'SIM_IPAD_6_GEN_14_2': { + 'SIM_IPAD_6_GEN_14_3': { 'args': [ '--platform', 'iPad (6th generation)', '--version', - '14.2', + '14.3', ], - 'identifier': 'iPad (6th generation) 14.2' + 'identifier': 'iPad (6th generation) 14.3' }, 'SIM_IPHONE_6S_12_4': { 'args': [ @@ -154,14 +154,14 @@ ], 'identifier': 'iPhone 6s 14.0' }, - 'SIM_IPHONE_6S_14_2': { + 'SIM_IPHONE_6S_14_3': { 'args': [ '--platform', 'iPhone 6s', '--version', - '14.2', + '14.3', ], - 'identifier': 'iPhone 6s 14.2' + 'identifier': 'iPhone 6s 14.3' }, 'SIM_IPHONE_6S_PLUS_13_6': { 'args': [ @@ -190,14 +190,14 @@ ], 'identifier': 'iPhone 6s Plus 14.0' }, - 'SIM_IPHONE_6S_PLUS_14_2': { + 'SIM_IPHONE_6S_PLUS_14_3': { 'args': [ '--platform', 'iPhone 6s Plus', '--version', - '14.2', + '14.3', ], - 'identifier': 'iPhone 6s Plus 14.2' + 'identifier': 'iPhone 6s Plus 14.3' }, 'SIM_IPHONE_7_13_6': { 'args': [ @@ -226,14 +226,14 @@ ], 'identifier': 'iPhone 7 14.0' }, - 'SIM_IPHONE_7_14_2': { + 'SIM_IPHONE_7_14_3': { 'args': [ '--platform', 'iPhone 7', '--version', - '14.2', + '14.3', ], - 'identifier': 'iPhone 7 14.2' + 'identifier': 'iPhone 7 14.3' }, 'SIM_IPHONE_SE_1ST_GEN_13_6': { 'args': [ @@ -298,14 +298,14 @@ ], 'identifier': 'iPhone X 14.0' }, - 'SIM_IPHONE_X_14_2': { + 'SIM_IPHONE_X_14_3': { 'args': [ '--platform', 'iPhone X', '--version', - '14.2', + '14.3', ], - 'identifier': 'iPhone X 14.2' + 'identifier': 'iPhone X 14.3' }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': { 'args': [ @@ -319,13 +319,13 @@ '../../weblayer/browser/android/javatests/skew/expectations.txt', '--impl-version=88', ], - 'identifier': 'Implementation Tests For 88.0.4324.76', + 'identifier': 'Implementation Tests For 88.0.4324.78', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M88', - 'revision': 'version:88.0.4324.76', + 'revision': 'version:88.0.4324.78', } ], }, @@ -342,13 +342,13 @@ '../../weblayer/browser/android/javatests/skew/expectations.txt', '--impl-version=87', ], - 'identifier': 'Implementation Tests For 87.0.4280.141', + 'identifier': 'Implementation Tests For 87.0.4280.143', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M87', - 'revision': 'version:87.0.4280.141', + 'revision': 'version:87.0.4280.143', } ], }, @@ -388,13 +388,13 @@ '../../weblayer/browser/android/javatests/skew/expectations.txt', '--client-version=88', ], - 'identifier': 'Client Tests For 88.0.4324.76', + 'identifier': 'Client Tests For 88.0.4324.78', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M88', - 'revision': 'version:88.0.4324.76', + 'revision': 'version:88.0.4324.78', } ], }, @@ -411,13 +411,13 @@ '../../weblayer/browser/android/javatests/skew/expectations.txt', '--client-version=87', ], - 'identifier': 'Client Tests For 87.0.4280.141', + 'identifier': 'Client Tests For 87.0.4280.143', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M87', - 'revision': 'version:87.0.4280.141', + 'revision': 'version:87.0.4280.143', } ], },
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py index 96cd962..2b86257 100755 --- a/testing/scripts/run_performance_tests.py +++ b/testing/scripts/run_performance_tests.py
@@ -115,10 +115,6 @@ 'xr.vr.common_perftests', ] -BENCHMARKS_TO_SKIP_REF = [ - 'system_health.common_desktop', - 'system_health.common_mobile' -] class OutputFilePaths(object): """Provide paths to where results outputs should be written. @@ -650,7 +646,7 @@ command_generator, output_paths, options.xvfb) overall_return_code = return_code or overall_return_code test_results_files.append(output_paths.test_results) - if options.run_ref_build and benchmark not in BENCHMARKS_TO_SKIP_REF: + if options.run_ref_build: reference_benchmark_foldername = benchmark + '.reference' reference_output_paths = OutputFilePaths( isolated_out_dir, reference_benchmark_foldername).SetUp()
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index ed189c6..261c7c4 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -796,6 +796,12 @@ "LogUnexpectedIPCPostedToBackForwardCachedDocuments", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables declarative link capturing in web apps. +// Explainer: +// https://github.com/WICG/sw-launch/blob/master/declarative_link_capturing.md +const base::Feature kWebAppEnableLinkCapturing{ + "WebAppEnableLinkCapturing", base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls URL handling feature in web apps. Controls parsing of "url_handlers" // field in web app manifests. See explainer for more information: // https://github.com/WICG/pwa-url-handler/blob/master/explainer.md
diff --git a/third_party/blink/common/messaging/cloneable_message.cc b/third_party/blink/common/messaging/cloneable_message.cc index a83971c20..abbaeb3 100644 --- a/third_party/blink/common/messaging/cloneable_message.cc +++ b/third_party/blink/common/messaging/cloneable_message.cc
@@ -20,19 +20,19 @@ CloneableMessage clone; clone.encoded_message = encoded_message; - // Both |blobs| and |native_file_system_tokens| contain mojo pending remotes. + // Both |blobs| and |file_system_access_tokens| contain mojo pending remotes. // ShallowClone() follows these steps to clone each pending remote: // // (1) Temporarily bind the source pending remote in this CloneableMessage's - // |blobs| or |native_file_system_tokens|. This requires a const_cast because + // |blobs| or |file_system_access_tokens|. This requires a const_cast because // it temporarily modifies this CloneableMessage's |blobs| or - // |native_file_system_tokens|. + // |file_system_access_tokens|. // // (2) Use the bound remote to call Clone(), which creates a new remote for // the new clone. // // (3) Unbind the source remote to restore this CloneableMessage's |blobs| or - // |native_file_system_tokens| back to the original pending remote from (1). + // |file_system_access_tokens| back to the original pending remote from (1). for (const auto& blob : blobs) { mojom::SerializedBlobPtr& source_serialized_blob = const_cast<mojom::SerializedBlobPtr&>(blob); @@ -50,21 +50,21 @@ source_serialized_blob->blob = source_blob.Unbind(); } - // Clone the |native_file_system_tokens| pending remotes using the steps + // Clone the |file_system_access_tokens| pending remotes using the steps // described by the comment above. - std::vector<mojo::PendingRemote<mojom::NativeFileSystemTransferToken>>& + std::vector<mojo::PendingRemote<mojom::FileSystemAccessTransferToken>>& source_tokens = const_cast<std::vector< - mojo::PendingRemote<mojom::NativeFileSystemTransferToken>>&>( - native_file_system_tokens); + mojo::PendingRemote<mojom::FileSystemAccessTransferToken>>&>( + file_system_access_tokens); for (auto& token : source_tokens) { - mojo::Remote<mojom::NativeFileSystemTransferToken> source_token( + mojo::Remote<mojom::FileSystemAccessTransferToken> source_token( std::move(token)); - mojo::PendingRemote<mojom::NativeFileSystemTransferToken> cloned_token; + mojo::PendingRemote<mojom::FileSystemAccessTransferToken> cloned_token; source_token->Clone(cloned_token.InitWithNewPipeAndPassReceiver()); - clone.native_file_system_tokens.push_back(std::move(cloned_token)); + clone.file_system_access_tokens.push_back(std::move(cloned_token)); token = source_token.Unbind(); } return clone;
diff --git a/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc b/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc index 1154297..64d0f8f2 100644 --- a/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc +++ b/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc
@@ -24,7 +24,7 @@ if (!data.ReadEncodedMessage(&message_view) || !data.ReadBlobs(&out->blobs) || !data.ReadLockedAgentClusterId(&locked_agent_cluster_id) || !data.ReadSenderOrigin(&out->sender_origin) || - !data.ReadNativeFileSystemTokens(&out->native_file_system_tokens)) { + !data.ReadFileSystemAccessTokens(&out->file_system_access_tokens)) { return false; }
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 1dbe7d0..47f9269 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -330,6 +330,8 @@ BLINK_COMMON_EXPORT extern const base::Feature kLogUnexpectedIPCPostedToBackForwardCachedDocuments; +BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableLinkCapturing; + BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableUrlHandlers; BLINK_COMMON_EXPORT extern const base::Feature kWebAppEnableProtocolHandlers;
diff --git a/third_party/blink/public/common/messaging/cloneable_message.h b/third_party/blink/public/common/messaging/cloneable_message.h index c0e0de61..ca857a3 100644 --- a/third_party/blink/public/common/messaging/cloneable_message.h +++ b/third_party/blink/public/common/messaging/cloneable_message.h
@@ -14,7 +14,7 @@ #include "mojo/public/cpp/bindings/struct_ptr.h" #include "third_party/blink/public/common/common_export.h" #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom.h" #include "url/origin.h" namespace blink { @@ -46,16 +46,16 @@ std::vector<mojom::SerializedBlobPtr> blobs; // Populated by message senders to prevent remote origins from accessing - // |native_file_system_tokens|. Tokens from a remote origin must fail by + // |file_system_access_tokens|. Tokens from a remote origin must fail by // dispatching a 'messageerror' event instead of a 'message' event. If // somehow a compromised process bypasses this origin check, the - // NativeFileSystemManager in the browser process performs another origin - // check that will prevent the use of remote origin NativeFileSystemHandles. + // FileSystemAccessManager in the browser process performs another origin + // check that will prevent the use of remote origin FileSystemAccessHandles. // // The message sender may leave |sender_origin| null. When |sender_origin| is // null, the message receiver must handle the message like it is from an // unknown remote origin by dispatching the 'messageerror' event when - // |native_file_system_tokens| is not an empty array. + // |file_system_access_tokens| is not an empty array. base::Optional<url::Origin> sender_origin; // Stack trace captured by sender. @@ -72,8 +72,8 @@ // Tokens required to clone FileSystemFileHandles and/or // FileSystemDirectoryHandles. - std::vector<mojo::PendingRemote<mojom::NativeFileSystemTransferToken>> - native_file_system_tokens; + std::vector<mojo::PendingRemote<mojom::FileSystemAccessTransferToken>> + file_system_access_tokens; private: DISALLOW_COPY_AND_ASSIGN(CloneableMessage);
diff --git a/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h b/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h index 8148d72..8b8efdf 100644 --- a/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h +++ b/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h
@@ -57,9 +57,9 @@ blink::CloneableMessage* out); static std::vector< - mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken>>& - native_file_system_tokens(blink::CloneableMessage& input) { - return input.native_file_system_tokens; + mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken>>& + file_system_access_tokens(blink::CloneableMessage& input) { + return input.file_system_access_tokens; } };
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index e8343d8..8fdbafe0 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -7152,8 +7152,8 @@ # See https://github.com/WICG/LargestContentfulPaint and largest_contentful_paint.idl type LargestContentfulPaint extends object properties - number renderTime - number loadTime + Network.TimeSinceEpoch renderTime + Network.TimeSinceEpoch loadTime # The number of pixels being painted. number size # The id attribute of the element, if available. @@ -7162,25 +7162,46 @@ optional string url optional DOM.BackendNodeId nodeId + type LayoutShiftAttribution extends object + properties + DOM.Rect previousRect + DOM.Rect currentRect + optional DOM.BackendNodeId nodeId + + # See https://wicg.github.io/layout-instability/#sec-layout-shift and layout_shift.idl + type LayoutShift extends object + properties + # Score increment produced by this event. + number value + boolean hadRecentInput + Network.TimeSinceEpoch lastInputTime + array of LayoutShiftAttribution sources + type TimelineEvent extends object properties # Identifies the frame that this event is related to. Empty for non-frame targets. Page.FrameId frameId + # The event type, as specified in https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype + # This determines which of the optional "details" fiedls is present. string type + # Name may be empty depending on the type. string name # Time in seconds since Epoch, monotonically increasing within document lifetime. Network.TimeSinceEpoch time # Event duration, if applicable. optional number duration optional LargestContentfulPaint lcpDetails + optional LayoutShift layoutShiftDetails # Previously buffered events would be reported before method returns. - # The specified filter overrides any previous filters, passing empty - # filter disables recording. - # Note that not all types exposed to the web platform are currently supported. # See also: timelineEventAdded command enable parameters + # The types of event to report, as specified in + # https://w3c.github.io/performance-timeline/#dom-performanceentry-entrytype + # The specified filter overrides any previous filters, passing empty + # filter disables recording. + # Note that not all types exposed to the web platform are currently supported. array of string eventTypes # Sent when a performance timeline event is added. See reportPerformanceTimeline method.
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index cfdb8c492..ea7cd9f 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -66,13 +66,13 @@ "fetch/fetch_api_request.mojom", "fetch/fetch_api_response.mojom", "file/file_utilities.mojom", - "file_system_access/native_file_system_directory_handle.mojom", - "file_system_access/native_file_system_drag_drop_token.mojom", - "file_system_access/native_file_system_error.mojom", - "file_system_access/native_file_system_file_handle.mojom", - "file_system_access/native_file_system_file_writer.mojom", - "file_system_access/native_file_system_manager.mojom", - "file_system_access/native_file_system_transfer_token.mojom", + "file_system_access/file_system_access_directory_handle.mojom", + "file_system_access/file_system_access_drag_drop_token.mojom", + "file_system_access/file_system_access_error.mojom", + "file_system_access/file_system_access_file_handle.mojom", + "file_system_access/file_system_access_file_writer.mojom", + "file_system_access/file_system_access_manager.mojom", + "file_system_access/file_system_access_transfer_token.mojom", "filesystem/file_system.mojom", "font_access/font_access.mojom", "geolocation/geolocation_service.mojom",
diff --git a/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom b/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom new file mode 100644 index 0000000..26d3b66 --- /dev/null +++ b/third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom
@@ -0,0 +1,85 @@ +// Copyright 2019 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. + +module blink.mojom; + +import "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom"; +import "third_party/blink/public/mojom/permissions/permission_status.mojom"; + +// Union representing either a file or a directory handle. Used in APIs that +// can return arbitrary handles. +union FileSystemAccessHandle { + pending_remote<FileSystemAccessFileHandle> file; + pending_remote<FileSystemAccessDirectoryHandle> directory; +}; + +struct FileSystemAccessEntry { + FileSystemAccessHandle entry_handle; + string name; +}; + +interface FileSystemAccessDirectoryEntriesListener { + // Called by FileSystemAccessDirectoryHandle.GetEntries when some entries + // have been obtained. |has_more_entries| is false when all the entries have + // been obtained, and indicates that the callback will not be called again. + DidReadDirectory(FileSystemAccessError result, + array<FileSystemAccessEntry> entries, + bool has_more_entries); +}; + +// This interface represents a handle to a directory in the File System Access +// API. +// +// TODO(mek): Using something similar to (but probably not the same as) +// mojo_base.mojom.Basename (https://crbug.com/779196) to represent names of +// children could help us defend against directory traversal bugs at the IPC +// layer (not the same type though because of https://crbug.com/956231 and the +// fact that our paths really aren't base::FilePath, but instead are virtual +// paths). +interface FileSystemAccessDirectoryHandle { + // Queries the current permission status for this handle. + GetPermissionStatus(bool writable) => (PermissionStatus status); + + // Requests read and/or write permission for this handle. Returns the new + // permission status for this handle. + RequestPermission(bool writable) => (FileSystemAccessError result, PermissionStatus status); + + // Returns a file with the given |basename| that is a child of this + // directory. If no such file exists, and |create| is true, the file is first + // created. Returns an error if the operation fails, or a handle to the newly + // created file if the operation succeeds. + GetFile(string basename, bool create) => + (FileSystemAccessError result, pending_remote<FileSystemAccessFileHandle>? file); + + // Returns a directory with the given |basename| that is a child of this + // directory. If no such directory exists, and |create| is true, the directory + // is first created. + // Returns an error if the operation fails, or a handle to the newly created + // directory if the operation succeeds. + GetDirectory(string basename, bool create) => + (FileSystemAccessError result, + pending_remote<FileSystemAccessDirectoryHandle>? directory); + + // Returns all the direct children of this directory. + GetEntries(pending_remote<FileSystemAccessDirectoryEntriesListener> listener); + + // Deletes an entry which is a child of this directory. + // To delete recursively, set |recurse| to true. + RemoveEntry(string basename, bool recurse) => (FileSystemAccessError result); + + // If |possible_child| is not a descendant of this directory, |path| will be + // null. If |possible_child| is equal to this directory, |path| will be an + // empty array. And if |possible_child| is a descendant of this directory, + // |path| will contain the path components making up the path of + // |possible_child| relative to this directory. + Resolve(pending_remote<FileSystemAccessTransferToken> possible_child) => + (FileSystemAccessError result, array<string>? path); + + // Create a TransferToken for this directory. This token can be used to pass + // a reference to this directory to other methods, for example to copy or move + // the directory, or when transferring the handle over postMessage. + Transfer(pending_receiver<FileSystemAccessTransferToken> token); +};
diff --git a/third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom b/third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom new file mode 100644 index 0000000..9c6f9da --- /dev/null +++ b/third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom
@@ -0,0 +1,24 @@ +// Copyright 2020 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. + +module blink.mojom; + +import "mojo/public/mojom/base/unguessable_token.mojom"; + +// This interface represents an opaque token that can be used to pass a dragged +// and dropped file or directory from the browser process to the renderer +// process. A pending_remote<FileSystemAccessDragDropToken> passed from +// the browser to the renderer can be redeemed for a FileSystemAccessEntry +// through FileSystemAccessManager::GetEntryFromDragDropToken. +interface FileSystemAccessDragDropToken { + // Used to retrieve the unique identifier associated with a token remote. + // This is used by the FileSystemAccessManager to associate a implementation + // with a Remote<FileSystemAccessDragDropToken>. + GetInternalId() => (mojo_base.mojom.UnguessableToken id); + + // Used by DataObjectItem to retain its copy of a + // FileSystemAccessDragDropToken while passing a copy back to the browser + // process. + Clone(pending_receiver<FileSystemAccessDragDropToken> token_clone); +};
diff --git a/third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom b/third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom new file mode 100644 index 0000000..4a5902d --- /dev/null +++ b/third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom
@@ -0,0 +1,38 @@ +// Copyright 2019 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. + +module blink.mojom; + +import "mojo/public/mojom/base/file_error.mojom"; + +// Always returned as a member of a FileSystemAccessError, which is declared below. +enum FileSystemAccessStatus { + kOk, + // The website doesn't/didn't have permission to do what it tried to do. + kPermissionDenied, + // The website wasn't allowed to ask for permission in the current context. + kSecurityError, + // The object being operated on was in an invalid state for the operation. + kInvalidState, + // An invalid argument was passed to a method. + kInvalidArgument, + // The operation failed for some unspecified reason. + kOperationFailed, + // The operation was aborted by the user. + kOperationAborted, + // The operation failed with a mojom_base.mojom.FileError describing the + // underlying cause. + kFileError, +}; + +// Errors reported by File System Access API methods. +struct FileSystemAccessError { + FileSystemAccessStatus status; + // Only meaningful when |status| is kFileError. + // Conceptually, this should be an optional member, but mojo does not + // currently support optionals. + mojo_base.mojom.FileError file_error; + // Optional extra information describing the error. + string message; +};
diff --git a/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom b/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom new file mode 100644 index 0000000..7a497133 --- /dev/null +++ b/third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom
@@ -0,0 +1,40 @@ +// Copyright 2019 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. + +module blink.mojom; + +import "mojo/public/mojom/base/file_info.mojom"; +import "third_party/blink/public/mojom/blob/blob.mojom"; +import "third_party/blink/public/mojom/blob/serialized_blob.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom"; +import "third_party/blink/public/mojom/permissions/permission_status.mojom"; + +// This interface represents a handle to a directory in the File System Access +// API. +interface FileSystemAccessFileHandle { + // Queries the current permission status for this handle. + GetPermissionStatus(bool writable) => (PermissionStatus status); + + // Requests read and/or write permission for this handle. Returns the new + // permission status for this handle. + RequestPermission(bool writable) => (FileSystemAccessError result, PermissionStatus status); + + // Returns a blob representing the current state of this file. + AsBlob() => (FileSystemAccessError result, mojo_base.mojom.FileInfo info, SerializedBlob? blob); + + // Returns a FileWriter object. The FileWriter provides write operations on a file. + CreateFileWriter(bool keep_existing_data, bool auto_close) => ( + FileSystemAccessError result, pending_remote<FileSystemAccessFileWriter>? writer); + + // Returns true if |other| represents the same file on disk as this handle. + IsSameEntry(pending_remote<FileSystemAccessTransferToken> other) => + (FileSystemAccessError result, bool is_same); + + // Create a TransferToken for this directory. This token can be used to pass + // a reference to this directory to other methods, for example to copy or move + // the file, or when transferring the handle over postMessage. + Transfer(pending_receiver<FileSystemAccessTransferToken> token); +};
diff --git a/third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom b/third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom new file mode 100644 index 0000000..8c965fb --- /dev/null +++ b/third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom
@@ -0,0 +1,44 @@ +// Copyright 2019 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. + +module blink.mojom; + +import "third_party/blink/public/mojom/blob/blob.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom"; + +// Represents an object to modify a file. +interface FileSystemAccessFileWriter { + // Write data from |data| to the given |position| in the file being written + // to. Returns whether the operation succeeded and if so how many bytes were + // written. + // TODO(mek): This might need some way of reporting progress events back to + // the renderer. + Write(uint64 offset, pending_remote<Blob> data) => (FileSystemAccessError result, + uint64 bytes_written); + + // Write data from |stream| to the given |position| in the file being written + // to. Returns whether the operation succeeded and if so how many bytes were + // written. + // TODO(mek): This might need some way of reporting progress events back to + // the renderer. + WriteStream(uint64 offset, handle<data_pipe_consumer> stream) => + (FileSystemAccessError result, uint64 bytes_written); + + // Changes the length of the file to be |length|. If |length| is larger than + // the current size of the file, the file will be extended, and the extended + // part is filled with null bytes. + Truncate(uint64 length) => (FileSystemAccessError result); + + // Closes the file writer. This will materialize the writes operations on the + // intended file target in the case of atomic writes. + // Specify the |autoClose| flag to ensure Close() is automatically invoked + // when the mojo pipe closes. + // Returns whether the operation succeeded. + Close() => (FileSystemAccessError result); + + // Aborts the write operation, resulting in the writes not being committed, + // even if autoClose is specified. All further operations will be rejected. + // Returns whether the write operation was aborted successfully. + Abort() => (FileSystemAccessError result); +};
diff --git a/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom b/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom new file mode 100644 index 0000000..f0f41cd --- /dev/null +++ b/third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom
@@ -0,0 +1,90 @@ +// Copyright 2019 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. + +module blink.mojom; + +import "mojo/public/mojom/base/string16.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom"; + +enum ChooseFileSystemEntryType { + kOpenFile, + kOpenMultipleFiles, + kSaveFile, + kOpenDirectory +}; + +enum CommonDirectory { + kDefault, + kDirDesktop, + kDirDocuments, + kDirDownloads, + kDirHome, + kDirMusic, + kDirPictures, + kDirVideos, +}; + +// Struct to represent individual options for types of files that are accepted +// by calls to ChooseEntry. Each type has an optional description, and any +// number of mime types and/or extensions. +// Options with no extensions and no known mime types will be ignored. +struct ChooseFileSystemEntryAcceptsOption { + mojo_base.mojom.String16 description; + array<string> mime_types; + array<string> extensions; +}; + +// Interface provided by the browser to the renderer as main entry point to the +// File System Access API. The renderer can request this interface for a +// specific worker or document, so the browser process will always be able to +// tell what operations are being done by which document or worker. +interface FileSystemAccessManager { + // Opens the sandboxed filesystem for the origin of the current document or worker. + GetSandboxedFileSystem() => + (FileSystemAccessError result, + pending_remote<FileSystemAccessDirectoryHandle>? directory); + + // Prompts the user to select a file from the local filesystem. Returns an + // error code if something failed, or a list of the selected entries on + // success. + // If |include_accepts_all| is true, a "all files" option is included in the + // dialog displayed to the user. If no valid options are present in |accepts| + // |include_accepts_all| is treated as if it was true. + ChooseEntries(ChooseFileSystemEntryType type, + array<ChooseFileSystemEntryAcceptsOption> accepts, + CommonDirectory starting_directory, + bool include_accepts_all) => + (FileSystemAccessError result, + array<FileSystemAccessEntry> entries); + + // Used to redeem tokens received by a postMessage() target. Clones + // FileSystemFileHandles. Token redemption should never fail. The + // postMessage() target should perform an origin check before + // redeeming tokens. Origin check failures must dispatch a messageerror + // event instead of cloning the objects. FileSystemAccessManager will also + // validate the redeemed token, including the token's origin, before binding the + // FileSystemHandle. + GetFileHandleFromToken( + pending_remote<FileSystemAccessTransferToken> token, + pending_receiver<FileSystemAccessFileHandle> file_handle); + + // Same as GetFileHandleFromToken(), but for FileSystemDirectoryHandles. + // See GetFileHandleFromToken() comment above for details. + GetDirectoryHandleFromToken( + pending_remote<FileSystemAccessTransferToken> token, + pending_receiver<FileSystemAccessDirectoryHandle> directory_handle); + + // Used to redeem FileSystemAccessDragDropToken that are passed to the + // renderer from the browser during a drag and drop operation. Token + // redemption can fail if the id of the process trying to redeem the token + // does not match the id assigned to the token at creation or if the + // FileSystemAccessManager does not have record of the token. + GetEntryFromDragDropToken( + pending_remote<FileSystemAccessDragDropToken> token + ) => (FileSystemAccessEntry entry); +};
diff --git a/third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom b/third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom new file mode 100644 index 0000000..20ea4d5 --- /dev/null +++ b/third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom
@@ -0,0 +1,18 @@ +// Copyright 2019 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. + +module blink.mojom; + +import "mojo/public/mojom/base/unguessable_token.mojom"; + +// This interface represents an opaque token that can be used to pass a +// reference to a file or directory to certain API calls, or when transferring +// the handle over postMessage style APIs. +interface FileSystemAccessTransferToken { + GetInternalID() => (mojo_base.mojom.UnguessableToken id); + + // Used by BroadcastChannels to clone multiple FileSystemHandles from a + // single serialized FileSystemHandle. + Clone(pending_receiver<FileSystemAccessTransferToken> token_clone); +};
diff --git a/third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom b/third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom deleted file mode 100644 index 600e2aae..0000000 --- a/third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2019 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. - -module blink.mojom; - -import "third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom"; -import "third_party/blink/public/mojom/permissions/permission_status.mojom"; - -// Union representing either a file or a directory handle. Used in APIs that -// can return arbitrary handles. -union NativeFileSystemHandle { - pending_remote<NativeFileSystemFileHandle> file; - pending_remote<NativeFileSystemDirectoryHandle> directory; -}; - -struct NativeFileSystemEntry { - NativeFileSystemHandle entry_handle; - string name; -}; - -interface NativeFileSystemDirectoryEntriesListener { - // Called by NativeFileSystemDirectoryHandle.GetEntries when some entries - // have been obtained. |has_more_entries| is false when all the entries have - // been obtained, and indicates that the callback will not be called again. - DidReadDirectory(NativeFileSystemError result, - array<NativeFileSystemEntry> entries, - bool has_more_entries); -}; - -// This interface represents a handle to a directory in the Native File System -// API. -// -// TODO(mek): Using something similar to (but probably not the same as) -// mojo_base.mojom.Basename (https://crbug.com/779196) to represent names of -// children could help us defend against directory traversal bugs at the IPC -// layer (not the same type though because of https://crbug.com/956231 and the -// fact that our paths really aren't base::FilePath, but instead are virtual -// paths). -interface NativeFileSystemDirectoryHandle { - // Queries the current permission status for this handle. - GetPermissionStatus(bool writable) => (PermissionStatus status); - - // Requests read and/or write permission for this handle. Returns the new - // permission status for this handle. - RequestPermission(bool writable) => (NativeFileSystemError result, PermissionStatus status); - - // Returns a file with the given |basename| that is a child of this - // directory. If no such file exists, and |create| is true, the file is first - // created. Returns an error if the operation fails, or a handle to the newly - // created file if the operation succeeds. - GetFile(string basename, bool create) => - (NativeFileSystemError result, pending_remote<NativeFileSystemFileHandle>? file); - - // Returns a directory with the given |basename| that is a child of this - // directory. If no such directory exists, and |create| is true, the directory - // is first created. - // Returns an error if the operation fails, or a handle to the newly created - // directory if the operation succeeds. - GetDirectory(string basename, bool create) => - (NativeFileSystemError result, - pending_remote<NativeFileSystemDirectoryHandle>? directory); - - // Returns all the direct children of this directory. - GetEntries(pending_remote<NativeFileSystemDirectoryEntriesListener> listener); - - // Deletes an entry which is a child of this directory. - // To delete recursively, set |recurse| to true. - RemoveEntry(string basename, bool recurse) => (NativeFileSystemError result); - - // If |possible_child| is not a descendant of this directory, |path| will be - // null. If |possible_child| is equal to this directory, |path| will be an - // empty array. And if |possible_child| is a descendant of this directory, - // |path| will contain the path components making up the path of - // |possible_child| relative to this directory. - Resolve(pending_remote<NativeFileSystemTransferToken> possible_child) => - (NativeFileSystemError result, array<string>? path); - - // Create a TransferToken for this directory. This token can be used to pass - // a reference to this directory to other methods, for example to copy or move - // the directory, or when transferring the handle over postMessage. - Transfer(pending_receiver<NativeFileSystemTransferToken> token); -};
diff --git a/third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom b/third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom deleted file mode 100644 index e4080915..0000000 --- a/third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2020 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. - -module blink.mojom; - -import "mojo/public/mojom/base/unguessable_token.mojom"; - -// This interface represents an opaque token that can be used to pass a dragged -// and dropped file or directory from the browser process to the renderer -// process. A mojo::PendingRemote<NativeFileSystemDragDropToken> passed from -// the browser to the renderer can be redeemed for a NativeFileSystemEntry -// through NativeFileSystemManager::GetEntryFromDragDropToken. -interface NativeFileSystemDragDropToken { - // Used to retrieve the unique identifier associated with a token remote. - // This is used by the NativeFileSystemManager to associate a implementation - // with a Remote<NativeFileSystemDragDropToken>. - GetInternalId() => (mojo_base.mojom.UnguessableToken id); - - // Used by DataObjectItem to retain it's copy of a - // NativeFileSystemDragDropToken while passing a copy back to the browser - // process. - Clone(pending_receiver<NativeFileSystemDragDropToken> token_clone); -};
diff --git a/third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom b/third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom deleted file mode 100644 index 7a20388..0000000 --- a/third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2019 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. - -module blink.mojom; - -import "mojo/public/mojom/base/file_error.mojom"; - -// Always returned as a member of a NativeFileSystemError, which is declared below. -enum NativeFileSystemStatus { - kOk, - // The website doesn't/didn't have permission to do what it tried to do. - kPermissionDenied, - // The website wasn't allowed to ask for permission in the current context. - kSecurityError, - // The object being operated on was in an invalid state for the operation. - kInvalidState, - // An invalid argument was passed to a method. - kInvalidArgument, - // The operation failed for some unspecified reason. - kOperationFailed, - // The operation was aborted by the user. - kOperationAborted, - // The operation failed with a mojom_base.mojom.FileError describing the - // underlying cause. - kFileError, -}; - -// Errors reported by Native File System API methods. -struct NativeFileSystemError { - NativeFileSystemStatus status; - // Only meaningful when |status| is kFileError. - // Conceptually, this should be an optional member, but mojo does not - // currently support optionals. - mojo_base.mojom.FileError file_error; - // Optional extra information describing the error. - string message; -};
diff --git a/third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom b/third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom deleted file mode 100644 index 0798555..0000000 --- a/third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2019 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. - -module blink.mojom; - -import "mojo/public/mojom/base/file_info.mojom"; -import "third_party/blink/public/mojom/blob/blob.mojom"; -import "third_party/blink/public/mojom/blob/serialized_blob.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom"; -import "third_party/blink/public/mojom/permissions/permission_status.mojom"; - -// This interface represents a handle to a directory in the Native File System -// API. -interface NativeFileSystemFileHandle { - // Queries the current permission status for this handle. - GetPermissionStatus(bool writable) => (PermissionStatus status); - - // Requests read and/or write permission for this handle. Returns the new - // permission status for this handle. - RequestPermission(bool writable) => (NativeFileSystemError result, PermissionStatus status); - - // Returns a blob representing the current state of this file. - AsBlob() => (NativeFileSystemError result, mojo_base.mojom.FileInfo info, SerializedBlob? blob); - - // Returns a FileWriter object. The FileWriter provides write operations on a file. - CreateFileWriter(bool keep_existing_data, bool auto_close) => ( - NativeFileSystemError result, pending_remote<NativeFileSystemFileWriter>? writer); - - // Returns true if |other| represents the same file on disk as this handle. - IsSameEntry(pending_remote<NativeFileSystemTransferToken> other) => - (NativeFileSystemError result, bool is_same); - - // Create a TransferToken for this directory. This token can be used to pass - // a reference to this directory to other methods, for example to copy or move - // the file, or when transferring the handle over postMessage. - Transfer(pending_receiver<NativeFileSystemTransferToken> token); -};
diff --git a/third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom b/third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom deleted file mode 100644 index 4c0f510..0000000 --- a/third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2019 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. - -module blink.mojom; - -import "third_party/blink/public/mojom/blob/blob.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom"; - -// Represents an object to modify a file. -interface NativeFileSystemFileWriter { - // Write data from |data| to the given |position| in the file being written - // to. Returns whether the operation succeeded and if so how many bytes were - // written. - // TODO(mek): This might need some way of reporting progress events back to - // the renderer. - Write(uint64 offset, pending_remote<Blob> data) => (NativeFileSystemError result, - uint64 bytes_written); - - // Write data from |stream| to the given |position| in the file being written - // to. Returns whether the operation succeeded and if so how many bytes were - // written. - // TODO(mek): This might need some way of reporting progress events back to - // the renderer. - WriteStream(uint64 offset, handle<data_pipe_consumer> stream) => - (NativeFileSystemError result, uint64 bytes_written); - - // Changes the length of the file to be |length|. If |length| is larger than - // the current size of the file, the file will be extended, and the extended - // part is filled with null bytes. - Truncate(uint64 length) => (NativeFileSystemError result); - - // Closes the file writer. This will materialize the writes operations on the - // intended file target in the case of atomic writes. - // Specify the |autoClose| flag to ensure Close() is automatically invoked - // when the mojo pipe closes. - // Returns whether the operation succeeded. - Close() => (NativeFileSystemError result); - - // Aborts the write operation, resulting in the writes not being committed, - // even if autoClose is specified. All further operations will be rejected. - // Returns whether the write operation was aborted successfully. - Abort() => (NativeFileSystemError result); -};
diff --git a/third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom b/third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom deleted file mode 100644 index c43ee2c7..0000000 --- a/third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2019 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. - -module blink.mojom; - -import "mojo/public/mojom/base/string16.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom"; - -enum ChooseFileSystemEntryType { - kOpenFile, - kOpenMultipleFiles, - kSaveFile, - kOpenDirectory -}; - -enum CommonDirectory { - kDefault, - kDirDesktop, - kDirDocuments, - kDirDownloads, - kDirHome, - kDirMusic, - kDirPictures, - kDirVideos, -}; - -// Struct to represent individual options for types of files that are accepted -// by calls to ChooseEntry. Each type has an optional description, and any -// number of mime types and/or extensions. -// Options with no extensions and no known mime types will be ignored. -struct ChooseFileSystemEntryAcceptsOption { - mojo_base.mojom.String16 description; - array<string> mime_types; - array<string> extensions; -}; - -// Interface provided by the browser to the renderer as main entry point to the -// Native File System API. The renderer can request this interface for a -// specific worker or document, so the browser process will always be able to -// tell what operations are being done by which document or worker. -interface NativeFileSystemManager { - // Opens the sandboxed filesystem for the origin of the current document or worker. - GetSandboxedFileSystem() => - (NativeFileSystemError result, - pending_remote<NativeFileSystemDirectoryHandle>? directory); - - // Prompts the user to select a file from the native filesystem. Returns an - // error code if something failed, or a list of the selected entries on - // success. - // If |include_accepts_all| is true, a "all files" option is included in the - // dialog displayed to the user. If no valid options are present in |accepts| - // |include_accepts_all| is treated as if it was true. - ChooseEntries(ChooseFileSystemEntryType type, - array<ChooseFileSystemEntryAcceptsOption> accepts, - CommonDirectory starting_directory, - bool include_accepts_all) => - (NativeFileSystemError result, - array<NativeFileSystemEntry> entries); - - // Used to redeem tokens received by a postMessage() target. Clones - // FileSystemFileHandles. Token redemption should never fail. The - // postMessage() target should perform an origin check before - // redeeming tokens. Origin check failures must dispatch a messageerror - // event instead of cloning the objects. NativeFileSystemManager will also - // validate the redeemed token, including the token's origin, before binding the - // FileSystemHandle. - GetFileHandleFromToken( - pending_remote<NativeFileSystemTransferToken> token, - pending_receiver<NativeFileSystemFileHandle> file_handle); - - // Same as GetFileHandleFromToken(), but for FileSystemDirectoryHandles. - // See GetFileHandleFromToken() comment above for details. - GetDirectoryHandleFromToken( - pending_remote<NativeFileSystemTransferToken> token, - pending_receiver<NativeFileSystemDirectoryHandle> directory_handle); - - // Used to redeem NativeFileSystemDragDropToken that are passed to the - // renderer from the browser during a drag and drop operation. Token - // redemption can fail if the id of the process trying to redeem the token - // does not match the id assigned to the token at creation or if the - // NativeFileSystemManager does not have record of the token. - GetEntryFromDragDropToken( - pending_remote<NativeFileSystemDragDropToken> token - ) => (NativeFileSystemEntry entry); -};
diff --git a/third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom b/third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom deleted file mode 100644 index 59c41732..0000000 --- a/third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2019 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. - -module blink.mojom; - -import "mojo/public/mojom/base/unguessable_token.mojom"; - -// This interface represents an opaque token that can be used to pass a -// reference to a file or directory to certain API calls, or when transferring -// the handle over postMessage style APIs. -interface NativeFileSystemTransferToken { - GetInternalID() => (mojo_base.mojom.UnguessableToken id); - - // Used by BroadcastChannels to clone multiple FileSystemHandles from a - // single serialized FileSystemHandle. - Clone(pending_receiver<NativeFileSystemTransferToken> token_clone); -};
diff --git a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom index abd3bce..f508aa7 100644 --- a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom +++ b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
@@ -8,7 +8,7 @@ import "mojo/public/mojom/base/string16.mojom"; import "mojo/public/mojom/base/time.mojom"; import "third_party/blink/public/mojom/blob/blob.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom"; // kIDBMaxMessageSize is 128MB, originally based on // IPC::Channel::kMaximumMessageSize. The "usable" size is this value less @@ -219,7 +219,7 @@ union IDBExternalObject { IDBBlobInfo blob_or_file; - pending_remote<NativeFileSystemTransferToken> native_file_system_token; + pending_remote<FileSystemAccessTransferToken> file_system_access_token; }; struct IDBValue {
diff --git a/third_party/blink/public/mojom/messaging/cloneable_message.mojom b/third_party/blink/public/mojom/messaging/cloneable_message.mojom index 13fc5d3..f96d40f 100644 --- a/third_party/blink/public/mojom/messaging/cloneable_message.mojom +++ b/third_party/blink/public/mojom/messaging/cloneable_message.mojom
@@ -7,7 +7,7 @@ import "mojo/public/mojom/base/big_buffer.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom"; import "third_party/blink/public/mojom/blob/serialized_blob.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom"; import "url/mojom/origin.mojom"; // This struct represents the cloneable part of messages that are sent across @@ -17,16 +17,16 @@ // Blob handles for any blobs being sent in this message. array<SerializedBlob> blobs; // Populated by message senders to prevent remote origins from accessing - // |native_file_system_tokens|. Tokens from a remote origin must fail by + // |file_system_access_tokens|. Tokens from a remote origin must fail by // dispatching a 'messageerror' event instead of a 'message' event. If // somehow a compromised process bypasses this origin check, the - // NativeFileSystemManager in the browser process performs another origin - // check that will prevent the use of remote origin NativeFileSystemHandles. + // FileSystemAccessManager in the browser process performs another origin + // check that will prevent the use of remote origin FileSystemAccessHandles. // // The message sender may leave |sender_origin| null. When |sender_origin| is // null, the message receiver must handle the message like it is from an // unknown remote origin by dispatching the 'messageerror' event when - // |native_file_system_tokens| is not an empty array. + // |file_system_access_tokens| is not an empty array. url.mojom.Origin? sender_origin; // Stack trace captured by sender. // For more details see v8_inspector::V8StackTraceId. @@ -41,5 +41,5 @@ mojo_base.mojom.UnguessableToken? locked_agent_cluster_id; // Tokens required to clone FileSystemFileHandles and/or // FileSystemDirectoryHandles. - array<pending_remote<NativeFileSystemTransferToken>> native_file_system_tokens; + array<pending_remote<FileSystemAccessTransferToken>> file_system_access_tokens; };
diff --git a/third_party/blink/public/mojom/page/drag.mojom b/third_party/blink/public/mojom/page/drag.mojom index 303c5e28..2a15333 100644 --- a/third_party/blink/public/mojom/page/drag.mojom +++ b/third_party/blink/public/mojom/page/drag.mojom
@@ -11,7 +11,7 @@ import "ui/base/dragdrop/mojom/drag_drop_types.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; import "url/mojom/url.mojom"; -import "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom"; // This struct encodes what drag-and-drop operations are allowed. It's // typemapped to blink::DragOperationsMask. @@ -44,7 +44,7 @@ struct DragItemFile { mojo_base.mojom.FilePath path; mojo_base.mojom.FilePath display_name; - pending_remote<NativeFileSystemDragDropToken>? native_file_system_token; + pending_remote<FileSystemAccessDragDropToken>? file_system_access_token; }; // Only used when dragging images out of Blink.
diff --git a/third_party/blink/public/mojom/web_launch/web_launch.mojom b/third_party/blink/public/mojom/web_launch/web_launch.mojom index f659c33..282f771 100644 --- a/third_party/blink/public/mojom/web_launch/web_launch.mojom +++ b/third_party/blink/public/mojom/web_launch/web_launch.mojom
@@ -4,7 +4,7 @@ module blink.mojom; -import "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom"; +import "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom"; import "url/mojom/url.mojom"; // Interface for getting the cause of page loads to blink. This service lives @@ -17,5 +17,5 @@ interface WebLaunchService { // Used to notify a frame that it was opened with |files|. This // method is fire-and-forget. - SetLaunchFiles(array<NativeFileSystemEntry> files); + SetLaunchFiles(array<FileSystemAccessEntry> files); };
diff --git a/third_party/blink/public/platform/web_drag_data.h b/third_party/blink/public/platform/web_drag_data.h index 22e5142..940a4c53 100644 --- a/third_party/blink/public/platform/web_drag_data.h +++ b/third_party/blink/public/platform/web_drag_data.h
@@ -33,7 +33,7 @@ #include "base/memory/scoped_refptr.h" #include "services/network/public/mojom/referrer_policy.mojom-shared.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom-shared.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom-shared.h" #include "third_party/blink/public/platform/cross_variant_mojo_util.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_data.h" @@ -47,7 +47,7 @@ using NativeFileSystemDropData = base::RefCountedData<blink::CrossVariantMojoRemote< - mojom::NativeFileSystemDragDropTokenInterfaceBase>>; + mojom::FileSystemAccessDragDropTokenInterfaceBase>>; // Holds data that may be exchanged through a drag-n-drop operation. It is // inexpensive to copy a WebDragData object.
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h index c057291f..08ef4b8 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h +++ b/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h
@@ -38,7 +38,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/common/messaging/message_port_channel.h" #include "third_party/blink/public/common/messaging/message_port_descriptor.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink-forward.h" #include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/transferables.h" #include "third_party/blink/renderer/core/core_export.h" @@ -103,7 +103,7 @@ using MessagePortChannelArray = Vector<MessagePortChannel>; using StreamArray = Vector<Stream>; using NativeFileSystemTokensArray = - Vector<mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>>; + Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>>; // Increment this for each incompatible change to the wire format. // Version 2: Added StringUCharTag for UChar v8 strings.
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 077ebec..4c8f79e 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -746,6 +746,7 @@ "//third_party/blink/renderer/modules/webcodecs/audio_frame.idl", "//third_party/blink/renderer/modules/webcodecs/audio_frame_init.idl", "//third_party/blink/renderer/modules/webcodecs/audio_frame_output_callback.idl", + "//third_party/blink/renderer/modules/webcodecs/avc_encoder_config.idl", "//third_party/blink/renderer/modules/webcodecs/codec_state.idl", "//third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.idl", "//third_party/blink/renderer/modules/webcodecs/color_space_matrix_id.idl",
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc index 41d0fc1..ed3f252 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h" #include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_crypto.h" @@ -334,13 +334,13 @@ // IndexedDB code assumes that deserializing a SSV is non-destructive. So // rather than consuming the token here instead we clone it. - mojo::Remote<mojom::blink::NativeFileSystemTransferToken> token( + mojo::Remote<mojom::blink::FileSystemAccessTransferToken> token( std::move(tokens_array[token_index])); if (!token) { return nullptr; } - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> token_clone; + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> token_clone; token->Clone(token_clone.InitWithNewPipeAndPassReceiver()); tokens_array[token_index] = std::move(token_clone); @@ -348,7 +348,7 @@ // FileSystemHandle. ExecutionContext* execution_context = ExecutionContext::From(GetScriptState()); - mojo::Remote<mojom::blink::NativeFileSystemManager> + mojo::Remote<mojom::blink::FileSystemAccessManager> native_file_system_manager; execution_context->GetBrowserInterfaceBroker().GetInterface( native_file_system_manager.BindNewPipeAndPassReceiver()); @@ -356,7 +356,7 @@ // Clone the FileSystemHandle object. switch (tag) { case kNativeFileSystemFileHandleTag: { - mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle> file_handle; + mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle> file_handle; native_file_system_manager->GetFileHandleFromToken( token.Unbind(), file_handle.InitWithNewPipeAndPassReceiver()); @@ -365,7 +365,7 @@ execution_context, name, std::move(file_handle)); } case kNativeFileSystemDirectoryHandleTag: { - mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle> + mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle> directory_handle; native_file_system_manager->GetDirectoryHandleFromToken(
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc index 30254b4..8cb08ef3 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -304,7 +304,7 @@ bool V8ScriptValueSerializerForModules::WriteNativeFileSystemHandle( SerializationTag tag, NativeFileSystemHandle* native_file_system_handle) { - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> token = + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> token = native_file_system_handle->Transfer(); SerializedScriptValue::NativeFileSystemTokensArray& tokens_array =
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc index 5be5a1f..f7982fc1 100644 --- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc +++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_interface_document.cc
@@ -17,7 +17,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_dom_configuration.h" #include "third_party/blink/renderer/bindings/core/v8/v8_location.h" #include "third_party/blink/renderer/core/animation/document_animation.h" -#include "third_party/blink/renderer/core/document_transition/document_create_transition.h" +#include "third_party/blink/renderer/core/document_transition/document_transition_supplement.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/fullscreen/document_fullscreen.h" #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
diff --git a/third_party/blink/renderer/core/clipboard/data_object_item.cc b/third_party/blink/renderer/core/clipboard/data_object_item.cc index 800ce7d..a4aa6c7 100644 --- a/third_party/blink/renderer/core/clipboard/data_object_item.cc +++ b/third_party/blink/renderer/core/clipboard/data_object_item.cc
@@ -31,7 +31,7 @@ #include "third_party/blink/renderer/core/clipboard/data_object_item.h" #include "base/time/time.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom-blink.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h" #include "third_party/blink/renderer/core/clipboard/system_clipboard.h" @@ -225,16 +225,16 @@ return file_system_id_; } -bool DataObjectItem::HasNativeFileSystemEntry() const { +bool DataObjectItem::HasFileSystemAccessEntry() const { return static_cast<bool>(native_file_system_entry_); } -mojo::PendingRemote<mojom::blink::NativeFileSystemDragDropToken> -DataObjectItem::CloneNativeFileSystemEntryToken() const { - DCHECK(HasNativeFileSystemEntry()); - mojo::Remote<mojom::blink::NativeFileSystemDragDropToken> token_cloner( +mojo::PendingRemote<mojom::blink::FileSystemAccessDragDropToken> +DataObjectItem::CloneFileSystemAccessEntryToken() const { + DCHECK(HasFileSystemAccessEntry()); + mojo::Remote<mojom::blink::FileSystemAccessDragDropToken> token_cloner( std::move(native_file_system_entry_->data)); - mojo::PendingRemote<mojom::blink::NativeFileSystemDragDropToken> token_clone; + mojo::PendingRemote<mojom::blink::FileSystemAccessDragDropToken> token_clone; token_cloner->Clone(token_clone.InitWithNewPipeAndPassReceiver()); native_file_system_entry_->data = token_cloner.Unbind(); return token_clone;
diff --git a/third_party/blink/renderer/core/clipboard/data_object_item.h b/third_party/blink/renderer/core/clipboard/data_object_item.h index 5a9c4c1..71706e57d 100644 --- a/third_party/blink/renderer/core/clipboard/data_object_item.h +++ b/third_party/blink/renderer/core/clipboard/data_object_item.h
@@ -33,8 +33,7 @@ #include "base/optional.h" #include "mojo/public/cpp/bindings/remote.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom-blink.h" #include "third_party/blink/public/platform/web_drag_data.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/fileapi/file.h" @@ -95,9 +94,9 @@ bool HasFileSystemId() const; String FileSystemId() const; - bool HasNativeFileSystemEntry() const; - mojo::PendingRemote<mojom::blink::NativeFileSystemDragDropToken> - CloneNativeFileSystemEntryToken() const; + bool HasFileSystemAccessEntry() const; + mojo::PendingRemote<mojom::blink::FileSystemAccessDragDropToken> + CloneFileSystemAccessEntryToken() const; void Trace(Visitor*) const;
diff --git a/third_party/blink/renderer/core/html/html_view_source_document.cc b/third_party/blink/renderer/core/html/html_view_source_document.cc index bea2258..d5e4af46 100644 --- a/third_party/blink/renderer/core/html/html_view_source_document.cc +++ b/third_party/blink/renderer/core/html/html_view_source_document.cc
@@ -108,25 +108,21 @@ line_number_ = 0; // Create a checkbox to control line wrapping. - auto* line_wrap_div = MakeGarbageCollected<HTMLDivElement>(*this); - line_wrap_div->setAttribute(html_names::kClassAttr, "line-wrap-control"); + auto* label = MakeGarbageCollected<HTMLLabelElement>(*this); + label->setAttribute(html_names::kClassAttr, "line-wrap-control"); auto* checkbox = MakeGarbageCollected<HTMLInputElement>(*this, CreateElementFlags()); checkbox->setAttribute(html_names::kTypeAttr, "checkbox"); - checkbox->setAttribute(html_names::kIdAttr, "line-wrap-checkbox"); - line_wrap_div->ParserAppendChild(checkbox); - auto* label = MakeGarbageCollected<HTMLLabelElement>(*this); - label->setAttribute(html_names::kForAttr, "line-wrap-checkbox"); + label->ParserAppendChild(checkbox); label->ParserAppendChild( Text::Create(*this, WTF::AtomicString(Locale::DefaultLocale().QueryString( IDS_VIEW_SOURCE_LINE_WRAP)))); - line_wrap_div->ParserAppendChild(label); auto* tr = MakeGarbageCollected<HTMLTableRowElement>(*this); auto* td = MakeGarbageCollected<HTMLTableCellElement>(html_names::kTdTag, *this); td->setAttribute(html_names::kColspanAttr, "2"); td->setAttribute(html_names::kClassAttr, "line-wrap-cell"); - td->ParserAppendChild(line_wrap_div); + td->ParserAppendChild(label); tr->ParserAppendChild(td); tbody_->ParserAppendChild(tr);
diff --git a/third_party/blink/renderer/core/html/html_view_source_document_test.cc b/third_party/blink/renderer/core/html/html_view_source_document_test.cc index ab09d32..8c8665b 100644 --- a/third_party/blink/renderer/core/html/html_view_source_document_test.cc +++ b/third_party/blink/renderer/core/html/html_view_source_document_test.cc
@@ -39,11 +39,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " "class=\"html-doctype\"><!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML " @@ -96,11 +94,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " "class=\"html-tag\"><script></span></td></tr><tr><td " @@ -152,11 +148,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " "class=\"html-tag\"><head></span><span class=\"html-tag\"><base " @@ -221,11 +215,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " "class=\"html-tag\"><HEAD></span><span class=\"html-tag\"><BASE " @@ -293,11 +285,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"><br></td></tr><tr><td " "class=\"line-number\" value=\"3\"></td><td " @@ -329,12 +319,10 @@ std::string expected_beginning( "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td class=\"line-content\"> " - " "); + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\">" + "</td><td class=\"line-content\"> "); std::string expected_ending( " <span class=\"html-tag\"><b></span>A<span " "class=\"html-tag\"></b></span> <span " @@ -349,11 +337,9 @@ EXPECT_EQ(GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\">1234567<span " "class=\"html-end-of-file\"></span></td></tr></tbody></table></" "body></html>"); @@ -375,11 +361,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label></td></tr>" + "<tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " "class=\"html-doctype\"><!DOCTYPE html></span></td></tr><tr><td " @@ -446,11 +430,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " "class=\"html-doctype\"><!DOCTYPE html></span></td></tr><tr><td " @@ -481,11 +463,9 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\">" + "</label></td></tr><tr><td class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> Incomplete token " "test</td></tr><tr><td class=\"line-number\" value=\"3\"></td><td " @@ -507,11 +487,10 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td class=\"line-content\"><span " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td>" + "<td class=\"line-content\"><span " "class=\"html-tag\"><textarea></span>foobar in " "textarea</td></tr><tr><td class=\"line-number\" value=\"2\"></td><td " "class=\"line-content\"> <span " @@ -526,11 +505,10 @@ GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " - "colspan=\"2\" class=\"line-wrap-cell\"><div " - "class=\"line-wrap-control\"><input type=\"checkbox\" " - "id=\"line-wrap-checkbox\"><label " - "for=\"line-wrap-checkbox\"></label></div></td></tr><tr><td " - "class=\"line-number\" value=\"1\"></td><td class=\"line-content\"><span " + "colspan=\"2\" class=\"line-wrap-cell\"><label " + "class=\"line-wrap-control\"><input type=\"checkbox\"></label>" + "</td></tr><tr><td class=\"line-number\" value=\"1\"></td>" + "<td class=\"line-content\"><span " "class=\"html-tag\"><script></span>foobar in " "script</td></tr><tr><td class=\"line-number\" value=\"2\"></td><td " "class=\"line-content\"> <span "
diff --git a/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.cc b/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.cc index 1ccefd5..64df06b55 100644 --- a/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_performance_timeline_agent.cc
@@ -16,6 +16,8 @@ #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/timing/dom_window_performance.h" #include "third_party/blink/renderer/core/timing/largest_contentful_paint.h" +#include "third_party/blink/renderer/core/timing/layout_shift.h" +#include "third_party/blink/renderer/core/timing/layout_shift_attribution.h" #include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h" namespace blink { @@ -23,29 +25,67 @@ namespace { constexpr PerformanceEntryType kSupportedTypes = - PerformanceEntry::EntryType::kLargestContentfulPaint; + PerformanceEntry::EntryType::kLargestContentfulPaint | + PerformanceEntry::EntryType::kLayoutShift; + +double ToProtocolTime(DOMHighResTimeStamp timeOrigin, + DOMHighResTimeStamp time) { + return time ? ConvertDOMHighResTimeStampToSeconds(timeOrigin + time) : 0.0; +} std::unique_ptr<protocol::PerformanceTimeline::LargestContentfulPaint> -BuildEventDetails(LargestContentfulPaint* lcp, DOMHighResTimeStamp timeOrigin) { - const double renderTime = - lcp->renderTime() - ? ConvertDOMHighResTimeStampToSeconds(timeOrigin + lcp->renderTime()) - : 0; - const double loadTime = - lcp->loadTime() - ? ConvertDOMHighResTimeStampToSeconds(timeOrigin + lcp->loadTime()) - : 0; +BuildEventDetails(const LargestContentfulPaint& lcp, + DOMHighResTimeStamp timeOrigin) { auto result = protocol::PerformanceTimeline::LargestContentfulPaint::create() - .setRenderTime(renderTime) - .setLoadTime(loadTime) - .setSize(lcp->size()) + .setRenderTime(ToProtocolTime(timeOrigin, lcp.renderTime())) + .setLoadTime(ToProtocolTime(timeOrigin, lcp.loadTime())) + .setSize(lcp.size()) .build(); - if (!lcp->id().IsEmpty()) - result->setElementId(lcp->id()); - if (Element* element = lcp->element()) + if (!lcp.id().IsEmpty()) + result->setElementId(lcp.id()); + if (Element* element = lcp.element()) result->setNodeId(IdentifiersFactory::IntIdForNode(element)); - if (!lcp->url().IsEmpty()) - result->setUrl(lcp->url()); + if (!lcp.url().IsEmpty()) + result->setUrl(lcp.url()); + return result; +} + +std::unique_ptr<protocol::DOM::Rect> BuildRect(DOMRectReadOnly* rect) { + return protocol::DOM::Rect::create() + .setX(rect->x()) + .setY(rect->y()) + .setWidth(rect->width()) + .setHeight(rect->height()) + .build(); +} + +std::unique_ptr< + protocol::Array<protocol::PerformanceTimeline::LayoutShiftAttribution>> +BuildLayoutShiftAttributions(const LayoutShift::AttributionList& attributions) { + auto result = std::make_unique< + protocol::Array<protocol::PerformanceTimeline::LayoutShiftAttribution>>(); + for (const auto& attr : attributions) { + auto entry = protocol::PerformanceTimeline::LayoutShiftAttribution::create() + .setPreviousRect(BuildRect(attr->previousRect())) + .setCurrentRect(BuildRect(attr->currentRect())) + .build(); + if (Node* node = attr->rawNodeForInspector()) + entry->setNodeId(IdentifiersFactory::IntIdForNode(node)); + result->push_back(std::move(entry)); + } + return result; +} + +std::unique_ptr<protocol::PerformanceTimeline::LayoutShift> BuildEventDetails( + const LayoutShift& ls, + DOMHighResTimeStamp timeOrigin) { + auto result = + protocol::PerformanceTimeline::LayoutShift::create() + .setValue(ls.value()) + .setHadRecentInput(ls.hadRecentInput()) + .setLastInputTime(ToProtocolTime(timeOrigin, ls.lastInputTime())) + .setSources(BuildLayoutShiftAttributions(ls.sources())) + .build(); return result; } @@ -59,13 +99,14 @@ .setName(entry->name()) // TODO(caseq): entry time is clamped; consider exposing an // unclamped time. - .setTime(ConvertDOMHighResTimeStampToSeconds( - timeOrigin + entry->startTime())) + .setTime(ToProtocolTime(timeOrigin, entry->startTime())) .build(); if (entry->duration()) result->setDuration(ConvertDOMHighResTimeStampToSeconds(entry->duration())); if (auto* lcp = DynamicTo<LargestContentfulPaint>(entry)) - result->setLcpDetails(BuildEventDetails(lcp, timeOrigin)); + result->setLcpDetails(BuildEventDetails(*lcp, timeOrigin)); + else if (auto* ls = DynamicTo<LayoutShift>(entry)) + result->setLayoutShiftDetails(BuildEventDetails(*ls, timeOrigin)); return result; }
diff --git a/third_party/blink/renderer/core/layout/layout_counter.cc b/third_party/blink/renderer/core/layout/layout_counter.cc index 07c18d3..67164bb 100644 --- a/third_party/blink/renderer/core/layout/layout_counter.cc +++ b/third_party/blink/renderer/core/layout/layout_counter.cc
@@ -24,6 +24,7 @@ #include <memory> #include "base/memory/ptr_util.h" +#include "base/numerics/clamped_math.h" #include "third_party/blink/renderer/core/css/counter_style.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" @@ -204,8 +205,8 @@ return true; } if (auto* olist = DynamicTo<HTMLOListElement>(*e)) { - value = - olist->StartConsideringItemCount() + (olist->IsReversed() ? 1 : -1); + value = base::ClampAdd(olist->StartConsideringItemCount(), + olist->IsReversed() ? 1 : -1); type_mask = CounterNode::kResetType; return true; }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc index eb16a73..3f295bb 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -59,11 +59,11 @@ ComputeUsedTrackSizes(&algorithm_row_track_collection, &grid_items, &reordered_item_indices); - // Place grid and out of flow items. + // Place items. LayoutUnit intrinsic_block_size; - PlaceItems(grid_items, algorithm_column_track_collection, - algorithm_row_track_collection, &out_of_flow_items, - &intrinsic_block_size); + PlaceGridItems(grid_items, out_of_flow_items, + algorithm_column_track_collection, + algorithm_row_track_collection, &intrinsic_block_size); intrinsic_block_size = ClampIntrinsicBlockSize(ConstraintSpace(), Node(), @@ -184,6 +184,7 @@ const GridSpan& span = (track_direction == kForColumns) ? resolved_position.columns : resolved_position.rows; + DCHECK(span.IsTranslatedDefinite()); return span.StartLine(); } @@ -192,6 +193,7 @@ const GridSpan& span = (track_direction == kForColumns) ? resolved_position.columns : resolved_position.rows; + DCHECK(span.IsTranslatedDefinite()); return span.EndLine(); } @@ -200,6 +202,7 @@ const GridSpan& span = (track_direction == kForColumns) ? resolved_position.columns : resolved_position.rows; + DCHECK(span.IsTranslatedDefinite()); return span.IntegerSpan(); } @@ -320,12 +323,12 @@ for (NGBlockNode child = iterator.NextChild(); child; child = iterator.NextChild()) { GridItemData grid_item = MeasureGridItem(child); - // If |out_of_flow_items| is provided, store out-of-flow items separately, - // as they do not contribute to track sizing or auto-placement. - if (grid_item.item_type == ItemType::kInGridFlow) - grid_items->emplace_back(grid_item); - else if (out_of_flow_items) + // Store out-of-flow items separately, as they do not contribute to track + // sizing or auto placement. + if (out_of_flow_items && child.IsOutOfFlowPositioned()) out_of_flow_items->emplace_back(grid_item); + else + grid_items->emplace_back(grid_item); } } @@ -478,9 +481,6 @@ MinMaxSizesType::kContent), &constraint_space) .sizes; - grid_item.item_type = node.IsOutOfFlowPositioned() ? ItemType::kOutOfFlow - : ItemType::kInGridFlow; - return grid_item; } @@ -520,7 +520,7 @@ wtf_size_t column_count; wtf_size_t row_count; DetermineExplicitTrackStarts( - *grid_items, automatic_column_repetitions, automatic_row_repetitions, + automatic_column_repetitions, automatic_row_repetitions, &explicit_column_start, &explicit_row_start, &column_count, &row_count); NGGridPlacement(automatic_row_repetitions, automatic_column_repetitions, @@ -581,7 +581,6 @@ } void NGGridLayoutAlgorithm::DetermineExplicitTrackStarts( - const Vector<GridItemData>& grid_items, wtf_size_t automatic_column_repetitions, wtf_size_t automatic_row_repetitions, wtf_size_t* explicit_column_start, @@ -597,12 +596,13 @@ *column_count = 0u; *row_count = 0u; - for (const GridItemData& grid_item : grid_items) { + NGGridChildIterator iterator(Node()); + for (NGBlockNode child = iterator.NextChild(); child; + child = iterator.NextChild()) { GridSpan column_span = GridPositionsResolver::ResolveGridPositionsFromStyle( - Style(), grid_item.node.Style(), kForColumns, - automatic_column_repetitions); + Style(), child.Style(), kForColumns, automatic_column_repetitions); GridSpan row_span = GridPositionsResolver::ResolveGridPositionsFromStyle( - Style(), grid_item.node.Style(), kForRows, automatic_row_repetitions); + Style(), child.Style(), kForRows, automatic_row_repetitions); if (!column_span.IsIndefinite()) { *explicit_column_start = std::max<int>( *explicit_column_start, -column_span.UntranslatedStartLine()); @@ -611,7 +611,7 @@ } else { *column_count = std::max<int>( *column_count, GridPositionsResolver::SpanSizeForAutoPlacedItem( - grid_item.node.Style(), kForColumns)); + child.Style(), kForColumns)); } if (!row_span.IsIndefinite()) { *explicit_row_start = @@ -620,63 +620,32 @@ } else { *row_count = std::max<int>( *row_count, GridPositionsResolver::SpanSizeForAutoPlacedItem( - grid_item.node.Style(), kForRows)); + child.Style(), kForRows)); } } } void NGGridLayoutAlgorithm::CacheItemSetIndices( const NGGridLayoutAlgorithmTrackCollection& track_collection, - Vector<GridItemData>* items) const { - DCHECK(items); + Vector<GridItemData>* grid_items) const { + DCHECK(grid_items); const GridTrackSizingDirection track_direction = track_collection.Direction(); - for (GridItemData& item : *items) { - wtf_size_t start_line, end_line; - if (item.item_type == ItemType::kInGridFlow) { - start_line = item.StartLine(track_direction); - end_line = item.EndLine(track_direction) - 1; - DCHECK_NE(start_line, kNotFound); - DCHECK_NE(end_line, kNotFound); - } else { - ResolveOutOfFlowItemGridLines(item, track_collection, &start_line, - &end_line); - } - // We only calculate the indexes if: - // 1. The item is in flow (it is a grid item) or - // 2. The item is out of flow, but the line was not defined as 'auto' and - // the line is within the bounds of the grid, since an out of flow item - // cannot create grid lines. - // TODO(ansollan): The start line of an out of flow item can be the last - // line of the grid. If that is the case, begin_set_index has to be - // computed as end_set_index. Similarly, if an end line is the first line - // of the grid, end_set_index has to be computed as begin_set_index. - wtf_size_t begin_set_index = kNotFound; - wtf_size_t end_set_index = kNotFound; - if (start_line != kNotFound) { - wtf_size_t first_spanned_range = - track_collection.RangeIndexFromTrackNumber(start_line); - begin_set_index = - track_collection.RangeStartingSetIndex(first_spanned_range); - } - if (end_line != kNotFound) { - wtf_size_t last_spanned_range = - track_collection.RangeIndexFromTrackNumber(end_line); - end_set_index = - track_collection.RangeStartingSetIndex(last_spanned_range) + - track_collection.RangeSetCount(last_spanned_range); - } + for (GridItemData& item : *grid_items) { + wtf_size_t first_spanned_range = track_collection.RangeIndexFromTrackNumber( + item.StartLine(track_direction)); + wtf_size_t last_spanned_range = track_collection.RangeIndexFromTrackNumber( + item.EndLine(track_direction) - 1); -#if DCHECK_IS_ON() - if (begin_set_index != kNotFound && end_set_index != kNotFound) { - DCHECK_LE(end_set_index, track_collection.SetCount()); - DCHECK_LT(begin_set_index, end_set_index); - } else if (begin_set_index != kNotFound) { - DCHECK_LT(begin_set_index, track_collection.SetCount()); - } else if (end_set_index != kNotFound) { - DCHECK_LE(end_set_index, track_collection.SetCount()); - } -#endif + DCHECK_LE(first_spanned_range, last_spanned_range); + wtf_size_t begin_set_index = + track_collection.RangeStartingSetIndex(first_spanned_range); + wtf_size_t end_set_index = + track_collection.RangeStartingSetIndex(last_spanned_range) + + track_collection.RangeSetCount(last_spanned_range); + + DCHECK_LE(begin_set_index, end_set_index); + DCHECK_LE(end_set_index, track_collection.SetCount()); if (track_direction == kForColumns) { item.columns_begin_set_index = begin_set_index; @@ -688,44 +657,6 @@ } } -// TODO(ansollan): Move ResolveOutOfFlowItemGridLines to NGGridPlacement and -// pass |automatic_repetitions| and |explicit_start| variables. -void NGGridLayoutAlgorithm::ResolveOutOfFlowItemGridLines( - const GridItemData& out_of_flow_item, - const NGGridLayoutAlgorithmTrackCollection& track_collection, - wtf_size_t* start_line, - wtf_size_t* end_line) const { - DCHECK(start_line); - DCHECK(end_line); - - const ComputedStyle& out_of_flow_item_style = out_of_flow_item.node.Style(); - const GridTrackSizingDirection track_direction = track_collection.Direction(); - GridSpan span = GridPositionsResolver::ResolveGridPositionsFromStyle( - Style(), out_of_flow_item_style, track_direction, 0); - if (span.IsIndefinite()) { - *start_line = kNotFound; - *end_line = kNotFound; - return; - } else if (span.UntranslatedStartLine() > -1) { - // TODO(ansollan): Handle out of flow positioned items with negative - // indexes. - span.Translate(0); - } - - *start_line = span.StartLine(); - *end_line = span.EndLine() - 1; - if (!track_collection.IsTrackWithinBounds(*start_line) || - (track_direction == kForColumns - ? out_of_flow_item_style.GridColumnStart().IsAuto() - : out_of_flow_item_style.GridRowStart().IsAuto())) - *start_line = kNotFound; - if (!track_collection.IsTrackWithinBounds(*end_line) || - (track_direction == kForColumns - ? out_of_flow_item_style.GridColumnEnd().IsAuto() - : out_of_flow_item_style.GridRowEnd().IsAuto())) - *end_line = kNotFound; -} - void NGGridLayoutAlgorithm::CacheGridItemsTrackSpanProperties( const NGGridLayoutAlgorithmTrackCollection& track_collection, Vector<GridItemData>* grid_items, @@ -1282,11 +1213,11 @@ return Style().IsGridAutoFlowDirectionRow() ? kForRows : kForColumns; } -void NGGridLayoutAlgorithm::PlaceItems( +void NGGridLayoutAlgorithm::PlaceGridItems( const Vector<GridItemData>& grid_items, - const NGGridLayoutAlgorithmTrackCollection& column_track_collection, - const NGGridLayoutAlgorithmTrackCollection& row_track_collection, - Vector<GridItemData>* out_of_flow_items, + const Vector<GridItemData>& out_of_flow_items, + NGGridLayoutAlgorithmTrackCollection& column_track_collection, + NGGridLayoutAlgorithmTrackCollection& row_track_collection, LayoutUnit* intrinsic_block_size) { DCHECK(intrinsic_block_size); LayoutUnit column_grid_gap = @@ -1312,13 +1243,101 @@ row_set_offsets = ComputeSetOffsets(row_track_collection, row_grid_gap); } - PlaceGridItems(grid_items, column_set_offsets, row_set_offsets, - *intrinsic_block_size, column_grid_gap, row_grid_gap); + for (const GridItemData& grid_item : grid_items) { + wtf_size_t column_start_index = grid_item.columns_begin_set_index; + wtf_size_t column_end_index = grid_item.columns_end_set_index; + wtf_size_t row_start_index = grid_item.rows_begin_set_index; + wtf_size_t row_end_index = grid_item.rows_end_set_index; - PlaceOutOfFlowItems(column_set_offsets, row_set_offsets, - column_track_collection, row_track_collection, - *intrinsic_block_size, column_grid_gap, row_grid_gap, - out_of_flow_items); + DCHECK_LT(column_start_index, column_end_index); + DCHECK_LT(row_start_index, row_end_index); + DCHECK_LT(column_end_index, column_set_offsets.size()); + DCHECK_LT(row_end_index, row_set_offsets.size()); + + LogicalOffset offset = {column_set_offsets[column_start_index], + row_set_offsets[row_start_index]}; + + // Inline and block sizes can be deduced from the delta between the inline + // offset and the cumulated offset at the given item's end indices. The + // cumulated offset's calculation includes the grid gap between and after + // the spanned tracks. The latter is not needed, so it is subtracted. + LogicalSize size = { + column_set_offsets[column_end_index] - offset.inline_offset - + column_grid_gap, + row_set_offsets[row_end_index] - offset.block_offset - row_grid_gap}; + DCHECK_GE(size.inline_size, 0); + DCHECK_GE(size.block_size, 0); + + PlaceGridItem(grid_item, offset, size); + } + + for (const GridItemData& out_of_flow_item : out_of_flow_items) { + // TODO(ansollan): Look up offsets based on specified row/column for + // absolutely-positioned items, as described in + // https://drafts.csswg.org/css-grid-1/#abspos, and pass the correct static + // positioned offset in. + container_builder_.AddOutOfFlowChildCandidate(out_of_flow_item.node, + LogicalOffset()); + } +} + +namespace { + +// Returns the alignment offset for either the inline or block direction. +LayoutUnit AlignmentOffset(LayoutUnit container_size, + LayoutUnit size, + LayoutUnit margin_start, + LayoutUnit margin_end, + AxisEdge axis_edge) { + switch (axis_edge) { + case AxisEdge::kStart: + return margin_start; + case AxisEdge::kCenter: + return (container_size - size + margin_start - margin_end) / 2; + case AxisEdge::kEnd: + return container_size - margin_end - size; + case AxisEdge::kBaseline: + // TODO(ikilpatrick): Implement baseline alignment. + return margin_start; + } + NOTREACHED(); + return LayoutUnit(); +} + +} // namespace + +void NGGridLayoutAlgorithm::PlaceGridItem(const GridItemData& grid_item, + LogicalOffset offset, + LogicalSize size) { + const auto& item_style = grid_item.node.Style(); + NGConstraintSpaceBuilder builder(ConstraintSpace(), + item_style.GetWritingDirection(), + /* is_new_fc */ true); + SetOrthogonalFallbackInlineSizeIfNeeded(Style(), grid_item.node, &builder); + builder.SetIsPaintedAtomically(true); + builder.SetAvailableSize(size); + builder.SetPercentageResolutionSize(size); + + builder.SetStretchInlineSizeIfAuto(grid_item.is_inline_axis_stretched); + builder.SetStretchBlockSizeIfAuto(grid_item.is_block_axis_stretched); + + scoped_refptr<const NGLayoutResult> result = + grid_item.node.Layout(builder.ToConstraintSpace()); + const auto& physical_fragment = result->PhysicalFragment(); + + // Apply the grid-item's alignment (if any). + NGFragment fragment(ConstraintSpace().GetWritingDirection(), + physical_fragment); + offset += LogicalOffset( + AlignmentOffset(size.inline_size, fragment.InlineSize(), + grid_item.margins.inline_start, + grid_item.margins.inline_end, + grid_item.inline_axis_alignment), + AlignmentOffset( + size.block_size, fragment.BlockSize(), grid_item.margins.block_start, + grid_item.margins.block_end, grid_item.block_axis_alignment)); + + container_builder_.AddChild(physical_fragment, offset); } LayoutUnit NGGridLayoutAlgorithm::GridGap( @@ -1357,206 +1376,4 @@ return row_gap && row_gap->IsPercentOrCalc() && available_size == kIndefiniteSize; } - -namespace { - -// Returns the alignment offset for either the inline or block direction. -LayoutUnit AlignmentOffset(LayoutUnit container_size, - LayoutUnit size, - LayoutUnit margin_start, - LayoutUnit margin_end, - AxisEdge axis_edge) { - switch (axis_edge) { - case AxisEdge::kStart: - return margin_start; - case AxisEdge::kCenter: - return (container_size - size + margin_start - margin_end) / 2; - case AxisEdge::kEnd: - return container_size - margin_end - size; - case AxisEdge::kBaseline: - // TODO(ikilpatrick): Implement baseline alignment. - return margin_start; - } - NOTREACHED(); - return LayoutUnit(); -} - -void AlignmentOffsetForOutOfFlow( - const AxisEdge inline_axis_edge, - const AxisEdge block_axis_edge, - const LogicalSize container_size, - NGLogicalStaticPosition::InlineEdge* inline_edge, - NGLogicalStaticPosition::BlockEdge* block_edge, - LogicalOffset* offset) { - using InlineEdge = NGLogicalStaticPosition::InlineEdge; - using BlockEdge = NGLogicalStaticPosition::BlockEdge; - - switch (inline_axis_edge) { - case AxisEdge::kStart: - *inline_edge = InlineEdge::kInlineStart; - break; - case AxisEdge::kCenter: - *inline_edge = InlineEdge::kInlineCenter; - offset->inline_offset += container_size.inline_size / 2; - break; - default: - *inline_edge = InlineEdge::kInlineEnd; - offset->inline_offset += container_size.inline_size; - break; - } - - switch (block_axis_edge) { - case AxisEdge::kStart: - *block_edge = BlockEdge::kBlockStart; - break; - case AxisEdge::kCenter: - *block_edge = BlockEdge::kBlockCenter; - offset->block_offset += container_size.block_size / 2; - break; - default: - *block_edge = BlockEdge::kBlockEnd; - offset->block_offset += container_size.block_size; - break; - } -} -} // namespace - -void NGGridLayoutAlgorithm::PlaceGridItems( - const Vector<GridItemData>& grid_items, - const Vector<LayoutUnit>& column_set_offsets, - const Vector<LayoutUnit>& row_set_offsets, - LayoutUnit intrinsic_block_size, - LayoutUnit column_grid_gap, - LayoutUnit row_grid_gap) { - for (const GridItemData& grid_item : grid_items) { - LogicalOffset offset; - LogicalSize size; - ComputeOffsetAndSize(grid_item, column_set_offsets, column_grid_gap, - &offset.inline_offset, &size.inline_size); - ComputeOffsetAndSize(grid_item, row_set_offsets, row_grid_gap, - &offset.block_offset, &size.block_size, kForRows, - intrinsic_block_size); - const auto& item_style = grid_item.node.Style(); - NGConstraintSpaceBuilder builder(ConstraintSpace(), - item_style.GetWritingDirection(), - /* is_new_fc */ true); - SetOrthogonalFallbackInlineSizeIfNeeded(Style(), grid_item.node, &builder); - builder.SetIsPaintedAtomically(true); - builder.SetAvailableSize(size); - builder.SetPercentageResolutionSize(size); - - builder.SetStretchInlineSizeIfAuto(grid_item.is_inline_axis_stretched); - builder.SetStretchBlockSizeIfAuto(grid_item.is_block_axis_stretched); - - scoped_refptr<const NGLayoutResult> result = - grid_item.node.Layout(builder.ToConstraintSpace()); - const auto& physical_fragment = result->PhysicalFragment(); - - // Apply the grid-item's alignment (if any). - NGFragment fragment(ConstraintSpace().GetWritingDirection(), - physical_fragment); - offset += - LogicalOffset(AlignmentOffset(size.inline_size, fragment.InlineSize(), - grid_item.margins.inline_start, - grid_item.margins.inline_end, - grid_item.inline_axis_alignment), - AlignmentOffset(size.block_size, fragment.BlockSize(), - grid_item.margins.block_start, - grid_item.margins.block_end, - grid_item.block_axis_alignment)); - - container_builder_.AddChild(physical_fragment, offset); - } -} - -void NGGridLayoutAlgorithm::PlaceOutOfFlowItems( - const Vector<LayoutUnit>& column_set_offsets, - const Vector<LayoutUnit>& row_set_offsets, - const NGGridLayoutAlgorithmTrackCollection& column_track_collection, - const NGGridLayoutAlgorithmTrackCollection& row_track_collection, - LayoutUnit intrinsic_block_size, - LayoutUnit column_grid_gap, - LayoutUnit row_grid_gap, - Vector<GridItemData>* out_of_flow_items) { - // Cache set indices for out of flow items. - CacheItemSetIndices(column_track_collection, out_of_flow_items); - CacheItemSetIndices(row_track_collection, out_of_flow_items); - - for (const GridItemData& out_of_flow_item : *out_of_flow_items) { - LogicalRect containing_block_rect; - ComputeOffsetAndSize(out_of_flow_item, column_set_offsets, column_grid_gap, - &containing_block_rect.offset.inline_offset, - &containing_block_rect.size.inline_size); - ComputeOffsetAndSize(out_of_flow_item, row_set_offsets, row_grid_gap, - &containing_block_rect.offset.block_offset, - &containing_block_rect.size.block_size, kForRows, - intrinsic_block_size); - NGLogicalStaticPosition::InlineEdge inline_edge; - NGLogicalStaticPosition::BlockEdge block_edge; - LogicalOffset child_offset = containing_block_rect.offset; - AlignmentOffsetForOutOfFlow(out_of_flow_item.inline_axis_alignment, - out_of_flow_item.block_axis_alignment, - containing_block_rect.size, &inline_edge, - &block_edge, &child_offset); - - container_builder_.AddOutOfFlowChildCandidate( - out_of_flow_item.node, child_offset, inline_edge, block_edge, - /* needs_block_offset_adjustment */ false, containing_block_rect); - } -} - -void NGGridLayoutAlgorithm::ComputeOffsetAndSize( - const GridItemData& item, - const Vector<LayoutUnit>& set_offsets, - LayoutUnit grid_gap, - LayoutUnit* start_offset, - LayoutUnit* size, - GridTrackSizingDirection track_direction, - LayoutUnit intrinsic_block_size) const { - wtf_size_t start_index, end_index; - LayoutUnit border; - // The default padding box value of the |size| will only be used in out of - // flow items in which both the start line and end line are defined as 'auto'. - if (track_direction == kForColumns) { - start_index = item.columns_begin_set_index; - end_index = item.columns_end_set_index; - border = container_builder_.Borders().inline_start; - *size = - border_box_size_.inline_size - container_builder_.Borders().InlineSum(); - } else { - start_index = item.rows_begin_set_index; - end_index = item.rows_end_set_index; - border = container_builder_.Borders().block_start; - *size = border_box_size_.block_size == kIndefiniteSize - ? intrinsic_block_size - : border_box_size_.block_size; - *size -= container_builder_.Borders().BlockSum(); - } - *start_offset = border; - LayoutUnit end_offset = border; - // If the start line is defined, the size is calculated by subtracting the - // offset at start index. Additionally, the start border is removed from the - // cumulated offset because it was already accounted for in the previous value - // of the size. - if (start_index != kNotFound) { - *start_offset = set_offsets[start_index]; - *size -= (*start_offset - end_offset); - } - // If the end line is defined, the offset (which can be the offset at the - // start index or the start border) and the added grid gap after the spanned - // tracks are subtracted from the offset at the end index. - if (end_index != kNotFound) { - end_offset = set_offsets[end_index]; - *size = end_offset - *start_offset - grid_gap; - } - if (start_index != kNotFound && end_index != kNotFound) { - DCHECK_LT(start_index, end_index); - DCHECK_LT(end_index, set_offsets.size()); - DCHECK_GE(*size, 0); - } else { - // Only out of flow items can have an undefined ('auto') value for the start - // and/or end indices. - DCHECK_EQ(item.item_type, ItemType::kOutOfFlow); - } -} } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h index e4fbd2d..299d30f 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
@@ -21,7 +21,6 @@ public: enum class AutoPlacementType { kNotNeeded, kMajor, kMinor, kBoth }; enum class AxisEdge { kStart, kCenter, kEnd, kBaseline }; - enum class ItemType { kInGridFlow, kOutOfFlow }; // This enum corresponds to each step used to accommodate grid items across // intrinsic tracks according to their min and max track sizing functions, as @@ -74,8 +73,6 @@ AxisEdge inline_axis_alignment; AxisEdge block_axis_alignment; - ItemType item_type; - bool is_inline_axis_stretched; bool is_block_axis_stretched; @@ -164,25 +161,19 @@ void SetSpecifiedTracks(wtf_size_t automatic_repetitions, NGGridBlockTrackCollection* track_collection) const; // Determines the explicit column and row track starts. - void DetermineExplicitTrackStarts(const Vector<GridItemData>& grid_items, - wtf_size_t automatic_column_repetitions, + void DetermineExplicitTrackStarts(wtf_size_t automatic_column_repetitions, wtf_size_t automatic_row_repetitions, wtf_size_t* explicit_column_start, wtf_size_t* explicit_row_start, wtf_size_t* column_count, wtf_size_t* row_count) const; + // For every item and track direction, computes and stores the pair of indices // "begin" and "end" such that the item spans every set from the respective // collection's |sets_| with an index in the range [begin, end). void CacheItemSetIndices( const NGGridLayoutAlgorithmTrackCollection& track_collection, - Vector<GridItemData>* items) const; - // Helper function to resolve start and end lines of out of flow items. - void ResolveOutOfFlowItemGridLines( - const GridItemData& out_of_flow_item, - const NGGridLayoutAlgorithmTrackCollection& track_collection, - wtf_size_t* start_line, - wtf_size_t* end_line) const; + Vector<GridItemData>* grid_items) const; // For every grid item, caches properties of the track sizing functions it // spans (i.e. whether an item spans intrinsic or flexible tracks). void CacheGridItemsTrackSpanProperties( @@ -215,13 +206,18 @@ NGGridSetVector* sets_to_grow_beyond_limit); // Lays out and computes inline and block offsets for grid items. - void PlaceItems( + void PlaceGridItems( const Vector<GridItemData>& grid_items, - const NGGridLayoutAlgorithmTrackCollection& column_track_collection, - const NGGridLayoutAlgorithmTrackCollection& row_track_collection, - Vector<GridItemData>* out_of_flow_items, + const Vector<GridItemData>& out_of_flow_items, + NGGridLayoutAlgorithmTrackCollection& column_track_collection, + NGGridLayoutAlgorithmTrackCollection& row_track_collection, LayoutUnit* intrinsic_block_size); + // Lays out |grid_item| based on the offsets and sizes provided. + void PlaceGridItem(const GridItemData& grid_item, + LogicalOffset offset, + LogicalSize size); + // Gets the row or column gap of the grid. LayoutUnit GridGap(GridTrackSizingDirection track_direction, LayoutUnit available_size = kIndefiniteSize) const; @@ -235,41 +231,6 @@ // available size. bool IsRowGridGapUnresolvable(LayoutUnit available_size) const; - // Layout the |grid_items| based on the offsets provided. - void PlaceGridItems(const Vector<GridItemData>& grid_items, - const Vector<LayoutUnit>& column_set_offsets, - const Vector<LayoutUnit>& row_set_offsets, - LayoutUnit intrinsic_block_size, - LayoutUnit column_grid_gap, - LayoutUnit row_grid_gap); - - // Computes the static position, grid area and its offset of out of flow - // elements in the grid. - void PlaceOutOfFlowItems( - const Vector<LayoutUnit>& column_set_offsets, - const Vector<LayoutUnit>& row_set_offsets, - const NGGridLayoutAlgorithmTrackCollection& column_track_collection, - const NGGridLayoutAlgorithmTrackCollection& row_track_collection, - LayoutUnit intrinsic_block_size, - LayoutUnit column_grid_gap, - LayoutUnit row_grid_gap, - Vector<GridItemData>* out_of_flow_items); - - // Helper method that computes the offset and size of an item. - void ComputeOffsetAndSize( - const GridItemData& item, - const Vector<LayoutUnit>& set_offsets, - LayoutUnit grid_gap, - LayoutUnit* start_offset, - LayoutUnit* size, - GridTrackSizingDirection track_direction = kForColumns, - const LayoutUnit intrinsic_block_size = LayoutUnit()) const; - - // Determines the position of the out of flow item's container. - void DeterminePositionOfOutOfFlowContainer( - Vector<GridItemData>* out_of_flow_items, - const GridTrackSizingDirection track_direction) const; - GridTrackSizingDirection AutoFlowDirection() const; LogicalSize border_box_size_;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc index 4ffe3c4..02c803a 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
@@ -1583,8 +1583,13 @@ if (!RuntimeEnabledFeatures::LayoutNGGridEnabled()) return; + LoadAhem(); SetBodyInnerHTML(R"HTML( <style> + body { + font: 10px/1 Ahem; + } + #grid { display: grid; width: auto; @@ -1691,99 +1696,76 @@ EXPECT_EQ(expectation, dump); } -TEST_F(NGGridLayoutAlgorithmTest, PositionedOutOfFlowItems) { +TEST_F(NGGridLayoutAlgorithmTest, OutOfFlowGridItems) { if (!RuntimeEnabledFeatures::LayoutNGGridEnabled()) return; + LoadAhem(); SetBodyInnerHTML(R"HTML( <style> + body { + font: 10px/1 Ahem; + } + #grid { display: grid; - grid: 100px 100px 100px / 100px 100px 100px; - width: 300px; - height: auto; - background-color: gray; - padding: 5px; - border: 5px solid black; + width: 100px; + height: 300px; + grid-auto-columns: 100px; + grid-auto-rows: 100px; position: relative; } - .absolute { + .grid_item { + width: 100px; + height: 100px; + background-color: gray; + } + + #cell2 { position: absolute; - width: 50px; - height: 50px; + left: 25%; + top: 10%; + width: 100px; + height: 100px; + background-color: blue; } - .item { - background-color: gainsboro; + #cell4 { + position: absolute; + top: 150px; + left: 25px; + width: 100%; + height: 35%; + background-color: yellow; } - #firstItem { - background: magenta; - grid-column-start: 2; - grid-column-end: 3; - grid-row-start: 2; - grid-row-end: 3; - align-self: center; - justify-self: end; - } - - #secondItem { - background: cyan; - grid-column-start: auto; - grid-column-end: 2; - grid-row-start: 3; - grid-row-end: auto; - bottom: 30px; - } - - #thirdItem { - background: yellow; - left: 200px; - } - - #fourthItem { - background: lime; - grid-column-start: 5; - grid-column-end: 6; - } </style> <div id="wrapper"> <div id="grid"> - <div class="absolute" id="firstItem"></div> - <div class="absolute" id="secondItem"></div> - <div class="absolute" id="thirdItem"></div> - <div class="absolute" id="fourthItem"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> - <div class="item"></div> + <div class="grid_item" style="background: orange;">1</div> + <div id="cell2">2</div> + <div class="grid_item" style="background: green;">3</div> + <div id="cell4">4</div> + <div class="grid_item" style="background: blueviolet;">5</div> </div> </div> )HTML"); String dump = DumpFragmentTree(GetElementById("wrapper")); String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. - offset:unplaced size:1000x320 - offset:0,0 size:320x320 - offset:10,10 size:100x100 - offset:110,10 size:100x100 - offset:210,10 size:100x100 - offset:10,110 size:100x100 - offset:110,110 size:100x100 - offset:210,110 size:100x100 - offset:10,210 size:100x100 - offset:110,210 size:100x100 - offset:210,210 size:100x100 - offset:160,135 size:50x50 - offset:5,235 size:50x50 - offset:205,5 size:50x50 - offset:5,5 size:50x50 + offset:unplaced size:1000x300 + offset:0,0 size:100x300 + offset:0,0 size:100x100 + offset:0,0 size:10x10 + offset:0,100 size:100x100 + offset:0,0 size:10x10 + offset:0,200 size:100x100 + offset:0,0 size:10x10 + offset:25,30 size:100x100 + offset:0,0 size:10x10 + offset:25,150 size:100x105 + offset:0,0 size:10x10 )DUMP"; EXPECT_EQ(expectation, dump); }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc index ec80579..92c56e4 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
@@ -11,14 +11,6 @@ constexpr wtf_size_t NGGridTrackCollectionBase::kInvalidRangeIndex; -bool NGGridTrackCollectionBase::IsTrackWithinBounds( - wtf_size_t track_number) const { - DCHECK_NE(track_number, kInvalidRangeIndex); - wtf_size_t last_range_index = RangeCount() - 1; - return track_number < - RangeTrackNumber(last_range_index) + RangeTrackCount(last_range_index); -} - wtf_size_t NGGridTrackCollectionBase::RangeIndexFromTrackNumber( wtf_size_t track_number) const { wtf_size_t upper = RangeCount(); @@ -27,7 +19,9 @@ // We can't look for a range in a collection with no ranges. DCHECK_NE(upper, 0u); // We don't expect a |track_number| outside of the bounds of the collection. - DCHECK(IsTrackWithinBounds(track_number)); + DCHECK_NE(track_number, kInvalidRangeIndex); + DCHECK_LT(track_number, + RangeTrackNumber(upper - 1u) + RangeTrackCount(upper - 1u)); // Do a binary search on the tracks. wtf_size_t range = upper - lower;
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h index fd78fb7..8d52bf4 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h
@@ -49,8 +49,6 @@ wtf_size_t range_track_count_; }; - bool IsTrackWithinBounds(wtf_size_t track_number) const; - // Gets the range index for the range that contains the given track number. wtf_size_t RangeIndexFromTrackNumber(wtf_size_t track_number) const;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h index a496619..5156734 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h +++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -641,7 +641,11 @@ return bitfields_.AreInlineSizeConstraintsEqual(other.bitfields_); } bool AreBlockSizeConstraintsEqual(const NGConstraintSpace& other) const { - return bitfields_.AreBlockSizeConstraintsEqual(other.bitfields_); + if (!bitfields_.AreBlockSizeConstraintsEqual(other.bitfields_)) + return false; + if (!HasRareData() && !other.HasRareData()) + return true; + return TableCellAlignmentBaseline() == other.TableCellAlignmentBaseline(); } bool AreSizesEqual(const NGConstraintSpace& other) const {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc index 65e8de7..dc0a9b3 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -183,7 +183,7 @@ oof_positioned_candidates_.emplace_back( child, NGLogicalStaticPosition{child_offset, inline_edge, block_edge}, /* inline_container */ nullptr, needs_block_offset_adjustment, - /* containing_block_offset */ LogicalOffset(), + /*containing_block_offset */ LogicalOffset(), /* containing_block_fragment */ nullptr, containing_block_rect); }
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc index 30e47a5..6c68e26 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_helpers.cc
@@ -627,7 +627,7 @@ std::next(rows->begin(), start_row_index + row_count); auto RowBlockSizeDeficit = [&percentage_resolution_block_size]( - NGTableTypes::Row* row) { + const NGTableTypes::Row* row) { if (percentage_resolution_block_size == kIndefiniteSize) return LayoutUnit(); DCHECK(row->percent); @@ -637,7 +637,7 @@ }; auto IsUnconstrainedNonEmptyRow = - [&percentage_resolution_block_size](NGTableTypes::Row* row) { + [&percentage_resolution_block_size](const NGTableTypes::Row* row) { if (row->block_size == LayoutUnit()) return false; if (row->percent && percentage_resolution_block_size == kIndefiniteSize) @@ -646,12 +646,18 @@ }; auto IsRowWithOriginatingRowspan = - [&start_row, &desired_block_size_is_rowspan](NGTableTypes::Row* row) { + [&start_row, + &desired_block_size_is_rowspan](const NGTableTypes::Row* row) { // Rowspans are treated specially only during rowspan distribution. return desired_block_size_is_rowspan && row != start_row && row->has_rowspan_start; }; + auto IsEmptyRow = [](const NGTableTypes::Row* row) { + return row->block_size == LayoutUnit() && + (!row->percent || *row->percent == 0); + }; + unsigned percent_rows_with_deficit_count = 0; unsigned rows_with_originating_rowspan = 0; unsigned unconstrained_non_empty_row_count = 0; @@ -677,10 +683,10 @@ if (IsUnconstrainedNonEmptyRow(row)) { unconstrained_non_empty_row_count++; unconstrained_non_empty_row_block_size += row->block_size; - } else if (row->is_constrained && row->block_size != LayoutUnit()) { + } else if (row->is_constrained && !IsEmptyRow(row)) { constrained_non_empty_row_count++; } - if (row->block_size == LayoutUnit()) + if (IsEmptyRow(row)) empty_row_count++; } @@ -778,7 +784,7 @@ // - all rows are empty. // - non-empty rows are all constrained. // Different browsers disagree on when to grow empty rows. - NGTableTypes::Row* last_row; + NGTableTypes::Row* last_row = nullptr; LayoutUnit remaining_deficit = distributable_block_size; for (NGTableTypes::Row* row = start_row; row != end_row; ++row) { if (row->block_size != LayoutUnit()) @@ -791,6 +797,7 @@ row->block_size = delta; remaining_deficit -= delta; } + DCHECK(last_row); last_row->block_size += remaining_deficit; return; }
diff --git a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc index 76c8fd34..313cc8c 100644 --- a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc +++ b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
@@ -51,9 +51,9 @@ return false; out->locked_agent_cluster_id = locked_agent_cluster_id; - Vector<PendingRemote<blink::mojom::blink::NativeFileSystemTransferToken>>& + Vector<PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken>>& tokens = out->message->NativeFileSystemTokens(); - if (!data.ReadNativeFileSystemTokens(&tokens)) { + if (!data.ReadFileSystemAccessTokens(&tokens)) { return false; } return true;
diff --git a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h index 637c23a..6e6978a 100644 --- a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h +++ b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
@@ -9,7 +9,7 @@ #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h" #include "mojo/public/cpp/bindings/array_traits_wtf_vector.h" #include "mojo/public/cpp/bindings/string_traits_wtf.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink.h" #include "third_party/blink/public/mojom/messaging/cloneable_message.mojom-shared.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/core/core_export.h" @@ -60,8 +60,8 @@ } static Vector< - mojo::PendingRemote<blink::mojom::blink::NativeFileSystemTransferToken>> - native_file_system_tokens(blink::BlinkCloneableMessage& input) { + mojo::PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken>> + file_system_access_tokens(blink::BlinkCloneableMessage& input) { return std::move(input.message->NativeFileSystemTokens()); }
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc index 8edfc08c..12bd1f45 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -189,9 +189,9 @@ std::move(image_bitmap_contents_array)); } - // Convert the PendingRemote<NativeFileSystemTransferToken> from the + // Convert the PendingRemote<FileSystemAccessTransferToken> from the // blink::mojom namespace to the blink::mojom::blink namespace. - for (auto& token : message.native_file_system_tokens) { + for (auto& token : message.file_system_access_tokens) { result.message->NativeFileSystemTokens().push_back( ToCrossVariantMojoType(std::move(token))); }
diff --git a/third_party/blink/renderer/core/style/grid_area.h b/third_party/blink/renderer/core/style/grid_area.h index 118a6fb..a286b52 100644 --- a/third_party/blink/renderer/core/style/grid_area.h +++ b/third_party/blink/renderer/core/style/grid_area.h
@@ -124,8 +124,6 @@ bool IsIndefinite() const { return type_ == kIndefinite; } - bool IsUntranslatedDefinite() const { return type_ == kUntranslatedDefinite; } - void Translate(size_t offset) { DCHECK_EQ(type_, kUntranslatedDefinite);
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.h b/third_party/blink/renderer/core/timing/largest_contentful_paint.h index d43150989..97b66eb 100644 --- a/third_party/blink/renderer/core/timing/largest_contentful_paint.h +++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.h
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/timing/performance_entry.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink {
diff --git a/third_party/blink/renderer/core/timing/layout_shift.h b/third_party/blink/renderer/core/timing/layout_shift.h index f20e9517..fcf9987 100644 --- a/third_party/blink/renderer/core/timing/layout_shift.h +++ b/third_party/blink/renderer/core/timing/layout_shift.h
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h" #include "third_party/blink/renderer/core/timing/layout_shift_attribution.h" #include "third_party/blink/renderer/core/timing/performance_entry.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -45,7 +46,7 @@ bool hadRecentInput() const { return had_recent_input_; } double lastInputTime() const { return most_recent_input_timestamp_; } - AttributionList sources() const { return sources_; } + const AttributionList& sources() const { return sources_; } void Trace(Visitor*) const override; @@ -58,6 +59,13 @@ AttributionList sources_; }; +template <> +struct DowncastTraits<LayoutShift> { + static bool AllowFrom(const PerformanceEntry& entry) { + return entry.EntryTypeEnum() == PerformanceEntry::EntryType::kLayoutShift; + } +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_LAYOUT_SHIFT_H_
diff --git a/third_party/blink/renderer/core/timing/layout_shift_attribution.cc b/third_party/blink/renderer/core/timing/layout_shift_attribution.cc index 1da6afd..791652d 100644 --- a/third_party/blink/renderer/core/timing/layout_shift_attribution.cc +++ b/third_party/blink/renderer/core/timing/layout_shift_attribution.cc
@@ -31,6 +31,10 @@ return Performance::CanExposeNode(node_) ? node_ : nullptr; } +Node* LayoutShiftAttribution::rawNodeForInspector() const { + return node_; +} + DOMRectReadOnly* LayoutShiftAttribution::previousRect() const { return previous_rect_; }
diff --git a/third_party/blink/renderer/core/timing/layout_shift_attribution.h b/third_party/blink/renderer/core/timing/layout_shift_attribution.h index 62fa925..eaa6c9e 100644 --- a/third_party/blink/renderer/core/timing/layout_shift_attribution.h +++ b/third_party/blink/renderer/core/timing/layout_shift_attribution.h
@@ -27,6 +27,9 @@ ~LayoutShiftAttribution() override; Node* node() const; + // Return node_ unconditionally, skipping the checks that apply + // to exposing it through bindings. + Node* rawNodeForInspector() const; DOMRectReadOnly* previousRect() const; DOMRectReadOnly* currentRect() const;
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc index cff9d95..f94a11e1 100644 --- a/third_party/blink/renderer/core/timing/performance.cc +++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -633,6 +633,7 @@ } void Performance::AddLayoutShiftBuffer(LayoutShift& entry) { + probe::PerformanceEntryAdded(GetExecutionContext(), &entry); if (layout_shift_buffer_.size() < kDefaultLayoutShiftBufferSize) layout_shift_buffer_.push_back(&entry); }
diff --git a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.cc b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.cc index f897c3d1..b370f56 100644 --- a/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.cc +++ b/third_party/blink/renderer/modules/file_system_access/data_transfer_item_native_file_system.cc
@@ -6,12 +6,12 @@ #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/core/clipboard/data_object_item.h" @@ -36,13 +36,13 @@ return ScriptPromise::CastUndefined(script_state); } - // If the DataObjectItem doesn't have an associated NativeFileSystemEntry, + // If the DataObjectItem doesn't have an associated FileSystemAccessEntry, // return nullptr. - if (!data_transfer_item.GetDataObjectItem()->HasNativeFileSystemEntry()) { + if (!data_transfer_item.GetDataObjectItem()->HasFileSystemAccessEntry()) { return ScriptPromise::CastUndefined(script_state); } - mojo::Remote<mojom::blink::NativeFileSystemManager> nfs_manager; + mojo::Remote<mojom::blink::FileSystemAccessManager> nfs_manager; ExecutionContext* execution_context = ExecutionContext::From(script_state); execution_context->GetBrowserInterfaceBroker().GetInterface( nfs_manager.BindNewPipeAndPassReceiver()); @@ -52,8 +52,8 @@ // Since tokens are move-only, we need to create a clone in order // to preserve the state of `data_object_item` for future calls. - mojo::PendingRemote<mojom::blink::NativeFileSystemDragDropToken> - token_remote = data_object_item.CloneNativeFileSystemEntryToken(); + mojo::PendingRemote<mojom::blink::FileSystemAccessDragDropToken> + token_remote = data_object_item.CloneFileSystemAccessEntryToken(); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise result = resolver->Promise(); @@ -66,9 +66,9 @@ raw_nfs_manager->GetEntryFromDragDropToken( std::move(token_remote), WTF::Bind( - [](mojo::Remote<mojom::blink::NativeFileSystemManager>, + [](mojo::Remote<mojom::blink::FileSystemAccessManager>, ScriptPromiseResolver* resolver, - mojom::blink::NativeFileSystemEntryPtr entry) { + mojom::blink::FileSystemAccessEntryPtr entry) { ScriptState* script_state = resolver->GetScriptState(); if (!script_state) return;
diff --git a/third_party/blink/renderer/modules/file_system_access/global_native_file_system.cc b/third_party/blink/renderer/modules/file_system_access/global_native_file_system.cc index e8bd80f..e0dad660 100644 --- a/third_party/blink/renderer/modules/file_system_access/global_native_file_system.cc +++ b/third_party/blink/renderer/modules/file_system_access/global_native_file_system.cc
@@ -11,9 +11,9 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-blink-forward.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-shared.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-shared.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_directory_picker_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_picker_accept_type.h" @@ -203,11 +203,11 @@ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); ScriptPromise resolver_result = resolver->Promise(); - // TODO(mek): Cache mojo::Remote<mojom::blink::NativeFileSystemManager> + // TODO(mek): Cache mojo::Remote<mojom::blink::FileSystemAccessManager> // associated with an ExecutionContext, so we don't have to request a new one // for each operation, and can avoid code duplication between here and other // uses. - mojo::Remote<mojom::blink::NativeFileSystemManager> manager; + mojo::Remote<mojom::blink::FileSystemAccessManager> manager; window.GetBrowserInterfaceBroker().GetInterface( manager.BindNewPipeAndPassReceiver()); @@ -220,15 +220,15 @@ accept_all, WTF::Bind( [](ScriptPromiseResolver* resolver, - mojo::Remote<mojom::blink::NativeFileSystemManager>, + mojo::Remote<mojom::blink::FileSystemAccessManager>, bool return_as_sequence, LocalFrame* local_frame, - mojom::blink::NativeFileSystemErrorPtr file_operation_result, - Vector<mojom::blink::NativeFileSystemEntryPtr> entries) { + mojom::blink::FileSystemAccessErrorPtr file_operation_result, + Vector<mojom::blink::FileSystemAccessEntryPtr> entries) { ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; if (file_operation_result->status != - mojom::blink::NativeFileSystemStatus::kOk) { + mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *file_operation_result); return;
diff --git a/third_party/blink/renderer/modules/file_system_access/global_native_file_system_test.cc b/third_party/blink/renderer/modules/file_system_access/global_native_file_system_test.cc index fb9f7ef..31f21e6 100644 --- a/third_party/blink/renderer/modules/file_system_access/global_native_file_system_test.cc +++ b/third_party/blink/renderer/modules/file_system_access/global_native_file_system_test.cc
@@ -7,10 +7,10 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/forms/html_button_element.h" @@ -22,13 +22,13 @@ namespace blink { class MockNativeFileSystemManager - : public mojom::blink::NativeFileSystemManager { + : public mojom::blink::FileSystemAccessManager { public: MockNativeFileSystemManager(BrowserInterfaceBrokerProxy& broker, base::OnceClosure reached_callback) : reached_callback_(std::move(reached_callback)), broker_(broker) { broker_.SetBinderForTesting( - mojom::blink::NativeFileSystemManager::Name_, + mojom::blink::FileSystemAccessManager::Name_, WTF::BindRepeating( &MockNativeFileSystemManager::BindNativeFileSystemManager, WTF::Unretained(this))); @@ -36,13 +36,13 @@ MockNativeFileSystemManager(BrowserInterfaceBrokerProxy& broker) : broker_(broker) { broker_.SetBinderForTesting( - mojom::blink::NativeFileSystemManager::Name_, + mojom::blink::FileSystemAccessManager::Name_, WTF::BindRepeating( &MockNativeFileSystemManager::BindNativeFileSystemManager, WTF::Unretained(this))); } ~MockNativeFileSystemManager() override { - broker_.SetBinderForTesting(mojom::blink::NativeFileSystemManager::Name_, + broker_.SetBinderForTesting(mojom::blink::FileSystemAccessManager::Name_, {}); } @@ -76,30 +76,30 @@ } void GetFileHandleFromToken( - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>, - mojo::PendingReceiver<mojom::blink::NativeFileSystemFileHandle>) + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>, + mojo::PendingReceiver<mojom::blink::FileSystemAccessFileHandle>) override {} void GetDirectoryHandleFromToken( - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>, - mojo::PendingReceiver<mojom::blink::NativeFileSystemDirectoryHandle>) + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>, + mojo::PendingReceiver<mojom::blink::FileSystemAccessDirectoryHandle>) override {} void GetEntryFromDragDropToken( - mojo::PendingRemote<blink::mojom::blink::NativeFileSystemDragDropToken> + mojo::PendingRemote<blink::mojom::blink::FileSystemAccessDragDropToken> token, GetEntryFromDragDropTokenCallback callback) override {} private: void BindNativeFileSystemManager(mojo::ScopedMessagePipeHandle handle) { receivers_.Add(this, - mojo::PendingReceiver<mojom::blink::NativeFileSystemManager>( + mojo::PendingReceiver<mojom::blink::FileSystemAccessManager>( std::move(handle))); } base::OnceClosure reached_callback_; ChooseEntriesResponseCallback choose_entries_response_callback_; - mojo::ReceiverSet<mojom::blink::NativeFileSystemManager> receivers_; + mojo::ReceiverSet<mojom::blink::FileSystemAccessManager> receivers_; BrowserInterfaceBrokerProxy& broker_; }; @@ -151,18 +151,18 @@ manager_run_loop.QuitClosure()); manager.SetChooseEntriesResponse(WTF::Bind( [](MockNativeFileSystemManager::ChooseEntriesCallback callback) { - auto error = mojom::blink::NativeFileSystemError::New(); - error->status = mojom::blink::NativeFileSystemStatus::kOk; + auto error = mojom::blink::FileSystemAccessError::New(); + error->status = mojom::blink::FileSystemAccessStatus::kOk; error->message = ""; - mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle> + mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle> pending_remote; ignore_result(pending_remote.InitWithNewPipeAndPassReceiver()); - auto handle = mojom::blink::NativeFileSystemHandle::NewFile( + auto handle = mojom::blink::FileSystemAccessHandle::NewFile( std::move(pending_remote)); - auto entry = mojom::blink::NativeFileSystemEntry::New(std::move(handle), + auto entry = mojom::blink::FileSystemAccessEntry::New(std::move(handle), "foo.txt"); - Vector<mojom::blink::NativeFileSystemEntryPtr> entries; + Vector<mojom::blink::FileSystemAccessEntryPtr> entries; entries.push_back(std::move(entry)); std::move(callback).Run(std::move(error), std::move(entries)); @@ -187,19 +187,19 @@ LocalFrame* frame = &GetFrame(); EXPECT_FALSE(frame->HasStickyUserActivation()); - using mojom::blink::NativeFileSystemStatus; + using mojom::blink::FileSystemAccessStatus; - NativeFileSystemStatus statuses[] = { - NativeFileSystemStatus::kPermissionDenied, - NativeFileSystemStatus::kInvalidState, - NativeFileSystemStatus::kInvalidArgument, - NativeFileSystemStatus::kOperationFailed, + FileSystemAccessStatus statuses[] = { + FileSystemAccessStatus::kPermissionDenied, + FileSystemAccessStatus::kInvalidState, + FileSystemAccessStatus::kInvalidArgument, + FileSystemAccessStatus::kOperationFailed, // kOperationAborted is when the user cancels the file selection. - NativeFileSystemStatus::kOperationAborted, + FileSystemAccessStatus::kOperationAborted, }; MockNativeFileSystemManager manager(frame->GetBrowserInterfaceBroker()); - for (const NativeFileSystemStatus& status : statuses) { + for (const FileSystemAccessStatus& status : statuses) { LocalFrame::NotifyUserActivation( frame, mojom::UserActivationNotificationType::kTest); EXPECT_TRUE(frame->HasStickyUserActivation()); @@ -207,12 +207,12 @@ base::RunLoop manager_run_loop; manager.SetQuitClosure(manager_run_loop.QuitClosure()); manager.SetChooseEntriesResponse(WTF::Bind( - [](mojom::blink::NativeFileSystemStatus status, + [](mojom::blink::FileSystemAccessStatus status, MockNativeFileSystemManager::ChooseEntriesCallback callback) { - auto error = mojom::blink::NativeFileSystemError::New(); + auto error = mojom::blink::FileSystemAccessError::New(); error->status = status; error->message = ""; - Vector<mojom::blink::NativeFileSystemEntryPtr> entries; + Vector<mojom::blink::FileSystemAccessEntryPtr> entries; std::move(callback).Run(std::move(error), std::move(entries)); },
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.cc b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.cc index 2e00831..ca377b0c 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.cc +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.cc
@@ -8,8 +8,8 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_handle.h" @@ -28,12 +28,12 @@ namespace blink { -using mojom::blink::NativeFileSystemErrorPtr; +using mojom::blink::FileSystemAccessErrorPtr; NativeFileSystemDirectoryHandle::NativeFileSystemDirectoryHandle( ExecutionContext* context, const String& name, - mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle> mojo_ptr) + mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle> mojo_ptr) : NativeFileSystemHandle(context, name), mojo_ptr_(context) { mojo_ptr_.Bind(std::move(mojo_ptr), context->GetTaskRunner(TaskType::kMiscPlatformAPI)); @@ -69,13 +69,13 @@ name, options->create(), WTF::Bind( [](ScriptPromiseResolver* resolver, const String& name, - NativeFileSystemErrorPtr result, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle> + FileSystemAccessErrorPtr result, + mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle> handle) { ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; } @@ -104,13 +104,13 @@ name, options->create(), WTF::Bind( [](ScriptPromiseResolver* resolver, const String& name, - NativeFileSystemErrorPtr result, - mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle> + FileSystemAccessErrorPtr result, + mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle> handle) { ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; } @@ -166,7 +166,7 @@ mojo_ptr_->RemoveEntry( name, options->recursive(), WTF::Bind( - [](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result) { + [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result) { native_file_system_error::ResolveOrReject(resolver, *result); }, WrapPersistent(resolver))); @@ -189,9 +189,9 @@ mojo_ptr_->Resolve( possible_child->Transfer(), WTF::Bind( - [](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result, + [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result, const base::Optional<Vector<String>>& path) { - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; } @@ -206,9 +206,9 @@ return result; } -mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> +mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> NativeFileSystemDirectoryHandle::Transfer() { - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> result; + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> result; if (mojo_ptr_.is_bound()) mojo_ptr_->Transfer(result.InitWithNewPipeAndPassReceiver()); return result; @@ -231,12 +231,12 @@ void NativeFileSystemDirectoryHandle::RequestPermissionImpl( bool writable, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, mojom::blink::PermissionStatus)> callback) { if (!mojo_ptr_.is_bound()) { std::move(callback).Run( - mojom::blink::NativeFileSystemError::New( - mojom::blink::NativeFileSystemStatus::kInvalidState, + mojom::blink::FileSystemAccessError::New( + mojom::blink::FileSystemAccessStatus::kInvalidState, base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"), mojom::blink::PermissionStatus::DENIED); return; @@ -246,13 +246,13 @@ } void NativeFileSystemDirectoryHandle::IsSameEntryImpl( - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> other, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, bool)> + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)> callback) { if (!mojo_ptr_.is_bound()) { std::move(callback).Run( - mojom::blink::NativeFileSystemError::New( - mojom::blink::NativeFileSystemStatus::kInvalidState, + mojom::blink::FileSystemAccessError::New( + mojom::blink::FileSystemAccessStatus::kInvalidState, base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"), false); return; @@ -261,9 +261,9 @@ mojo_ptr_->Resolve( std::move(other), WTF::Bind( - [](base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, + [](base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)> callback, - NativeFileSystemErrorPtr result, + FileSystemAccessErrorPtr result, const base::Optional<Vector<String>>& path) { std::move(callback).Run(std::move(result), path.has_value() && path->IsEmpty());
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h index d3a18ea..6f0fd14 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_handle.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_HANDLE_H_ #include "mojo/public/cpp/bindings/pending_remote.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" #include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" @@ -23,7 +23,7 @@ NativeFileSystemDirectoryHandle( ExecutionContext* context, const String& name, - mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle>); + mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle>); // FileSystemDirectoryHandle IDL interface: NativeFileSystemDirectoryIterator* entries(); @@ -45,10 +45,10 @@ ScriptPromise resolve(ScriptState*, NativeFileSystemHandle* possible_child); - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> Transfer() + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> Transfer() override; - mojom::blink::NativeFileSystemDirectoryHandle* MojoHandle() { + mojom::blink::FileSystemAccessDirectoryHandle* MojoHandle() { return mojo_ptr_.get(); } @@ -60,16 +60,16 @@ base::OnceCallback<void(mojom::blink::PermissionStatus)>) override; void RequestPermissionImpl( bool writable, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, mojom::blink::PermissionStatus)>) override; // IsSameEntry for directories is implemented in terms of resolve, as resolve // also can be used to figure out if two directories are the same entry. void IsSameEntryImpl( - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> other, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, bool)>) + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)>) override; - HeapMojoRemote<mojom::blink::NativeFileSystemDirectoryHandle> mojo_ptr_; + HeapMojoRemote<mojom::blink::FileSystemAccessDirectoryHandle> mojo_ptr_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.cc b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.cc index a1c604e..70e7e113 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.cc +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.cc
@@ -82,12 +82,12 @@ } void NativeFileSystemDirectoryIterator::DidReadDirectory( - mojom::blink::NativeFileSystemErrorPtr result, - Vector<mojom::blink::NativeFileSystemEntryPtr> entries, + mojom::blink::FileSystemAccessErrorPtr result, + Vector<mojom::blink::FileSystemAccessEntryPtr> entries, bool has_more_entries) { if (!GetExecutionContext()) return; - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { error_ = std::move(result); if (pending_next_) { native_file_system_error::Reject(pending_next_, *error_);
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h index 256822f..05b9003f 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_directory_iterator.h
@@ -6,8 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_DIRECTORY_ITERATOR_H_ #include "base/files/file.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" @@ -25,7 +25,7 @@ : public ScriptWrappable, public ActiveScriptWrappable<NativeFileSystemDirectoryIterator>, public ExecutionContextClient, - public mojom::blink::NativeFileSystemDirectoryEntriesListener { + public mojom::blink::FileSystemAccessDirectoryEntriesListener { DEFINE_WRAPPERTYPEINFO(); public: @@ -44,17 +44,17 @@ void Trace(Visitor*) const override; private: - void DidReadDirectory(mojom::blink::NativeFileSystemErrorPtr result, - Vector<mojom::blink::NativeFileSystemEntryPtr> entries, + void DidReadDirectory(mojom::blink::FileSystemAccessErrorPtr result, + Vector<mojom::blink::FileSystemAccessEntryPtr> entries, bool has_more_entries) override; Mode mode_; - mojom::blink::NativeFileSystemErrorPtr error_; + mojom::blink::FileSystemAccessErrorPtr error_; bool waiting_for_more_entries_ = true; HeapDeque<Member<NativeFileSystemHandle>> entries_; Member<ScriptPromiseResolver> pending_next_; Member<NativeFileSystemDirectoryHandle> directory_; - HeapMojoReceiver<mojom::blink::NativeFileSystemDirectoryEntriesListener, + HeapMojoReceiver<mojom::blink::FileSystemAccessDirectoryEntriesListener, NativeFileSystemDirectoryIterator, HeapMojoWrapperMode::kWithoutContextObserver> receiver_;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.cc b/third_party/blink/renderer/modules/file_system_access/native_file_system_error.cc index 97c366d6..128f63a 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.cc +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_error.cc
@@ -4,7 +4,7 @@ #include "third_party/blink/renderer/modules/file_system_access/native_file_system_error.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" @@ -16,13 +16,13 @@ namespace native_file_system_error { void Reject(ScriptPromiseResolver* resolver, - const mojom::blink::NativeFileSystemError& error) { - DCHECK_NE(error.status, mojom::blink::NativeFileSystemStatus::kOk); + const mojom::blink::FileSystemAccessError& error) { + DCHECK_NE(error.status, mojom::blink::FileSystemAccessStatus::kOk); ResolveOrReject(resolver, error); } void ResolveOrReject(ScriptPromiseResolver* resolver, - const mojom::blink::NativeFileSystemError& error) { + const mojom::blink::FileSystemAccessError& error) { // Early exit if the resolver's context has been destroyed already. if (!resolver->GetScriptState()->ContextIsValid()) return; @@ -34,31 +34,31 @@ const String message = error.message.IsEmpty() ? String() : error.message; switch (error.status) { - case mojom::blink::NativeFileSystemStatus::kOk: + case mojom::blink::FileSystemAccessStatus::kOk: resolver->Resolve(); break; - case mojom::blink::NativeFileSystemStatus::kPermissionDenied: + case mojom::blink::FileSystemAccessStatus::kPermissionDenied: resolver->Reject(V8ThrowDOMException::CreateOrEmpty( isolate, DOMExceptionCode::kNotAllowedError, message)); break; - case mojom::blink::NativeFileSystemStatus::kSecurityError: + case mojom::blink::FileSystemAccessStatus::kSecurityError: resolver->Reject(V8ThrowDOMException::CreateOrEmpty( isolate, DOMExceptionCode::kSecurityError, message)); break; - case mojom::blink::NativeFileSystemStatus::kInvalidState: + case mojom::blink::FileSystemAccessStatus::kInvalidState: resolver->Reject(V8ThrowDOMException::CreateOrEmpty( isolate, DOMExceptionCode::kInvalidStateError, message)); break; - case mojom::blink::NativeFileSystemStatus::kInvalidArgument: + case mojom::blink::FileSystemAccessStatus::kInvalidArgument: resolver->Reject(V8ThrowException::CreateTypeError( resolver->GetScriptState()->GetIsolate(), message)); break; - case mojom::blink::NativeFileSystemStatus::kOperationFailed: - case mojom::blink::NativeFileSystemStatus::kOperationAborted: + case mojom::blink::FileSystemAccessStatus::kOperationFailed: + case mojom::blink::FileSystemAccessStatus::kOperationAborted: resolver->Reject(V8ThrowDOMException::CreateOrEmpty( isolate, DOMExceptionCode::kAbortError, message)); break; - case mojom::blink::NativeFileSystemStatus::kFileError: + case mojom::blink::FileSystemAccessStatus::kFileError: // TODO(mek): We might want to support custom messages for these cases. resolver->Reject(file_error::CreateDOMException(error.file_error)); break;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.h b/third_party/blink/renderer/modules/file_system_access/native_file_system_error.h index f7aa988..caa5d2e70f 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_error.h +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_error.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_ERROR_H_ #include "base/files/file.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink-forward.h" namespace blink { class ScriptPromiseResolver; @@ -15,12 +15,12 @@ // Rejects |resolver| with an appropriate exception if |status| represents an // error. Resolves |resolver| with undefined otherwise. void ResolveOrReject(ScriptPromiseResolver* resolver, - const mojom::blink::NativeFileSystemError& status); + const mojom::blink::FileSystemAccessError& status); // Rejects |resolver| with an appropriate exception if |status| represents an // error. DCHECKs otherwise. void Reject(ScriptPromiseResolver* resolver, - const mojom::blink::NativeFileSystemError& error); + const mojom::blink::FileSystemAccessError& error); } // namespace native_file_system_error } // namespace blink
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.cc b/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.cc index d758d00d6..921a1ee1 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.cc +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.cc
@@ -4,9 +4,9 @@ #include "third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_create_writer_options.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" @@ -20,12 +20,12 @@ #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { -using mojom::blink::NativeFileSystemErrorPtr; +using mojom::blink::FileSystemAccessErrorPtr; NativeFileSystemFileHandle::NativeFileSystemFileHandle( ExecutionContext* context, const String& name, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle> mojo_ptr) + mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle> mojo_ptr) : NativeFileSystemHandle(context, name), mojo_ptr_(context) { mojo_ptr_.Bind(std::move(mojo_ptr), context->GetTaskRunner(TaskType::kMiscPlatformAPI)); @@ -48,13 +48,13 @@ options->keepExistingData(), options->autoClose(), WTF::Bind( [](ScriptPromiseResolver* resolver, - mojom::blink::NativeFileSystemErrorPtr result, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileWriter> + mojom::blink::FileSystemAccessErrorPtr result, + mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter> writer) { ScriptState* script_state = resolver->GetScriptState(); if (!script_state) return; - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; } @@ -80,9 +80,9 @@ mojo_ptr_->AsBlob(WTF::Bind( [](ScriptPromiseResolver* resolver, const String& name, - NativeFileSystemErrorPtr result, const base::File::Info& info, + FileSystemAccessErrorPtr result, const base::File::Info& info, const scoped_refptr<BlobDataHandle>& blob) { - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; } @@ -94,9 +94,9 @@ return result; } -mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> +mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> NativeFileSystemFileHandle::Transfer() { - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> result; + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> result; if (mojo_ptr_.is_bound()) mojo_ptr_->Transfer(result.InitWithNewPipeAndPassReceiver()); return result; @@ -119,12 +119,12 @@ void NativeFileSystemFileHandle::RequestPermissionImpl( bool writable, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, mojom::blink::PermissionStatus)> callback) { if (!mojo_ptr_.is_bound()) { std::move(callback).Run( - mojom::blink::NativeFileSystemError::New( - mojom::blink::NativeFileSystemStatus::kInvalidState, + mojom::blink::FileSystemAccessError::New( + mojom::blink::FileSystemAccessStatus::kInvalidState, base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"), mojom::blink::PermissionStatus::DENIED); return; @@ -134,13 +134,13 @@ } void NativeFileSystemFileHandle::IsSameEntryImpl( - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> other, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, bool)> + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)> callback) { if (!mojo_ptr_.is_bound()) { std::move(callback).Run( - mojom::blink::NativeFileSystemError::New( - mojom::blink::NativeFileSystemStatus::kInvalidState, + mojom::blink::FileSystemAccessError::New( + mojom::blink::FileSystemAccessStatus::kInvalidState, base::File::Error::FILE_ERROR_FAILED, "Context Destroyed"), false); return;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h b/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h index 47ef04ab..449f0536 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_file_handle.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_FILE_HANDLE_H_ #include "mojo/public/cpp/bindings/pending_remote.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h" #include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" @@ -20,7 +20,7 @@ NativeFileSystemFileHandle( ExecutionContext* context, const String& name, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileHandle>); + mojo::PendingRemote<mojom::blink::FileSystemAccessFileHandle>); bool isFile() const override { return true; } @@ -29,10 +29,10 @@ ExceptionState&); ScriptPromise getFile(ScriptState*, ExceptionState&); - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> Transfer() + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> Transfer() override; - mojom::blink::NativeFileSystemFileHandle* MojoHandle() { + mojom::blink::FileSystemAccessFileHandle* MojoHandle() { return mojo_ptr_.get(); } @@ -44,14 +44,14 @@ base::OnceCallback<void(mojom::blink::PermissionStatus)>) override; void RequestPermissionImpl( bool writable, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, mojom::blink::PermissionStatus)>) override; void IsSameEntryImpl( - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> other, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, bool)>) + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)>) override; - HeapMojoRemote<mojom::blink::NativeFileSystemFileHandle> mojo_ptr_; + HeapMojoRemote<mojom::blink::FileSystemAccessFileHandle> mojo_ptr_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.cc b/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.cc index fc36313..2809a9e 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.cc +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.cc
@@ -4,7 +4,7 @@ #include "third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_handle_permission_descriptor.h" @@ -16,8 +16,8 @@ #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { -using mojom::blink::NativeFileSystemEntryPtr; -using mojom::blink::NativeFileSystemErrorPtr; +using mojom::blink::FileSystemAccessEntryPtr; +using mojom::blink::FileSystemAccessErrorPtr; NativeFileSystemHandle::NativeFileSystemHandle( ExecutionContext* execution_context, @@ -26,7 +26,7 @@ // static NativeFileSystemHandle* NativeFileSystemHandle::CreateFromMojoEntry( - mojom::blink::NativeFileSystemEntryPtr e, + mojom::blink::FileSystemAccessEntryPtr e, ExecutionContext* execution_context) { if (e->entry_handle->is_file()) { return MakeGarbageCollected<NativeFileSystemFileHandle>( @@ -79,9 +79,9 @@ RequestPermissionImpl( descriptor->mode() == "readwrite", WTF::Bind( - [](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result, + [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result, mojom::blink::PermissionStatus status) { - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; } @@ -101,9 +101,9 @@ IsSameEntryImpl( other->Transfer(), WTF::Bind( - [](ScriptPromiseResolver* resolver, NativeFileSystemErrorPtr result, + [](ScriptPromiseResolver* resolver, FileSystemAccessErrorPtr result, bool same) { - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; }
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h b/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h index 526b941f..e3385d8 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_handle.h
@@ -6,9 +6,9 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_HANDLE_H_ #include "mojo/public/cpp/bindings/pending_remote.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink-forward.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink-forward.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink-forward.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom-blink-forward.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" @@ -29,7 +29,7 @@ NativeFileSystemHandle(ExecutionContext* execution_context, const String& name); static NativeFileSystemHandle* CreateFromMojoEntry( - mojom::blink::NativeFileSystemEntryPtr, + mojom::blink::FileSystemAccessEntryPtr, ExecutionContext* execution_context); virtual bool isFile() const { return false; } @@ -46,7 +46,7 @@ // Grab a handle to a transfer token. This may return an invalid PendingRemote // if the context is already destroyed. - virtual mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> + virtual mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> Transfer() = 0; void Trace(Visitor*) const override; @@ -57,11 +57,11 @@ base::OnceCallback<void(mojom::blink::PermissionStatus)>) = 0; virtual void RequestPermissionImpl( bool writable, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, mojom::blink::PermissionStatus)>) = 0; virtual void IsSameEntryImpl( - mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken> other, - base::OnceCallback<void(mojom::blink::NativeFileSystemErrorPtr, + mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken> other, + base::OnceCallback<void(mojom::blink::FileSystemAccessErrorPtr, bool)>) = 0; String name_;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.cc b/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.cc index d57e0ea..e59cc974 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.cc +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.cc
@@ -21,7 +21,7 @@ NativeFileSystemUnderlyingSink::NativeFileSystemUnderlyingSink( ExecutionContext* context, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileWriter> writer_remote) + mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter> writer_remote) : writer_remote_(context) { writer_remote_.Bind(std::move(writer_remote), context->GetTaskRunner(TaskType::kMiscPlatformAPI)); @@ -225,13 +225,13 @@ } void NativeFileSystemUnderlyingSink::WriteComplete( - mojom::blink::NativeFileSystemErrorPtr result, + mojom::blink::FileSystemAccessErrorPtr result, uint64_t bytes_written) { DCHECK(pending_operation_); native_file_system_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr; - if (result->status == mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status == mojom::blink::FileSystemAccessStatus::kOk) { // Advance offset. offset_ += bytes_written; } @@ -239,12 +239,12 @@ void NativeFileSystemUnderlyingSink::TruncateComplete( uint64_t to_size, - mojom::blink::NativeFileSystemErrorPtr result) { + mojom::blink::FileSystemAccessErrorPtr result) { DCHECK(pending_operation_); native_file_system_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr; - if (result->status == mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status == mojom::blink::FileSystemAccessStatus::kOk) { // Set offset to smallest last set size so that a subsequent write is not // out of bounds. offset_ = to_size < offset_ ? to_size : offset_; @@ -252,7 +252,7 @@ } void NativeFileSystemUnderlyingSink::CloseComplete( - mojom::blink::NativeFileSystemErrorPtr result) { + mojom::blink::FileSystemAccessErrorPtr result) { DCHECK(pending_operation_); native_file_system_error::ResolveOrReject(pending_operation_, *result); pending_operation_ = nullptr;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h b/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h index 8d231fc..853a900 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_underlying_sink.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_UNDERLYING_SINK_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_UNDERLYING_SINK_H_ -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/core/streams/underlying_sink_base.h" @@ -22,7 +22,7 @@ public: explicit NativeFileSystemUnderlyingSink( ExecutionContext*, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileWriter>); + mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter>); // UnderlyingSinkBase ScriptPromise start(ScriptState*, @@ -52,13 +52,13 @@ ExceptionState&); ScriptPromise Truncate(ScriptState*, uint64_t size, ExceptionState&); ScriptPromise Seek(ScriptState*, uint64_t offset, ExceptionState&); - void WriteComplete(mojom::blink::NativeFileSystemErrorPtr result, + void WriteComplete(mojom::blink::FileSystemAccessErrorPtr result, uint64_t bytes_written); void TruncateComplete(uint64_t to_size, - mojom::blink::NativeFileSystemErrorPtr result); - void CloseComplete(mojom::blink::NativeFileSystemErrorPtr result); + mojom::blink::FileSystemAccessErrorPtr result); + void CloseComplete(mojom::blink::FileSystemAccessErrorPtr result); - HeapMojoRemote<mojom::blink::NativeFileSystemFileWriter> writer_remote_; + HeapMojoRemote<mojom::blink::FileSystemAccessFileWriter> writer_remote_; uint64_t offset_ = 0; Member<ScriptPromiseResolver> pending_operation_;
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.cc b/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.cc index 90e1e1eb..4e599eb 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.cc +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.cc
@@ -20,7 +20,7 @@ NativeFileSystemWritableFileStream* NativeFileSystemWritableFileStream::Create( ScriptState* script_state, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileWriter> + mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter> writer_pending_remote) { DCHECK(writer_pending_remote); ScriptState::Scope scope(script_state);
diff --git a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h b/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h index fe4ee8c..55327a4 100644 --- a/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h +++ b/third_party/blink/renderer/modules/file_system_access/native_file_system_writable_file_stream.h
@@ -6,8 +6,8 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_NATIVE_FILE_SYSTEM_WRITABLE_FILE_STREAM_H_ #include "mojo/public/cpp/bindings/remote.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_error.mojom-blink.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_file_writer.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom-blink.h" #include "third_party/blink/renderer/bindings/modules/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string_or_write_params.h" #include "third_party/blink/renderer/core/streams/writable_stream.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h" @@ -25,7 +25,7 @@ public: static NativeFileSystemWritableFileStream* Create( ScriptState*, - mojo::PendingRemote<mojom::blink::NativeFileSystemFileWriter>); + mojo::PendingRemote<mojom::blink::FileSystemAccessFileWriter>); void Trace(Visitor* visitor) const override;
diff --git a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.cc b/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.cc index 0b925ca8..b6fa20c 100644 --- a/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.cc +++ b/third_party/blink/renderer/modules/file_system_access/storage_manager_native_file_system.cc
@@ -10,7 +10,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/network/public/mojom/web_sandbox_flags.mojom-blink.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_manager.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h" #include "third_party/blink/public/platform/web_content_settings_client.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" @@ -46,21 +46,21 @@ return; } - mojo::Remote<mojom::blink::NativeFileSystemManager> manager; + mojo::Remote<mojom::blink::FileSystemAccessManager> manager; context->GetBrowserInterfaceBroker().GetInterface( manager.BindNewPipeAndPassReceiver()); auto* raw_manager = manager.get(); raw_manager->GetSandboxedFileSystem(WTF::Bind( [](ScriptPromiseResolver* resolver, - mojo::Remote<mojom::blink::NativeFileSystemManager>, - mojom::blink::NativeFileSystemErrorPtr result, - mojo::PendingRemote<mojom::blink::NativeFileSystemDirectoryHandle> + mojo::Remote<mojom::blink::FileSystemAccessManager>, + mojom::blink::FileSystemAccessErrorPtr result, + mojo::PendingRemote<mojom::blink::FileSystemAccessDirectoryHandle> handle) { ExecutionContext* context = resolver->GetExecutionContext(); if (!context) return; - if (result->status != mojom::blink::NativeFileSystemStatus::kOk) { + if (result->status != mojom::blink::FileSystemAccessStatus::kOk) { native_file_system_error::Reject(resolver, *result); return; }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc index 39508a0f..c5cc3eaf 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -550,7 +550,7 @@ auto idb_value = std::make_unique<IDBValue>( value_wrappers[i].TakeWireBytes(), value_wrappers[i].TakeBlobInfo(), - value_wrappers[i].TakeNativeFileSystemTransferTokens()); + value_wrappers[i].TakeFileSystemAccessTransferTokens()); puts[i]->value = std::move(idb_value); } @@ -797,7 +797,7 @@ auto idb_value = std::make_unique<IDBValue>( value_wrapper.TakeWireBytes(), value_wrapper.TakeBlobInfo(), - value_wrapper.TakeNativeFileSystemTransferTokens()); + value_wrapper.TakeFileSystemAccessTransferTokens()); request->transit_blob_handles() = value_wrapper.TakeBlobDataHandles(); transaction_->transaction_backend()->Put(
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.cc b/third_party/blink/renderer/modules/indexeddb/idb_value.cc index e0a30940..6257731 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_value.cc
@@ -21,7 +21,7 @@ IDBValue::IDBValue( scoped_refptr<SharedBuffer> data, Vector<WebBlobInfo> blob_info, - Vector<mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>> + Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>> native_file_system_tokens) : data_(std::move(data)), blob_info_(std::move(blob_info)),
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value.h b/third_party/blink/renderer/modules/indexeddb/idb_value.h index 0fafc443..344d71b 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_value.h
@@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_transfer_token.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_transfer_token.mojom-blink-forward.h" #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key.h" #include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h" @@ -41,7 +41,7 @@ IDBValue( scoped_refptr<SharedBuffer>, Vector<WebBlobInfo>, - Vector<mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>> = + Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>> = {}); ~IDBValue(); @@ -54,7 +54,7 @@ const IDBKey* PrimaryKey() const { return primary_key_.get(); } const IDBKeyPath& KeyPath() const { return key_path_; } - Vector<mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>>& + Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>>& NativeFileSystemTokens() { return native_file_system_tokens_; } @@ -103,7 +103,7 @@ Vector<WebBlobInfo> blob_info_; - Vector<mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>> + Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>> native_file_system_tokens_; std::unique_ptr<IDBKey> primary_key_;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h index d21e3ec..c4980be 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h
@@ -154,8 +154,8 @@ return std::move(blob_info_); } - Vector<mojo::PendingRemote<mojom::blink::NativeFileSystemTransferToken>> - TakeNativeFileSystemTransferTokens() { + Vector<mojo::PendingRemote<mojom::blink::FileSystemAccessTransferToken>> + TakeFileSystemAccessTransferTokens() { #if DCHECK_IS_ON() DCHECK(done_cloning_) << __func__ << " called before DoneCloning()"; DCHECK(owns_file_system_handles_) << __func__ << " called twice";
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc index 5b60db8b..16dad28 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_blink_mojom_traits.cc
@@ -200,7 +200,7 @@ } for (auto& token : input->NativeFileSystemTokens()) { external_objects.push_back( - blink::mojom::blink::IDBExternalObject::NewNativeFileSystemToken( + blink::mojom::blink::IDBExternalObject::NewFileSystemAccessToken( std::move(token))); } return external_objects; @@ -230,8 +230,8 @@ Vector<blink::WebBlobInfo> value_blob_info; Vector< - mojo::PendingRemote<blink::mojom::blink::NativeFileSystemTransferToken>> - native_file_system_tokens; + mojo::PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken>> + file_system_access_tokens; for (const auto& object : external_objects) { switch (object->which()) { @@ -249,16 +249,16 @@ break; } case blink::mojom::blink::IDBExternalObject::Tag:: - NATIVE_FILE_SYSTEM_TOKEN: - native_file_system_tokens.push_back( - std::move(object->get_native_file_system_token())); + FILE_SYSTEM_ACCESS_TOKEN: + file_system_access_tokens.push_back( + std::move(object->get_file_system_access_token())); break; } } *out = std::make_unique<blink::IDBValue>( std::move(value_buffer), std::move(value_blob_info), - std::move(native_file_system_tokens)); + std::move(file_system_access_tokens)); return true; }
diff --git a/third_party/blink/renderer/modules/launch/file_handling_expiry_impl.cc b/third_party/blink/renderer/modules/launch/file_handling_expiry_impl.cc index a33c74d..6ff868f1 100644 --- a/third_party/blink/renderer/modules/launch/file_handling_expiry_impl.cc +++ b/third_party/blink/renderer/modules/launch/file_handling_expiry_impl.cc
@@ -7,7 +7,7 @@ #include <memory> #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
diff --git a/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc b/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc index 37ed2da..54a60780 100644 --- a/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc +++ b/third_party/blink/renderer/modules/launch/web_launch_service_impl.cc
@@ -7,7 +7,7 @@ #include <memory> #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/script/script.h" @@ -33,7 +33,7 @@ WebLaunchServiceImpl::~WebLaunchServiceImpl() = default; void WebLaunchServiceImpl::SetLaunchFiles( - WTF::Vector<mojom::blink::NativeFileSystemEntryPtr> entries) { + WTF::Vector<mojom::blink::FileSystemAccessEntryPtr> entries) { if (!window_) return;
diff --git a/third_party/blink/renderer/modules/launch/web_launch_service_impl.h b/third_party/blink/renderer/modules/launch/web_launch_service_impl.h index 7bcfbb5..eaa521e 100644 --- a/third_party/blink/renderer/modules/launch/web_launch_service_impl.h +++ b/third_party/blink/renderer/modules/launch/web_launch_service_impl.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_LAUNCH_WEB_LAUNCH_SERVICE_IMPL_H_ #include "mojo/public/cpp/bindings/pending_associated_receiver.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_directory_handle.mojom-blink-forward.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_directory_handle.mojom-blink-forward.h" #include "third_party/blink/public/mojom/web_launch/web_launch.mojom-blink.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/heap/persistent.h" @@ -31,7 +31,7 @@ // blink::mojom::WebLaunchService: void SetLaunchFiles( - WTF::Vector<mojom::blink::NativeFileSystemEntryPtr>) override; + WTF::Vector<mojom::blink::FileSystemAccessEntryPtr>) override; private: WeakPersistent<LocalDOMWindow> window_;
diff --git a/third_party/blink/renderer/modules/webcodecs/avc_encoder_config.idl b/third_party/blink/renderer/modules/webcodecs/avc_encoder_config.idl new file mode 100644 index 0000000..2ace0bf --- /dev/null +++ b/third_party/blink/renderer/modules/webcodecs/avc_encoder_config.idl
@@ -0,0 +1,14 @@ +// Copyright 2020 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. + +// https://github.com/WICG/web-codecs + +enum AvcBitstreamFormat { + "annexb", + "avc", +}; + +dictionary AvcEncoderConfig { + AvcBitstreamFormat format = "avc"; +};
diff --git a/third_party/blink/renderer/modules/webcodecs/idls.gni b/third_party/blink/renderer/modules/webcodecs/idls.gni index c211162..808d696 100644 --- a/third_party/blink/renderer/modules/webcodecs/idls.gni +++ b/third_party/blink/renderer/modules/webcodecs/idls.gni
@@ -25,6 +25,7 @@ modules_dictionary_idl_files = [ "audio_decoder_config.idl", "audio_decoder_init.idl", + "avc_encoder_config.idl", "encoded_video_chunk_init.idl", "encoded_audio_chunk_init.idl", "image_decoder_init.idl",
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc index 2fb40d2..cbe714d 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -31,6 +31,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_function.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_avc_encoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_encoder_encode_options.h" @@ -233,6 +234,26 @@ return nullptr; } + // We are done with the parsing. + if (!config->hasAvc()) + return parsed; + + // We should only get here with H264 codecs. + if (parsed->codec != media::VideoCodec::kCodecH264) { + exception_state.ThrowTypeError( + "'avcOptions' can only be used with AVC codecs"); + return nullptr; + } + + std::string avc_format = IDLEnumAsString(config->avc()->format()).Utf8(); + if (avc_format == "avc") { + parsed->options.avc.produce_annexb = false; + } else if (avc_format == "annexb") { + parsed->options.avc.produce_annexb = true; + } else { + NOTREACHED(); + } + return parsed; } @@ -375,7 +396,7 @@ bool VideoEncoder::CanReconfigure(ParsedConfig& original_config, ParsedConfig& new_config) { // Reconfigure is intended for things that don't require changing underlying - // codec implementatio and can be changed on the fly. + // codec implementation and can be changed on the fly. return original_config.codec == new_config.codec && original_config.profile == new_config.profile && original_config.level == new_config.level &&
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl b/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl index c151cb6b..088e951 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_config.idl
@@ -4,7 +4,6 @@ // https://github.com/WICG/web-codecs - enum VideoEncoderAccelerationPreference { "allow", "deny", @@ -21,4 +20,6 @@ required unsigned long width; required unsigned long height; -}; \ No newline at end of file + + AvcEncoderConfig avc; +};
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc index 0cd2e9f..314f845 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -28,6 +28,7 @@ #include "third_party/blink/renderer/platform/graphics/image.h" #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h" #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h" +#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h" #include "third_party/libyuv/include/libyuv.h" #include "third_party/skia/include/gpu/GrDirectContext.h" @@ -66,34 +67,38 @@ return false; } +struct YUVReadbackContext { + gfx::Size coded_size; + gfx::Rect visible_rect; + gfx::Size natural_size; + base::TimeDelta timestamp; + scoped_refptr<media::VideoFrame> frame; +}; + void OnYUVReadbackDone( - void* raw_frame_ptr, + void* raw_ctx, std::unique_ptr<const SkImage::AsyncReadResult> async_result) { - scoped_refptr<media::VideoFrame> frame( - static_cast<media::VideoFrame*>(raw_frame_ptr)); - if (!async_result) { - LOG(ERROR) << "Failed to read yuv420 back!"; + if (!async_result) return; - } - auto* data0 = static_cast<const uint8_t*>(async_result->data(0)); - DCHECK(data0); - auto* data1 = static_cast<const uint8_t*>(async_result->data(1)); - DCHECK(data1); - auto* data2 = static_cast<const uint8_t*>(async_result->data(2)); - DCHECK(data2); - gfx::Size size = frame->coded_size(); - libyuv::CopyPlane(data0, static_cast<int>(async_result->rowBytes(0)), - frame->visible_data(media::VideoFrame::kYPlane), - frame->stride(media::VideoFrame::kYPlane), size.width(), - size.height()); - libyuv::CopyPlane(data1, static_cast<int>(async_result->rowBytes(1)), - frame->visible_data(media::VideoFrame::kUPlane), - frame->stride(media::VideoFrame::kUPlane), size.width() / 2, - size.height() / 2); - libyuv::CopyPlane(data2, static_cast<int>(async_result->rowBytes(2)), - frame->visible_data(media::VideoFrame::kVPlane), - frame->stride(media::VideoFrame::kVPlane), size.width() / 2, - size.height() / 2); + auto* context = reinterpret_cast<YUVReadbackContext*>(raw_ctx); + context->frame = media::VideoFrame::WrapExternalYuvData( + media::PIXEL_FORMAT_I420, context->coded_size, context->visible_rect, + context->natural_size, static_cast<int>(async_result->rowBytes(0)), + static_cast<int>(async_result->rowBytes(1)), + static_cast<int>(async_result->rowBytes(2)), + // TODO(crbug.com/1161304): We should be able to wrap readonly memory in + // a VideoFrame without resorting to a const_cast. + reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(0))), + reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(1))), + reinterpret_cast<uint8_t*>(const_cast<void*>(async_result->data(2))), + context->timestamp); + if (!context->frame) + return; + context->frame->AddDestructionObserver( + ConvertToBaseOnceCallback(WTF::CrossThreadBindOnce( + base::DoNothing::Once< + std::unique_ptr<const SkImage::AsyncReadResult>>(), + std::move(async_result)))); } } // namespace @@ -127,49 +132,59 @@ return nullptr; } - gfx::Size size(source->width(), source->height()); - gfx::Rect rect(size); - base::TimeDelta timestamp = - base::TimeDelta::FromMicroseconds(init->timestamp()); + const gfx::Size coded_size(source->width(), source->height()); + const gfx::Rect visible_rect(coded_size); + const gfx::Size natural_size = coded_size; + const auto timestamp = base::TimeDelta::FromMicroseconds(init->timestamp()); + const auto& paint_image = source->BitmapImage()->PaintImageForCurrentFrame(); + const auto sk_image_info = paint_image.GetSkImageInfo(); - auto sk_image_info = - source->BitmapImage()->PaintImageForCurrentFrame().GetSkImageInfo(); auto sk_color_space = sk_image_info.refColorSpace(); - if (!sk_color_space) { + if (!sk_color_space) sk_color_space = SkColorSpace::MakeSRGB(); - } if (!IsValidSkColorSpace(sk_color_space)) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Invalid color space"); return nullptr; } - auto frame = media::VideoFrame::CreateFrame(media::PIXEL_FORMAT_I420, size, - rect, size, timestamp); - if (!frame) { - exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError, - "Frame creation failed"); - return nullptr; - } + const bool is_texture = paint_image.IsTextureBacked(); + const auto sk_image = paint_image.GetSkImage(); - bool is_texture = - source->BitmapImage()->PaintImageForCurrentFrame().IsTextureBacked(); + scoped_refptr<media::VideoFrame> frame; + // Now only SkImage_Gpu implemented the readbackYUV420 method, so for // non-texture image, still use libyuv do the csc until SkImage_Base // implement asyncRescaleAndReadPixelsYUV420. if (is_texture) { - auto sk_image = - source->BitmapImage()->PaintImageForCurrentFrame().GetSkImage(); - SkIRect src_rect = SkIRect::MakeWH(source->width(), source->height()); + YUVReadbackContext result; + result.coded_size = coded_size; + result.visible_rect = visible_rect; + result.natural_size = natural_size; + result.timestamp = timestamp; + + // While this function indicates it's asynchronous, the flushAndSubmit() + // call below ensures it completes synchronously. + const auto src_rect = SkIRect::MakeWH(source->width(), source->height()); sk_image->asyncRescaleAndReadPixelsYUV420( kRec709_SkYUVColorSpace, sk_color_space, src_rect, {source->width(), source->height()}, SkImage::RescaleGamma::kSrc, - kHigh_SkFilterQuality, &OnYUVReadbackDone, frame.get()); + kHigh_SkFilterQuality, &OnYUVReadbackDone, &result); GrDirectContext* gr_context = source->BitmapImage()->ContextProvider()->GetGrContext(); DCHECK(gr_context); gr_context->flushAndSubmit(/*syncCpu=*/true); + + if (!result.frame) { + exception_state.ThrowDOMException(DOMExceptionCode::kOperationError, + "YUV conversion error during readback"); + return nullptr; + } + + frame = std::move(result.frame); } else { + DCHECK(!sk_image->isTextureBacked()); + auto sk_color_type = sk_image_info.colorType(); if (!IsValidSkColorType(sk_color_type)) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, @@ -177,47 +192,30 @@ return nullptr; } - // TODO(jie.a.chen@intel.com): Handle data of float type. - // Full copy #1 - WTF::Vector<uint8_t> pixel_data = - source->CopyBitmapData(source->GetBitmapSkImageInfo(), false); - if (pixel_data.size() < - media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_ARGB, size)) { - exception_state.ThrowDOMException(DOMExceptionCode::kBufferOverrunError, - "Image buffer is too small."); - return nullptr; - } - DCHECK(sk_color_type == kRGBA_8888_SkColorType || sk_color_type == kBGRA_8888_SkColorType); - auto libyuv_convert_to_i420 = (sk_color_type == kRGBA_8888_SkColorType) - ? libyuv::ABGRToI420 - : libyuv::ARGBToI420; - // TODO(jie.a.chen@intel.com): Use GPU to do the conversion. - // Full copy #2 - int error = - libyuv_convert_to_i420(pixel_data.data(), source->width() * 4, - frame->visible_data(media::VideoFrame::kYPlane), - frame->stride(media::VideoFrame::kYPlane), - frame->visible_data(media::VideoFrame::kUPlane), - frame->stride(media::VideoFrame::kUPlane), - frame->visible_data(media::VideoFrame::kVPlane), - frame->stride(media::VideoFrame::kVPlane), - source->width(), source->height()); - if (error) { - exception_state.ThrowDOMException(DOMExceptionCode::kOperationError, - "ARGB to YUV420 conversion error"); - return nullptr; - } - gfx::ColorSpace gfx_color_space(*sk_color_space); - // 'libyuv_convert_to_i420' assumes SMPTE170M. - // Refer to the func below to check the actual conversion: - // third_party/libyuv/source/row_common.cc -- RGBToY(...) - gfx_color_space = gfx_color_space.GetWithMatrixAndRange( - gfx::ColorSpace::MatrixID::SMPTE170M, - gfx::ColorSpace::RangeID::LIMITED); - frame->set_color_space(gfx_color_space); + SkPixmap pm; + const bool peek_result = sk_image->peekPixels(&pm); + DCHECK(peek_result); + + const auto format = sk_image->isOpaque() + ? (sk_color_type == kRGBA_8888_SkColorType + ? media::PIXEL_FORMAT_XBGR + : media::PIXEL_FORMAT_XRGB) + : (sk_color_type == kRGBA_8888_SkColorType + ? media::PIXEL_FORMAT_ABGR + : media::PIXEL_FORMAT_ARGB); + + frame = media::VideoFrame::WrapExternalData( + format, coded_size, visible_rect, natural_size, + // TODO(crbug.com/1161304): We should be able to wrap readonly memory in + // a VideoFrame instead of using writable_addr() here. + reinterpret_cast<uint8_t*>(pm.writable_addr()), pm.computeByteSize(), + timestamp); + frame->set_color_space(gfx::ColorSpace(*sk_color_space)); + frame->AddDestructionObserver(ConvertToBaseOnceCallback(CrossThreadBindOnce( + base::DoNothing::Once<sk_sp<SkImage>>(), std::move(sk_image)))); } auto* result = MakeGarbageCollected<VideoFrame>( std::move(frame), ExecutionContext::From(script_state)); @@ -226,14 +224,28 @@ // static bool VideoFrame::IsSupportedPlanarFormat(media::VideoFrame* frame) { - // For now only I420, I420A, or NV12 in CPU or GPU memory is supported. - return frame && (frame->IsMappable() || frame->HasGpuMemoryBuffer()) && - ((frame->format() == media::PIXEL_FORMAT_I420 && - frame->layout().num_planes() == 3) || - (frame->format() == media::PIXEL_FORMAT_I420A && - frame->layout().num_planes() == 4) || - (frame->format() == media::PIXEL_FORMAT_NV12 && - frame->layout().num_planes() == 2)); + if (!frame) + return false; + + if (!frame->IsMappable() && !frame->HasGpuMemoryBuffer()) + return false; + + const size_t num_planes = frame->layout().num_planes(); + switch (frame->format()) { + case media::PIXEL_FORMAT_I420: + return num_planes == 3; + case media::PIXEL_FORMAT_I420A: + return num_planes == 4; + case media::PIXEL_FORMAT_NV12: + return num_planes == 2; + case media::PIXEL_FORMAT_XBGR: + case media::PIXEL_FORMAT_XRGB: + case media::PIXEL_FORMAT_ABGR: + case media::PIXEL_FORMAT_ARGB: + return num_planes == 1; + default: + return false; + } } String VideoFrame::format() const { @@ -247,7 +259,14 @@ return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kI420); case media::PIXEL_FORMAT_NV12: return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kNV12); - + case media::PIXEL_FORMAT_ABGR: + return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kABGR); + case media::PIXEL_FORMAT_XBGR: + return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kXBGR); + case media::PIXEL_FORMAT_ARGB: + return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kARGB); + case media::PIXEL_FORMAT_XRGB: + return V8VideoPixelFormat(V8VideoPixelFormat::Enum::kXRGB); default: NOTREACHED(); return String(); @@ -466,28 +485,32 @@ } #endif // !defined(OS_ANDROID) + const bool is_rgb = local_frame->format() == media::PIXEL_FORMAT_ARGB || + local_frame->format() == media::PIXEL_FORMAT_XRGB || + local_frame->format() == media::PIXEL_FORMAT_ABGR || + local_frame->format() == media::PIXEL_FORMAT_XBGR; + if ((local_frame->IsMappable() && (local_frame->format() == media::PIXEL_FORMAT_I420 || local_frame->format() == media::PIXEL_FORMAT_I420A)) || (local_frame->HasTextures() && (local_frame->format() == media::PIXEL_FORMAT_I420 || local_frame->format() == media::PIXEL_FORMAT_I420A || - local_frame->format() == media::PIXEL_FORMAT_NV12 || - local_frame->format() == media::PIXEL_FORMAT_ABGR || - local_frame->format() == media::PIXEL_FORMAT_XRGB))) { + local_frame->format() == media::PIXEL_FORMAT_NV12)) || + is_rgb) { scoped_refptr<StaticBitmapImage> image; gfx::ColorSpace gfx_color_space = local_frame->ColorSpace(); gfx_color_space = gfx_color_space.GetWithMatrixAndRange( gfx::ColorSpace::MatrixID::RGB, gfx::ColorSpace::RangeID::FULL); auto sk_color_space = gfx_color_space.ToSkColorSpace(); - if (!sk_color_space) { + if (!sk_color_space) sk_color_space = SkColorSpace::MakeSRGB(); - } const bool prefer_accelerated_image_bitmap = local_frame->format() != media::PIXEL_FORMAT_I420A && (BitmapSourceSize().Area() > kCpuEfficientFrameSize || - local_frame->HasTextures()); + local_frame->HasTextures()) && + (!is_rgb || local_frame->HasTextures()); if (!prefer_accelerated_image_bitmap) { size_t bytes_per_row = sizeof(SkColor) * cropWidth();
diff --git a/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl b/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl index 2ed2476..dec3f3b5 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl +++ b/third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl
@@ -14,6 +14,12 @@ // 32bpp RGBA (byte-order), 1 plane. "ABGR", + // 32bpp BGRA (byte-order), 1 plane. + "ARGB", + + // 24bpp RGBX (byte-order), 1 plane. + "XBGR", + // 24bpp BGRX (byte-order), 1 plane. "XRGB", };
diff --git a/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc b/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc index bae9ffb0..8074424 100644 --- a/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc +++ b/third_party/blink/renderer/platform/mojo/drag_mojom_traits.cc
@@ -14,7 +14,7 @@ #include "mojo/public/cpp/base/big_buffer.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/referrer_policy.mojom-shared.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom-blink.h" #include "third_party/blink/public/platform/file_path_conversion.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_vector.h" @@ -102,10 +102,10 @@ item.storage_type = blink::WebDragData::Item::kStorageTypeFilename; item.filename_data = blink::FilePathToWebString(filename_data); item.display_name_data = blink::FilePathToWebString(display_name_data); - mojo::PendingRemote<::blink::mojom::blink::NativeFileSystemDragDropToken> + mojo::PendingRemote<::blink::mojom::blink::FileSystemAccessDragDropToken> native_file_system_token( - data.TakeNativeFileSystemToken<mojo::PendingRemote< - ::blink::mojom::blink::NativeFileSystemDragDropToken>>()); + data.TakeFileSystemAccessToken<mojo::PendingRemote< + ::blink::mojom::blink::FileSystemAccessDragDropToken>>()); item.native_file_system_entry = base::MakeRefCounted<::blink::NativeFileSystemDropData>( std::move(native_file_system_token)); @@ -182,9 +182,9 @@ } // static -mojo::PendingRemote<blink::mojom::blink::NativeFileSystemDragDropToken> +mojo::PendingRemote<blink::mojom::blink::FileSystemAccessDragDropToken> StructTraits<blink::mojom::DragItemFileDataView, blink::WebDragData::Item>:: - native_file_system_token(const blink::WebDragData::Item& item) { + file_system_access_token(const blink::WebDragData::Item& item) { // Should never have to send a transfer token information from the renderer // to the browser. DCHECK(!item.native_file_system_entry);
diff --git a/third_party/blink/renderer/platform/mojo/drag_mojom_traits.h b/third_party/blink/renderer/platform/mojo/drag_mojom_traits.h index de0f831..76763e3 100644 --- a/third_party/blink/renderer/platform/mojo/drag_mojom_traits.h +++ b/third_party/blink/renderer/platform/mojo/drag_mojom_traits.h
@@ -16,7 +16,7 @@ #include "mojo/public/cpp/bindings/struct_traits.h" #include "mojo/public/cpp/bindings/union_traits.h" #include "services/network/public/mojom/referrer_policy.mojom-forward.h" -#include "third_party/blink/public/mojom/file_system_access/native_file_system_drag_drop_token.mojom-blink.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_drag_drop_token.mojom-blink.h" #include "third_party/blink/public/mojom/page/drag.mojom-shared.h" #include "third_party/blink/public/platform/web_drag_data.h" #include "third_party/blink/renderer/platform/mojo/kurl_mojom_traits.h" @@ -53,8 +53,8 @@ blink::WebDragData::Item> { static base::FilePath path(const blink::WebDragData::Item& item); static base::FilePath display_name(const blink::WebDragData::Item& item); - static mojo::PendingRemote<blink::mojom::blink::NativeFileSystemDragDropToken> - native_file_system_token(const blink::WebDragData::Item& item); + static mojo::PendingRemote<blink::mojom::blink::FileSystemAccessDragDropToken> + file_system_access_token(const blink::WebDragData::Item& item); static bool Read(blink::mojom::DragItemFileDataView data, blink::WebDragData::Item* out); };
diff --git a/third_party/blink/tools/blinkpy/common/net/results_fetcher.py b/third_party/blink/tools/blinkpy/common/net/results_fetcher.py index b269148..49b4e2870 100644 --- a/third_party/blink/tools/blinkpy/common/net/results_fetcher.py +++ b/third_party/blink/tools/blinkpy/common/net/results_fetcher.py
@@ -41,6 +41,7 @@ TEST_RESULTS_SERVER = 'https://test-results.appspot.com' RESULTS_URL_BASE = '%s/data/layout_results' % TEST_RESULTS_SERVER +RESULTS_SUMMARY_URL_BASE = 'https://storage.googleapis.com/chromium-layout-test-archives' class Build(collections.namedtuple('Build', ('builder_name', 'build_number'))): @@ -85,33 +86,50 @@ return '%s/%s/layout-test-results' % (url_base, build_number) return self.accumulated_results_url_base(builder_name) - def builder_results_url_base(self, builder_name): - """Returns the URL for the given builder's directory in Google Storage. + def get_full_builder_url(self, url_base, builder_name): + """ Returns the url for a builder directory in google storage. Each builder has a directory in the GS bucket, and the directory name is the builder name transformed to be more URL-friendly by replacing all spaces, periods and parentheses with underscores. """ - return '%s/%s' % (RESULTS_URL_BASE, re.sub('[ .()]', '_', - builder_name)) + return '%s/%s' % (url_base, re.sub('[ .()]', '_', builder_name)) + + def builder_results_url_base(self, builder_name): + """Returns the URL for the given builder's directory in Google Storage. + """ + return self.get_full_builder_url(RESULTS_URL_BASE, builder_name) + + def builder_retry_results_url_base(self, builder_name): + """Returns the URL for the given builder's directory in Google Storage. + + This is used for fetching the retry data which is now contained in + test_results_summary.json which cannot be fetched from + https://test-results.appspot.com anymore. Migrating this tool to use + resultDB is the ideal solution. + """ + return self.get_full_builder_url(RESULTS_SUMMARY_URL_BASE, + builder_name) @memoized def fetch_retry_summary_json(self, build): - """Fetches and returns the text of the archived retry_summary file. + """Fetches and returns the text of the archived test_results_summary.json file. This file is expected to contain the results of retrying web tests with and without a patch in a try job. It includes lists of tests that failed only with the patch ("failures"), and tests that failed both with and without ("ignored"). """ - url_base = '%s/%s' % (self.builder_results_url_base( + url_base = '%s/%s' % (self.builder_retry_results_url_base( build.builder_name), build.build_number) - # Originally we used retry_summary.json, which is the summary of retry - # without patch; now we retry again with patch and ignore the flakes. - # See https://crbug.com/882969. - return self.web.get_binary( - '%s/%s' % (url_base, 'retry_with_patch_summary.json'), - return_none_on_404=True) + # NOTE(crbug.com/1082907): We used to fetch retry_with_patch_summary.json from + # test-results.appspot.com. The file has been renamed and can no longer be + # accessed via test-results, so we download it from GCS directly. + # There is still a bug in uploading this json file for other platforms than linux. + # see https://crbug.com/1157202 + return self.web.get_binary('%s/%s' % + (url_base, 'test_results_summary.json'), + return_none_on_404=True) def accumulated_results_url_base(self, builder_name): return self.builder_results_url_base(
diff --git a/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py b/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py index d0fd2b1f..94b7efd 100644 --- a/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py +++ b/third_party/blink/tools/blinkpy/common/net/results_fetcher_test.py
@@ -209,6 +209,21 @@ {'passed': True}) self.assertLog([]) + def test_get_full_builder_url(self): + fetcher = TestResultsFetcher() + self.assertEqual( + fetcher.get_full_builder_url('https://storage.googleapis.com', + 'foo bar'), + 'https://storage.googleapis.com/foo_bar') + self.assertEqual( + fetcher.get_full_builder_url('https://storage.googleapis.com', + 'foo.bar'), + 'https://storage.googleapis.com/foo_bar') + self.assertEqual( + fetcher.get_full_builder_url('https://storage.googleapis.com', + 'foo(bar)'), + 'https://storage.googleapis.com/foo_bar_') + class TestResultsFetcherHelperFunctionTest(unittest.TestCase): def test_filter_latest_jobs_empty(self):
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index ea9248e..eb579d4 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3286,22 +3286,17 @@ # Subgrid is not implemented yet crbug.com/618969 external/wpt/css/css-grid/subgrid/* [ Skip ] -# Tests that pass with layout-ng-grid enabled but fail in legacy grid: -virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/descendant-static-position-003.html [ Pass ] -virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-8.html [ Pass ] -virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-9.html [ Pass ] -virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-10.html [ Pass ] -virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/replaced-alignment-with-aspect-ratio-001.tentative.html [ Pass ] -virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/replaced-alignment-with-aspect-ratio-002.tentative.html [ Pass ] - # [layout-ng-grid] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/absolute-positioning-definite-sizes-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-containing-block-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/absolute-positioning-grid-container-parent-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/descendant-static-position-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/descendant-static-position-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/descendant-static-position-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/descendant-static-position-004.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/empty-grid-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-paint-positioned-children-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-item-dynamic-change-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-002.html [ Failure ] @@ -3310,14 +3305,20 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-005.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-006.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-and-autofit-tracks-007.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-background-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-background-rtl-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-content-alignment-rtl-001.html [ Failure ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-001.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-rtl-001.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-001.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-padding-001.html [ Crash ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-002-rtl.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-gaps-rtl-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-implicit-grid-line-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-padding-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-unknown-named-grid-line-001.html [ Failure ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html [ Crash ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-positioned-items-within-grid-implicit-track-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/grid-sizing-positioned-items-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-descendants-002.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-descendants-003.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-descendants-004.html [ Failure ] @@ -3333,6 +3334,23 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-descendants-014.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-descendants-015.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-descendants-016.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-004.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-005.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-006.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-007.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-008.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-009.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-010.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-011.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-012.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-013.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-014.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-015.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-016.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/orthogonal-positioned-grid-items-017.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-descendants-002.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-descendants-003.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-descendants-004.html [ Failure ] @@ -3348,6 +3366,25 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-descendants-014.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-descendants-015.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-descendants-016.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-004.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-005.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-006.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-007.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-008.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-009.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-010.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-011.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-012.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-013.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-014.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-015.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-016.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-017.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-should-not-create-implicit-tracks-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/abspos/positioned-grid-items-sizing-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-align-baseline-vertical.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-align-baseline.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-align-content-distribution-vertical-lr.html [ Failure ] @@ -3377,11 +3414,22 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-align-cycles-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-012.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-013.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-014.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-015.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-016.html [ Crash ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-004.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-005.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-006.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-007.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-008.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-009.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-010.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-011.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-012.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-013.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-014.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-015.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-016.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-alignment-positioned-items-017.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-self-baseline-synthesized-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-column-axis-self-baseline-synthesized-002.html [ Failure ] @@ -3461,27 +3509,56 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-5.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-6.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-item-no-aspect-ratio-stretch-7.html [ Failure ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-012.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-013.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-014.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-015.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-016.html [ Crash ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-004.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-005.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-006.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-007.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-008.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-009.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-010.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-011.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-012.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-013.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-014.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-015.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-016.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-alignment-positioned-items-017.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-self-baseline-synthesized-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-self-baseline-synthesized-002.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-self-baseline-synthesized-003.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-self-baseline-synthesized-004.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-row-axis-self-baseline-synthesized-005.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-004.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-005.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-006.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-007.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-008.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-009.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-010.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-011.html [ Failure ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-011.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-012.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-013.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-014.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-015.html [ Crash ] -crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-016.html [ Crash ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-012.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-001.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-002.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-004.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-005.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-006.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-007.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-008.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-009.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-010.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-011.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-012.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-013.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-014.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-015.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-016.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-stretch-009.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-stretch-010.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-alignment-stretch-011.html [ Failure ] @@ -3509,6 +3586,8 @@ crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-baseline-not-applied-if-sizing-cyclic-dependency-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-baseline-not-applied-if-sizing-cyclic-dependency-002.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-self-baseline-not-applied-if-sizing-cyclic-dependency-003.html [ Failure ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/replaced-alignment-with-aspect-ratio-001.tentative.html [ Pass ] +crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/replaced-alignment-with-aspect-ratio-002.tentative.html [ Pass ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-001.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-002-b.html [ Failure ] crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/self-baseline/grid-self-baseline-002.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/nested-blob-url-workers.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/nested-blob-url-workers.https.html new file mode 100644 index 0000000..7269cbb7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/nested-blob-url-workers.https.html
@@ -0,0 +1,42 @@ +<!doctype html> +<meta charset=utf-8> +<title>Service Worker: nested blob URL worker clients</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/test-helpers.sub.js"></script> +<body> +<script> + +const SCRIPT = 'resources/simple-intercept-worker.js'; +const SCOPE = 'resources/'; +const RESOURCE = 'resources/simple.txt'; + +promise_test((t) => { + return runTest(t, 'resources/nested-blob-url-workers.html'); +}, 'Nested blob URL workers should be intercepted by a service worker.'); + +promise_test((t) => { + return runTest(t, 'resources/nested-worker-created-from-blob-url-worker.html'); +}, 'Nested worker created from a blob URL worker should be intercepted by a service worker.'); + +promise_test((t) => { + return runTest(t, 'resources/nested-blob-url-worker-created-from-worker.html'); +}, 'Nested blob URL worker created from a worker should be intercepted by a service worker.'); + +async function runTest(t, iframe_url) { + const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE); + t.add_cleanup(_ => reg.unregister()); + await wait_for_state(t, reg.installing, 'activated'); + + const frame = await with_iframe(iframe_url); + t.add_cleanup(_ => frame.remove()); + assert_not_equals(frame.contentWindow.navigator.serviceWorker.controller, + null, 'frame should be controlled'); + + const response_text = await frame.contentWindow.fetch_in_worker(RESOURCE); + assert_equals(response_text, 'intercepted by service worker', + 'fetch() should be intercepted.'); +} + +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/create-blob-url-worker.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/create-blob-url-worker.js new file mode 100644 index 0000000..57e4882 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/create-blob-url-worker.js
@@ -0,0 +1,22 @@ +const childWorkerScript = ` + self.onmessage = async (e) => { + const response = await fetch(e.data); + const text = await response.text(); + self.postMessage(text); + }; +`; +const blob = new Blob([childWorkerScript], { type: 'text/javascript' }); +const blobUrl = URL.createObjectURL(blob); +const childWorker = new Worker(blobUrl); + +// When a message comes from the parent frame, sends a resource url to the child +// worker. +self.onmessage = (e) => { + childWorker.postMessage(e.data); +}; + +// When a message comes from the child worker, sends a content of fetch() to the +// parent frame. +childWorker.onmessage = (e) => { + self.postMessage(e.data); +};
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-blob-url-worker-created-from-worker.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-blob-url-worker-created-from-worker.html new file mode 100644 index 0000000..fc048e2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-blob-url-worker-created-from-worker.html
@@ -0,0 +1,16 @@ +<!doctype html> +<script> +const baseLocation = window.location; +const workerUrl = new URL('create-blob-url-worker.js', baseLocation).href; +const worker = new Worker(workerUrl); + +function fetch_in_worker(url) { + const resourceUrl = new URL(url, baseLocation).href; + return new Promise((resolve) => { + worker.onmessage = (event) => { + resolve(event.data); + }; + worker.postMessage(resourceUrl); + }); +} +</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-blob-url-workers.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-blob-url-workers.html new file mode 100644 index 0000000..f0eafcd3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-blob-url-workers.html
@@ -0,0 +1,38 @@ +<!doctype html> +<script> +const baseLocation = window.location; +const parentWorkerScript = ` + const childWorkerScript = 'self.onmessage = async (e) => {' + + ' const response = await fetch(e.data);' + + ' const text = await response.text();' + + ' self.postMessage(text);' + + '};'; + const blob = new Blob([childWorkerScript], { type: 'text/javascript' }); + const blobUrl = URL.createObjectURL(blob); + const childWorker = new Worker(blobUrl); + + // When a message comes from the parent frame, sends a resource url to the + // child worker. + self.onmessage = (e) => { + childWorker.postMessage(e.data); + }; + // When a message comes from the child worker, sends a content of fetch() to + // the parent frame. + childWorker.onmessage = (e) => { + self.postMessage(e.data); + }; +`; +const blob = new Blob([parentWorkerScript], { type: 'text/javascript' }); +const blobUrl = URL.createObjectURL(blob); +const worker = new Worker(blobUrl); + +function fetch_in_worker(url) { + const resourceUrl = new URL(url, baseLocation).href; + return new Promise((resolve) => { + worker.onmessage = (event) => { + resolve(event.data); + }; + worker.postMessage(resourceUrl); + }); +} +</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-worker-created-from-blob-url-worker.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-worker-created-from-blob-url-worker.html new file mode 100644 index 0000000..3fad2c9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/nested-worker-created-from-blob-url-worker.html
@@ -0,0 +1,33 @@ +<!doctype html> +<script> +const baseLocation = window.location; +const parentWorkerScript = ` + const workerUrl = + new URL('postmessage-fetched-text.js', '${baseLocation}').href; + const childWorker = new Worker(workerUrl); + + // When a message comes from the parent frame, sends a resource url to the + // child worker. + self.onmessage = (e) => { + childWorker.postMessage(e.data); + }; + // When a message comes from the child worker, sends a content of fetch() to + // the parent frame. + childWorker.onmessage = (e) => { + self.postMessage(e.data); + }; +`; +const blob = new Blob([parentWorkerScript], { type: 'text/javascript' }); +const blobUrl = URL.createObjectURL(blob); +const worker = new Worker(blobUrl); + +function fetch_in_worker(url) { + const resourceUrl = new URL(url, baseLocation).href; + return new Promise((resolve) => { + worker.onmessage = (event) => { + resolve(event.data); + }; + worker.postMessage(resourceUrl); + }); +} +</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/postmessage-fetched-text.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/postmessage-fetched-text.js new file mode 100644 index 0000000..9fc6717 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/postmessage-fetched-text.js
@@ -0,0 +1,5 @@ +self.onmessage = async (e) => { + const response = await fetch(e.data); + const text = await response.text(); + self.postMessage(text); +};
diff --git a/third_party/blink/web_tests/external/wpt_automation/input-events/input-events-typing-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/input-events/input-events-typing-manual-automation.js deleted file mode 100644 index 8dd519f..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/input-events/input-events-typing-manual-automation.js +++ /dev/null
@@ -1,11 +0,0 @@ -importAutomationScript('/input-events/inputevent_common_input.js'); - -function inject_input() { - return focusAndKeyDown('#plain', 'a').then(() => { - return keyDown('B', ['shiftKey']); - }).then(() => { - return focusAndKeyDown('#rich', 'c'); - }).then(() => { - return keyDown('D', ['shiftKey']); - }); -}
diff --git a/third_party/blink/web_tests/external/wpt_automation/input-events/inputevent_common_input.js b/third_party/blink/web_tests/external/wpt_automation/input-events/inputevent_common_input.js deleted file mode 100644 index 2db123b9..0000000 --- a/third_party/blink/web_tests/external/wpt_automation/input-events/inputevent_common_input.js +++ /dev/null
@@ -1,52 +0,0 @@ -// Returns a Promise for future conversion into WebDriver-backed API. -function keyDown(key, modifiers) { - return new Promise(function(resolve, reject) { - if (window.eventSender) { - eventSender.keyDown(key, modifiers); - resolve(); - } else { - reject(); - } - }); -} - -function selectTarget(selector) { - const target = document.querySelector(selector); - if (target.select) { - target.select(); - } else { - const selection = window.getSelection(); - selection.collapse(target, 0); - selection.extend(target, 1); - } -} - -// Combined convenient methods. - -function focusAndKeyDown(selector, key, modifiers) { - document.querySelector(selector).focus(); - return keyDown(key, modifiers); -} - -function collapseEndAndKeyDown(selector, key, modifiers) { - const target = document.querySelector(selector); - window.getSelection().collapse(target.lastElementChild || target, 1); - return keyDown(key, modifiers); -} - -function selectAndKeyDown(selector, key, modifiers) { - selectTarget(selector); - return keyDown(key, modifiers); -} - -function selectAndExecCommand(selector, command) { - assert_not_equals(window.testRunner, undefined, 'This test requires testRunner.'); - selectTarget(selector); - testRunner.execCommand(command); -} - -{ - const inputevent_automation = async_test("InputEvent Automation"); - // Defined in every test and should return a promise that gets resolved when input is finished. - inject_input().then(inputevent_automation.step_func_done()); -}
diff --git a/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint-expected.txt b/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint-expected.txt index 0a92b513..1372ad0 100644 --- a/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint-expected.txt +++ b/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint-expected.txt
@@ -4,7 +4,7 @@ frameId : <string> lcpDetails : { elementId : text - loadTime : <number> + loadTime : 0 nodeId : <div#text> renderTime : <number> size : 48000 @@ -19,7 +19,7 @@ elementId : image loadTime : <number> nodeId : <img#image> - renderTime : <number> + renderTime : 0 size : 65536 url : .../images/resources/green-256x256.jpg }
diff --git a/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint.js b/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint.js index cc7fe53..b36c646 100644 --- a/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint.js +++ b/third_party/blink/web_tests/inspector-protocol/performance-timeline/largest-contentful-paint.js
@@ -1,11 +1,14 @@ (async function(testRunner) { const {page, session, dp} = await testRunner.startBlank('Basic test for LargestContentfulPaint support in PerformanceTimeline'); - const unstableFields = ['time', 'renderTime', 'loadTime', 'frameId']; + const unstableFields = ['frameId']; const events = []; const startTime = Date.now(); await dp.PerformanceTimeline.enable({eventTypes: ['largest-contentful-paint']}); + const TestHelper = await testRunner.loadScript('resources/performance-timeline-test.js'); + const testHelper = new TestHelper(dp); + dp.PerformanceTimeline.onTimelineEventAdded(event => events.push(event.params.event)); session.navigate(testRunner.url('resources/lcp.html')); await dp.PerformanceTimeline.onceTimelineEventAdded(); @@ -21,33 +24,18 @@ const endTime = Date.now(); for (const event of events) { - checkTime(event.time); - if (event.lcpDetails.renderTime) - checkTime(event.lcpDetails.renderTime); - if (event.lcpDetails.loadTime) - checkTime(event.lcpDetails.loadTime); + testHelper.patchTimes(startTime, endTime, event, ['time']); + testHelper.patchTimes(startTime, endTime, event.lcpDetails, ['renderTime', 'loadTime']); await patchFields(event.lcpDetails); } testRunner.log(events, null, unstableFields); testRunner.completeTest(); - function checkTime(time) { - const timeInMs = time * 1000; - if (timeInMs < startTime || timeInMs > endTime) - testRunner.log(`FAIL: event time out of bounds, expect ${startTime} <= ${timeInMs} <= ${endTime}`); - } - async function patchFields(object) { if (object.url) object.url = testRunner.trimURL(object.url); if (object.nodeId) - object.nodeId = await describeNode(object.nodeId); - } - - async function describeNode(nodeId) { - const response = await dp.DOM.resolveNode({backendNodeId: nodeId}); - return response.result && response.result.object.description ? - `<${response.result.object.description}>` : '<invalid id>'; + object.nodeId = await testHelper.describeNode(object.nodeId); } })
diff --git a/third_party/blink/web_tests/inspector-protocol/performance-timeline/layout-shift-expected.txt b/third_party/blink/web_tests/inspector-protocol/performance-timeline/layout-shift-expected.txt new file mode 100644 index 0000000..5db69cd --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/performance-timeline/layout-shift-expected.txt
@@ -0,0 +1,75 @@ +Basic test for LayoutShift support in PerformanceTimeline +[ + [0] : { + frameId : <string> + layoutShiftDetails : { + hadRecentInput : false + lastInputTime : 0 + sources : [ + [0] : { + currentRect : { + height : 100 + width : 20 + x : 8 + y : 126 + } + nodeId : <div#padding2> + previousRect : { + height : 100 + width : 20 + x : 8 + y : 26 + } + } + [1] : { + currentRect : { + height : 120 + width : 400 + x : 38 + y : 108 + } + nodeId : <div#text> + previousRect : { + height : 120 + width : 400 + x : 38 + y : 8 + } + } + ] + value : 0.023958333333333335 + } + name : + time : <number> + type : layout-shift + } + [1] : { + frameId : <string> + layoutShiftDetails : { + hadRecentInput : true + lastInputTime : <number> + sources : [ + [0] : { + currentRect : { + height : 120 + width : 400 + x : 118 + y : 108 + } + nodeId : <div#text> + previousRect : { + height : 120 + width : 400 + x : 38 + y : 108 + } + } + ] + value : 0.012 + } + name : + time : <number> + type : layout-shift + } +] +
diff --git a/third_party/blink/web_tests/inspector-protocol/performance-timeline/layout-shift.js b/third_party/blink/web_tests/inspector-protocol/performance-timeline/layout-shift.js new file mode 100644 index 0000000..1d6fea6a --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/performance-timeline/layout-shift.js
@@ -0,0 +1,51 @@ +(async function(testRunner) { + const {page, session, dp} = await testRunner.startBlank('Basic test for LayoutShift support in PerformanceTimeline'); + const unstableFields = ['frameId']; + + const events = []; + const startTime = Date.now(); + + await dp.PerformanceTimeline.enable({eventTypes: ['layout-shift']}); + + const TestHelper = await testRunner.loadScript('resources/performance-timeline-test.js'); + const testHelper = new TestHelper(dp); + + dp.PerformanceTimeline.onTimelineEventAdded(event => events.push(event.params.event)); + await session.navigate(testRunner.url('resources/layout-shift.html')); + await session.evaluateAsync(`new Promise(resolve => requestAnimationFrame(resolve))`); + + session.evaluate(` + document.getElementById('padding1').style.display = 'block'; + `); + await dp.PerformanceTimeline.onceTimelineEventAdded(); + + // Now make an input-induced layout shift to assure input-related fields + // are properly populated. + click(10, 150); + + await dp.PerformanceTimeline.onceTimelineEventAdded(); + + const endTime = Date.now(); + + for (const event of events) { + testHelper.patchTimes(startTime, endTime, event, ['time']); + testHelper.patchTimes(startTime, endTime, event.layoutShiftDetails, ['lastInputTime']); + await patchFields(event.layoutShiftDetails); + } + + testRunner.log(events, null, unstableFields); + testRunner.completeTest(); + + async function patchFields(object) { + for (const source of object.sources) { + if (source.nodeId) + source.nodeId = await testHelper.describeNode(source.nodeId); + } + } + + async function click(x, y) { + await dp.Input.dispatchMouseEvent({type: 'mouseMoved', button: 'left', buttons: 0, clickCount: 1, x, y }); + await dp.Input.dispatchMouseEvent({type: 'mousePressed', button: 'left', buttons: 0, clickCount: 1, x, y }); + await dp.Input.dispatchMouseEvent({type: 'mouseReleased', button: 'left', buttons: 1, clickCount: 1, x, y }); + } +})
diff --git a/third_party/blink/web_tests/inspector-protocol/performance-timeline/resources/layout-shift.html b/third_party/blink/web_tests/inspector-protocol/performance-timeline/resources/layout-shift.html new file mode 100644 index 0000000..9d00280 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/performance-timeline/resources/layout-shift.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>LCP Test Page</title> +<style> + body { + font: 10px Ahem; + } + div#padding1 { + height: 100px; + } + div#padding2 { + display: inline-block; + height: 100px; + width: 20px; + } +</style> +<body> +<script src="/resources/ahem.js"></script> +<div id="padding1" style="display: none;"></div> +<div id="padding2" onclick="event.target.style.width = '100px'"></div> +<div id="text" style="width: 400px; display: inline-block"> +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor +incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis +nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore +eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt +in culpa qui officia deserunt mollit anim id est laborum. +</div> +</body>
diff --git a/third_party/blink/web_tests/inspector-protocol/performance-timeline/resources/performance-timeline-test.js b/third_party/blink/web_tests/inspector-protocol/performance-timeline/resources/performance-timeline-test.js new file mode 100644 index 0000000..0d915659 --- /dev/null +++ b/third_party/blink/web_tests/inspector-protocol/performance-timeline/resources/performance-timeline-test.js
@@ -0,0 +1,35 @@ +// Copyright 2021 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. + +(function() { + +class TestHelper { + constructor(dp) { + this._dp = dp; + } + + async describeNode(nodeId) { + const response = await this._dp.DOM.resolveNode({backendNodeId: nodeId}); + return response.result && response.result.object.description ? + `<${response.result.object.description}>` : '<invalid id>'; + } + + patchTimes(start, end, obj, fields) { + // Add some slack to defeat time clamping. + start -= 1; + end += 1; + for (const field of fields) { + const time = obj[field] * 1000; + if (time && (start <= time && time <= end)) { + obj[field] = `<${typeof time}>`; + } else if (time) { + obj[field] = `FAIL: actual: ${time}, expected: ${start} <= time <= ${end}` + } + } + } +}; + +return TestHelper; + +})()
diff --git a/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/nested-blob-url-workers.https-expected.txt b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/nested-blob-url-workers.https-expected.txt new file mode 100644 index 0000000..5710eac --- /dev/null +++ b/third_party/blink/web_tests/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/nested-blob-url-workers.https-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +FAIL Nested blob URL workers should be intercepted by a service worker. assert_equals: fetch() should be intercepted. expected "intercepted by service worker" but got "{\"error\": {\"code\": 404, \"message\": \"\"}}" +PASS Nested worker created from a blob URL worker should be intercepted by a service worker. +FAIL Nested blob URL worker created from a worker should be intercepted by a service worker. assert_equals: fetch() should be intercepted. expected "intercepted by service worker" but got "{\"error\": {\"code\": 404, \"message\": \"\"}}" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/wpt_internal/webcodecs/avc_encoder_config.any.js b/third_party/blink/web_tests/wpt_internal/webcodecs/avc_encoder_config.any.js new file mode 100644 index 0000000..ee67750 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/webcodecs/avc_encoder_config.any.js
@@ -0,0 +1,119 @@ +// META: global=window,dedicatedworker +// META: script=/wpt_internal/webcodecs/encoder_utils.js + +const defaultWidth = 640; +const defaultHeight = 360; + +let frameNumber = 0; + +async function configureAndEncode(encoder, config) { + encoder.configure(config); + + let frame = await createFrame(defaultWidth, defaultHeight, ++frameNumber); + encoder.encode(frame, { keyFrame : true }); + return encoder.flush() +} + +function cycleAvcOutputFormats(acc, desc) { + promise_test(async t => { + var output = undefined; + + let encoderInit = { + error: () => t.unreached_func("Unexpected error"), + output: (chunk, config) => { + assert_equals(output, undefined, "output undefined sanity"); + output = { + chunk: chunk, + config: config, + }; + }, + }; + + let encoder = new VideoEncoder(encoderInit); + + let encoderConfig = { + codec: "avc1.42001E", + acceleration: acc, + width: defaultWidth, + height: defaultHeight, + }; + + // Configure an encoder with no avcOptions (should default to avc format). + await configureAndEncode(encoder, encoderConfig); + + // avc chunks should output a config with an avcC description. + assert_not_equals(output, undefined, "output default"); + assert_not_equals(output.chunk, null, "chunk default"); + assert_not_equals(output.config, null, "config default"); + assert_not_equals(output.config.description, null, "desc default"); + + output = undefined; + + // Configure with annex-b. + encoderConfig.avc = { format: "annexb" }; + await configureAndEncode(encoder, encoderConfig); + + // annexb chunks should start with a start code. + assert_not_equals(output, undefined, "output annexb"); + assert_not_equals(output.chunk, null, "chunk annexb"); + assert_not_equals(output.chunk.data, null, "chunk.data annexb"); + + let startCode = new Int8Array(output.chunk.data.slice(0,4)); + + assert_equals(startCode[0], 0x00, "startCode [0]"); + assert_equals(startCode[1], 0x00, "startCode [1]"); + assert_equals(startCode[2], 0x00, "startCode [2]"); + assert_equals(startCode[3], 0x01, "startCode [3]"); + + // No config needs to be emitted for annexb, but we always emit one for now. + // There should not be an avcC 'description' with annexb. + // TODO: Update this if we only output configs when they change. + assert_not_equals(output.config, null, "config annexb"); + assert_equals(output.config.description, undefined, "desc annexb"); + + output = undefined; + + // Configure with avc. + encoderConfig.avc = { format: "avc" }; + await configureAndEncode(encoder, encoderConfig); + + // avc should output a config with an avcC description. + assert_not_equals(output, undefined, "output avc"); + assert_not_equals(output.chunk, null, "chunk avc"); + assert_not_equals(output.config, null, "config avc"); + assert_not_equals(output.config.description, null, "desc avc"); + + encoder.close(); + }, desc); +} + +cycleAvcOutputFormats("deny", + "Test AvcConfig supports 'avc' and 'annexb' (acceleration = 'deny')"); + +cycleAvcOutputFormats("allow", + "Test AvcConfig supports 'avc' and 'annexb' (acceleration = 'allow')"); + +/* Uncomment this for manual testing, before we have GPU tests for that */ +// cycleAvcOutputFormats("require", +// "Test AvcConfig supports 'avc' and 'annexb' (acceleration = 'require')"); + +promise_test(async t => { + let encoder = new VideoEncoder({ + error: () => t.unreached_func("Unexpected error"), + output: () => t.unreached_func("Unexpected output"), + }); + + const vp8Config = { + codec: 'vp8', + acceleration: "allow", + width: defaultWidth, + height: defaultHeight, + avc: { outputFormat: "avc" }, + }; + + assert_throws_js(TypeError, + () => { encoder.configure(vp8Config); }, + "Only H264 should support avcOptions"); + + encoder.close(); +}, "Make sure non-H264 configurations reject avcOptions");
diff --git a/third_party/blink/web_tests/wpt_internal/webcodecs/basic_video_encoding.any.js b/third_party/blink/web_tests/wpt_internal/webcodecs/basic_video_encoding.any.js index f6b610f..b27802f9 100644 --- a/third_party/blink/web_tests/wpt_internal/webcodecs/basic_video_encoding.any.js +++ b/third_party/blink/web_tests/wpt_internal/webcodecs/basic_video_encoding.any.js
@@ -1,41 +1,7 @@ // META: global=window,dedicatedworker +// META: script=/wpt_internal/webcodecs/encoder_utils.js -async function getImageAsBitmap(width, height) { - const src = "pattern.png"; - - var size = { - resizeWidth: width, - resizeHeight: height - }; - - return fetch(src) - .then(response => response.blob()) - .then(blob => createImageBitmap(blob, size)); -} - -async function generateBitmap(width, height, text) { - let img = await getImageAsBitmap(width, height); - let cnv = new OffscreenCanvas(width, height); - var ctx = cnv.getContext('2d'); - ctx.drawImage(img, 0, 0, width, height); - img.close(); - ctx.font = '30px fantasy'; - ctx.fillText(text, 5, 40); - return createImageBitmap(cnv); -} - -async function createFrame(width, height, ts) { - let imageBitmap = await generateBitmap(width, height, ts.toString()); - return new VideoFrame(imageBitmap, { timestamp: ts }); -} - -function delay(time_ms) { - return new Promise((resolve, reject) => { - setTimeout(resolve, time_ms); - }); -}; - -async function encode_decode_test(codec, acc) { +async function encode_decode_test(codec, acc, avc_options) { const w = 640; const h = 360; let next_ts = 0 @@ -73,7 +39,7 @@ } }; - const encoder_config = { + let encoder_config = { codec: codec, acceleration: acc, width: w, @@ -81,6 +47,10 @@ bitrate: 5000000, }; + if (avc_options !== null) { + encoder_config.avcOptions = avc_options; + } + let encoder = new VideoEncoder(encoder_init); encoder.configure(encoder_config); @@ -88,6 +58,10 @@ let frame = await createFrame(w, h, i); let keyframe = (i % 5 == 0); encoder.encode(frame, { keyFrame: keyframe }); + + // Wait to prevent queueing all frames before encoder.configure() completes. + // Queuing them all at once should still work, but would not be as + // repesentative of a real world scenario. await delay(1); } await encoder.flush(); @@ -158,17 +132,22 @@ promise_test(encode_test.bind(null, "vp09.02.10.10", "allow"), "encoding vp9 profile2"); -promise_test(encode_decode_test.bind(null, "vp09.02.10.10", "allow"), +promise_test(encode_decode_test.bind(null, "vp09.02.10.10", "allow", null), "encoding and decoding vp9 profile2"); promise_test(encode_test.bind(null, "vp8", "allow"), "encoding vp8"); -promise_test(encode_decode_test.bind(null, "vp8", "allow"), +promise_test(encode_decode_test.bind(null, "vp8", "allow", null), "encoding and decoding vp8"); -promise_test(encode_decode_test.bind(null, "avc1.42001E", "allow"), - "encoding and decoding avc1.42001E"); +promise_test( + encode_decode_test.bind(null, "avc1.42001E", "allow", { outputFormat: "annexb"}), + "encoding and decoding avc1.42001E (annexb)"); + +promise_test( + encode_decode_test.bind(null, "avc1.42001E", "allow", { outputFormat: "avc"}), + "encoding and decoding avc1.42001E (avc)"); /* Uncomment this for manual testing, before we have GPU tests for that */ // promise_test(encode_test.bind(null, "avc1.42001E", "require"),
diff --git a/third_party/blink/web_tests/wpt_internal/webcodecs/encoder_utils.js b/third_party/blink/web_tests/wpt_internal/webcodecs/encoder_utils.js new file mode 100644 index 0000000..a8d1554 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/webcodecs/encoder_utils.js
@@ -0,0 +1,34 @@ +async function getImageAsBitmap(width, height) { + const src = "pattern.png"; + + var size = { + resizeWidth: width, + resizeHeight: height + }; + + return fetch(src) + .then(response => response.blob()) + .then(blob => createImageBitmap(blob, size)); +} + +async function generateBitmap(width, height, text) { + let img = await getImageAsBitmap(width, height); + let cnv = new OffscreenCanvas(width, height); + var ctx = cnv.getContext('2d'); + ctx.drawImage(img, 0, 0, width, height); + img.close(); + ctx.font = '30px fantasy'; + ctx.fillText(text, 5, 40); + return createImageBitmap(cnv); +} + +async function createFrame(width, height, ts) { + let imageBitmap = await generateBitmap(width, height, ts.toString()); + return new VideoFrame(imageBitmap, { timestamp: ts }); +} + +function delay(time_ms) { + return new Promise((resolve, reject) => { + setTimeout(resolve, time_ms); + }); +};
diff --git a/third_party/blink/web_tests/wpt_internal/webcodecs/reconfiguring_encoder.any.js b/third_party/blink/web_tests/wpt_internal/webcodecs/reconfiguring_encoder.any.js index 71df078..43f979fc 100644 --- a/third_party/blink/web_tests/wpt_internal/webcodecs/reconfiguring_encoder.any.js +++ b/third_party/blink/web_tests/wpt_internal/webcodecs/reconfiguring_encoder.any.js
@@ -1,42 +1,5 @@ // META: global=window,dedicatedworker - -async function getImageAsBitmap(width, height) { - const src = "pattern.png"; - - var size = { - resizeWidth: width, - resizeHeight: height - }; - - return fetch(src) - .then(response => response.blob()) - .then(blob => createImageBitmap(blob, size)); -} - -async function generateBitmap(width, height, text) { - let img = await getImageAsBitmap(width, height); - let cnv = new OffscreenCanvas(width, height); - var ctx = cnv.getContext('2d'); - ctx.drawImage(img, 0, 0, width, height); - img.close(); - ctx.font = '30px fantasy'; - ctx.fillText(text, 5, 40); - return createImageBitmap(cnv); -} - - -async function createFrame(width, height, ts) { - let imageBitmap = await generateBitmap(width, height, ts.toString()); - let frame = new VideoFrame(imageBitmap, { timestamp: ts }); - imageBitmap.close(); - return frame; -} - -function delay(time_ms) { - return new Promise((resolve, reject) => { - setTimeout(resolve, time_ms); - }); -}; +// META: script=/wpt_internal/webcodecs/encoder_utils.js async function change_encoding_params_test(codec, acc) { let original_w = 800;
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 74809781..eb377d8 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-10-4-97-gc6345ca36 -Revision: c6345ca36de9d396b4dbef2aeab73a5a838c46b6 +Version: VER-2-10-4-98-gf88c00e45 +Revision: f88c00e45a2f503f8a62bb9cc963ece5c46fc7d5 CPEPrefix: cpe:/a:freetype:freetype:2.10.4 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index f53dd8a1..ea86ce6 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -263,7 +263,8 @@ "META": {"sizes": {"includes": [20]}}, "includes": [2200], }, - "chrome/browser/resources/webapks/webapks_ui_resources.grd": { + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/webapks/resources.grd": { + "META": {"sizes": {"includes": [10]}}, "includes": [2220], }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/webui_js_error/webui_js_error_resources.grd": {
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index fb5fa44..5c1dd3ed 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -27183,11 +27183,16 @@ <suffix name="HomepageTile" label="For HomepageTile feature."/> <suffix name="IdentityDisc" label="For IdentityDisc feature."/> <suffix name="IncognitoWindow" label="For IncognitoWindow feature."/> + <suffix name="IPH_NewTabTip" label="In product help new tab tip."/> <suffix name="LongPressToolbarTip" label="For LongPressToolbar feature."/> <suffix name="MediaDownload" label="For MediaDownload feature."/> <suffix name="NewIncognitoTabTip" label="For NewIncognitoTabTip feature."/> <suffix name="NewTab" label="For NewTab feature."/> - <suffix name="NewTabPageButton" label="For NewTabPageButton feature."/> + <suffix name="NewTabPageButton" + label="For NewTabPageButton feature. This feature was used for feature + in M79- then deprecated; in M88+ this histogram was reused for a + different experiment. Be sure to apply filter on milestone for + this histogram to get the meaningful data."/> <suffix name="NewTabTip" label="For NewTabTip feature."/> <suffix name="PasswordsAccountStorage" label="For PasswordsAccountStorage feature."/> @@ -27202,6 +27207,7 @@ <suffix name="TabGroupsTapToSeeAnotherTab" label="For tab strip."/> <suffix name="TabGroupsYourTabsTogether" label="For tab switcher with tab groups."/> + <suffix name="TabSwitcherButton" label="For tab switcher button."/> <suffix name="TranslateMenuButton" label="For translate menu button."/> <suffix name="WebUITabStrip" label="For the WebUI tab strip."/> <affected-action name="InProductHelp.NotifyEvent.IPH"/>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 514880b..1d1a0a6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -10022,6 +10022,21 @@ <int value="4" label="App sync is enabled"> Profile data was recorded in full since App Sync is enabled. </int> + <int value="5" label="Sync service is unavailable"> + Profile data was redacted since sync service is unavailable. + </int> + <int value="6" label="Chrome sync feature is disabled"> + Profile data was redacted since Chrome sync feature is disabled. + </int> + <int value="7" label="Chrome App Sync is disabled"> + Profile data was redacted since Chrome App Sync is disabled. + </int> + <int value="8" label="Chrome OS sync feature is disabled"> + Profile data was redacted since Chrome OS sync feature is disabled. + </int> + <int value="9" label="Chrome OS App Sync is disabled"> + Profile data was redacted since Chrome OS App Sync is disabled. + </int> </enum> <enum name="ChromeOSRecoveryReason"> @@ -32824,6 +32839,12 @@ <int value="2" label="Failed / credentials rejected"/> </enum> +<enum name="FulfillTrustTokenIssuanceAnswerStatus"> + <int value="0" label="Ok"/> + <int value="1" label="NotFound"/> + <int value="2" label="UnknownError"/> +</enum> + <enum name="FuseZipError"> <int value="0" label="Success">Hardcoded in fuse-zip</int> <int value="11" label="Multipart ZIP"> @@ -36818,6 +36839,10 @@ <int value="0" label="kClick"/> </enum> +<enum name="HoldingSpaceFilesAppChipAction"> + <int value="0" label="kClick"/> +</enum> + <enum name="HoldingSpaceItemAction"> <int value="0" label="kCopy"/> <int value="1" label="kDrag"/> @@ -42117,6 +42142,7 @@ <int value="-2105133782" label="GesturePropertiesDBusService:enabled"/> <int value="-2104950596" label="HandwritingGesture:enabled"/> <int value="-2104654357" label="GamesHub:enabled"/> + <int value="-2102286055" label="WebViewVulkanIntermediateBuffer:disabled"/> <int value="-2101682955" label="EnableNotificationIndicator:enabled"/> <int value="-2101337189" label="AutofillOffNoServerData:disabled"/> <int value="-2099486626" label="DownloadLater:enabled"/> @@ -43554,6 +43580,7 @@ <int value="-810684526" label="AutofillToolkitViewsCreditCardDialogsMac:disabled"/> <int value="-810110236" label="EditPasswordsInSettings:enabled"/> + <int value="-809456392" label="WebViewVulkanIntermediateBuffer:enabled"/> <int value="-808486493" label="NewWallpaperPicker:disabled"/> <int value="-806549905" label="TabbedAppOverflowMenuThreeButtonActionbar:disabled"/> @@ -44933,6 +44960,7 @@ <int value="538468149" label="OfflinePagesCT:enabled"/> <int value="538600423" label="OmniboxDocumentProvider:enabled"/> <int value="538685995" label="InstallableInkDrop:enabled"/> + <int value="542930298" label="WebAppEnableLinkCapturing:disabled"/> <int value="542960889" label="HeavyAdIntervention:enabled"/> <int value="544443920" label="QuickAnswers:disabled"/> <int value="546043947" label="ImplicitRootScroller:enabled"/> @@ -45494,6 +45522,7 @@ <int value="1084365949" label="ReleaseNotesNotification:disabled"/> <int value="1084972292" label="WebXRAnchors:enabled"/> <int value="1085130793" label="LongPressBackForHistory:disabled"/> + <int value="1086592430" label="WebAppEnableLinkCapturing:enabled"/> <int value="1087235172" label="file-manager-enable-new-audio-player"/> <int value="1088915385" label="new-password-form-parsing:enabled"/> <int value="1089913432" label="VirtualDesksGestures:disabled"/> @@ -54966,6 +54995,9 @@ </enum> <enum name="OmniboxUserTextCleared"> + <obsolete> + Removed 2021-01. + </obsolete> <int value="0" label="cleared by editing"/> <int value="1" label="cleared with escape"/> </enum> @@ -64636,6 +64668,14 @@ <int value="1" label="Supported"/> </enum> +<enum name="RequestStopReason"> + <int value="0" label="Fulfilled"/> + <int value="1" label="Timeout"/> + <int value="2" label="Empty Result"/> + <int value="3" label="Multiple Copy Completion"/> + <int value="4" label="Request Canceled"/> +</enum> + <enum name="RequestStorageResult"> <int value="0" label="Approved due to existing storage access"/> <int value="1" label="Approved with new grant"/> @@ -68431,18 +68471,6 @@ <int value="3" label="Not displayed"/> </enum> -<enum name="SigninInterceptSessionStartupResult"> - <int value="0" label="Nothing to do (Reconcilor)"/> - <int value="1" label="Nothing to do (Multilogin)"/> - <int value="2" label="Success (reconcilor)"/> - <int value="3" label="Success (multilogin)"/> - <int value="4" label="Success (other)"/> - <int value="5" label="Timeout (multilogin)"/> - <int value="6" label="Timeout (reconcilor)"/> - <int value="7" label="Transient error (multilogin)"/> - <int value="8" label="Persistent error (multilogin)"/> -</enum> - <enum name="SigninInvalidGaiaCredentialsReason"> <int value="0" label="Unknown"/> <int value="1" label="Credentials rejected by server"/>
diff --git a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml index 048f855..7e0f4d0 100644 --- a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
@@ -89,7 +89,7 @@ </histogram> <histogram name="Accessibility.AndroidServiceInfo" - enum="AccessibilityAndroidServiceInfoEnum" expires_after="M89"> + enum="AccessibilityAndroidServiceInfoEnum" expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> <summary> @@ -136,7 +136,7 @@ </histogram> <histogram name="Accessibility.ChromeVox.PerformGestureType" - enum="ChromeVoxGestureType" expires_after="M90"> + enum="ChromeVoxGestureType" expires_after="M93"> <owner>dtseng@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> <summary> @@ -182,7 +182,7 @@ </histogram> <histogram name="Accessibility.CrosCaretHighlight" enum="BooleanEnabled" - expires_after="M90"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> <summary> @@ -192,7 +192,7 @@ </histogram> <histogram name="Accessibility.CrosChromeVoxNext" enum="BooleanEnabled" - expires_after="M90"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> <summary> @@ -236,7 +236,7 @@ </histogram> <histogram name="Accessibility.CrosDictation.ToggleDictationMethod" - enum="CrosDictationToggleDictationMethod" expires_after="M90"> + enum="CrosDictationToggleDictationMethod" expires_after="M93"> <owner>anastasi@google.com</owner> <owner>dtseng@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> @@ -255,7 +255,7 @@ </histogram> <histogram name="Accessibility.CrosFocusHighlight" enum="BooleanEnabled" - expires_after="M90"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> <summary> @@ -276,7 +276,7 @@ </histogram> <histogram name="Accessibility.CrosLargeCursor" enum="BooleanEnabled" - expires_after="M90"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>kenjibaheux@google.com</owner> <owner>chrome-a11y-core@google.com</owner> @@ -287,7 +287,7 @@ </histogram> <histogram name="Accessibility.CrosLargeCursorSize" units="dip" - expires_after="M90"> + expires_after="M93"> <owner>yawano@chromium.org</owner> <owner>lpalmaro@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> @@ -403,7 +403,7 @@ </histogram> <histogram name="Accessibility.CrosStickyKeys" enum="BooleanEnabled" - expires_after="M90"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>kenjibaheux@google.com</owner> <owner>tengs@chromium.org</owner> @@ -448,7 +448,7 @@ </histogram> <histogram name="Accessibility.ImageLabels" enum="BooleanEnabled" - expires_after="M89"> + expires_after="M93"> <owner>katie@chromium.org</owner> <owner>dmazzoni@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> @@ -740,7 +740,7 @@ </histogram> <histogram name="Accessibility.ManuallyEnabled" enum="BooleanEnabled" - expires_after="M89"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>kenjibaheux@google.com</owner> <owner>chrome-a11y-core@google.com</owner> @@ -896,7 +896,7 @@ </histogram> <histogram name="Accessibility.WinAPIs" enum="AccessibilityWinAPIEnum" - expires_after="M89"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>nektar@chromium.org</owner> <owner>chrome-a11y-core@google.com</owner> @@ -904,7 +904,7 @@ </histogram> <histogram name="Accessibility.WinAPIs.GetPropertyValue" - enum="AccessibilityWinAPIGetPropertyValueEnum" expires_after="M89"> + enum="AccessibilityWinAPIGetPropertyValueEnum" expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>nektar@chromium.org</owner> <owner>kbabbitt@microsoft.com</owner> @@ -915,7 +915,7 @@ </histogram> <histogram name="Accessibility.WinAudioDescription" enum="BooleanEnabled" - expires_after="M89"> + expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>kenjibaheux@google.com</owner> <owner>chrome-a11y-core@google.com</owner> @@ -926,7 +926,7 @@ </histogram> <histogram name="Accessibility.WinHighContrastTheme" - enum="AccessibilityHighContrastColorScheme" expires_after="M89"> + enum="AccessibilityHighContrastColorScheme" expires_after="M93"> <owner>dmazzoni@chromium.org</owner> <owner>almaher@microsoft.com</owner> <owner>weblayoutdev@microsoft.com</owner> @@ -1037,6 +1037,108 @@ </summary> </histogram> +<histogram name="TextToSpeech.Event" enum="TextToSpeechEvent" + expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>dtseng@chromium.org</owner> + <owner>chrome-a11y-core@google.com</owner> + <summary> + Events fired by the text-to-speech engine when speaking an utterance. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.FromExtensionAPI" + enum="TextToSpeechFromExtensionAPI" expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + Indicates if an utterance spoken via synthesized text-to-speech was + triggered by the Chrome TTS extension API or the web speech API. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.HasGender" enum="TextToSpeechHasGender" + expires_after="M73"> + <obsolete> + Obsolete as of M73 because we decided to remove gender from the API. + </obsolete> + <owner>dmazzoni@chromium.org</owner> + <summary> + True if an utterance spoken via synthesized text-to-speech requested a + specific gender. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.HasLang" enum="TextToSpeechHasLang" + expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + True if an utterance spoken via synthesized text-to-speech specified a + language code. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.HasPitch" enum="TextToSpeechHasPitch" + expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + True if an utterance spoken via synthesized text-to-speech requested a + specific pitch other than the default. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.HasRate" enum="TextToSpeechHasRate" + expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + True if an utterance spoken via synthesized text-to-speech requested a + specific speech rate other than the default. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.HasVoiceName" + enum="TextToSpeechHasVoiceName" expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + True if an utterance spoken via synthesized text-to-speech requested a + specific voice by name. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.HasVolume" enum="TextToSpeechHasVolume" + expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + True if an utterance spoken via synthesized text-to-speech requested a + specific volume other than the default. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.Native" enum="TextToSpeechNative" + expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + True if an utterance is spoken with native speech provided by the operating + system, otherwise it's spoken via a Chrome extension that implements + text-to-speech support. + </summary> +</histogram> + +<histogram name="TextToSpeech.Utterance.TextLength" units="bytes" + expires_after="M93"> + <owner>dmazzoni@chromium.org</owner> + <owner>katie@chromium.org</owner> + <summary> + The length of an utterance to be spoken via synthesized text-to-speech. + </summary> +</histogram> + </histograms> </histogram-configuration>
diff --git a/tools/metrics/histograms/histograms_xml/ash/histograms.xml b/tools/metrics/histograms/histograms_xml/ash/histograms.xml index 30a5b11..332b005 100644 --- a/tools/metrics/histograms/histograms_xml/ash/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
@@ -445,6 +445,36 @@ </summary> </histogram> +<histogram name="Ash.ClipboardHistory.ImageModelRequest.Lifetime" units="ms" + expires_after="2021-12-11"> + <owner>newcomer@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The lifetime of the ClipboardImageModelRequest object. Logged in the dtor of + ClipboardImageModelRequest. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ImageModelRequest.Runtime" units="ms" + expires_after="2021-12-11"> + <owner>newcomer@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The runtime of a request in a ClipboardImageModelRequest. Logged from when + the ClipboardImageModelRequest is Start()-ed to when it is Stop()-ed. + </summary> +</histogram> + +<histogram name="Ash.ClipboardHistory.ImageModelRequest.StopReason" + enum="RequestStopReason" expires_after="2021-12-11"> + <owner>newcomer@chromium.org</owner> + <owner>multipaste@google.com</owner> + <summary> + The reason a ClipboardImageModelRequest is stopped. Logged when a request is + Stop()-ed. + </summary> +</histogram> + <histogram base="true" name="Ash.ContextualNudgeDismissContext" enum="ContextualNudgeDismissContext" expires_after="2021-12-01"> <!-- Name completed by histogram_suffixes name="ContextualNudgesNames" -->
diff --git a/tools/metrics/histograms/histograms_xml/cookie/histograms.xml b/tools/metrics/histograms/histograms_xml/cookie/histograms.xml index 908be7b..80c2e71 100644 --- a/tools/metrics/histograms/histograms_xml/cookie/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/cookie/histograms.xml
@@ -408,6 +408,18 @@ </summary> </histogram> +<histogram name="Cookie.SamePartyReadIncluded.PartyContextSize" + units="registrable domains" expires_after="2022-01-05"> + <owner>cfredric@chromium.org</owner> + <owner>chlily@chromium.org</owner> + <summary> + This histogram records, for each cookie with the SameParty attribute that is + read, how large the party-context was. I.e., how many distinct registrable + domains needed to be treated as a single party in order for the cookie to + "work". + </summary> +</histogram> + <histogram name="Cookie.SamePartySetIncluded.IsHTTP" enum="BooleanHTTPVsJS" expires_after="2022-01-05"> <owner>cfredric@chromium.org</owner> @@ -418,6 +430,18 @@ </summary> </histogram> +<histogram name="Cookie.SamePartySetIncluded.PartyContextSize" + units="registrable domains" expires_after="2022-01-05"> + <owner>cfredric@chromium.org</owner> + <owner>chlily@chromium.org</owner> + <summary> + This histogram records, for each cookie that is set with the SameParty + attribute, how large the party-context was. I.e., how many distinct + registrable domains needed to be treated as a single party in order for the + cookie to "work". + </summary> +</histogram> + <histogram name="Cookie.SameSiteAttributeValue" enum="CookieSameSiteString" expires_after="2021-11-01"> <owner>chlily@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml index b5b94f60..ce014da 100644 --- a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
@@ -252,10 +252,15 @@ </histogram> <histogram name="Extensions.BookmarkAppLaunchContainer" - enum="AppLaunchContainer" expires_after="2021-01-31"> + enum="AppLaunchContainer" expires_after="2021-07-31"> <owner>benwells@chromium.org</owner> <owner>dominickn@chromium.org</owner> - <summary>Records the container used for a bookmark app launch.</summary> + <owner>phillis@chromium.org</owner> + <summary> + Records the container used for a bookmark app launch, when the app is + launched (eg. via UI surfaces or intents). Not recorded when the web app is + navigated to via URL. + </summary> </histogram> <histogram name="Extensions.BookmarkAppLaunchSource" enum="AppLaunchSource" @@ -2071,17 +2076,17 @@ </histogram> <histogram name="Extensions.HostedAppLaunchContainer" enum="AppLaunchContainer" - expires_after="2021-04-04"> + expires_after="2021-07-31"> <owner>benwells@chromium.org</owner> <owner>dominickn@chromium.org</owner> <summary> - Records the container used for a hosted app launch. The definition of - 'launch' for the purposes of this histogram is different to that used for - the launch type histograms. This definition is less inclusive, for example - it does not include navigations to the hosted app due to normal browsing, - which the other definition does include. This definition could be thought of - more as explicit launches via a launch surface such as the app launcher, - chrome://apps, or a shortcut. + Records the container used for a hosted app launch, when the app is + launched. The definition of 'launch' for the purposes of this histogram is + different to that used for the launch type histograms. This definition is + less inclusive, for example it does not include navigations to the hosted + app due to normal browsing, which the other definition does include. This + definition could be thought of more as explicit launches via a launch + surface such as the app launcher, chrome://apps, or a shortcut. </summary> </histogram>
diff --git a/tools/metrics/histograms/histograms_xml/file/histograms.xml b/tools/metrics/histograms/histograms_xml/file/histograms.xml index 98d6600..8cea7cf 100644 --- a/tools/metrics/histograms/histograms_xml/file/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/file/histograms.xml
@@ -202,6 +202,19 @@ </summary> </histogram> +<histogram + name="FileBrowser.HoldingSpace.TimeFromFirstWelcomeBannerShowToFirstPin" + units="ms" expires_after="2022-01-05"> + <owner>dmblack@google.com</owner> + <owner>tbarzic@chromium.org</owner> + <summary> + Chrome OS Files App: Records the time from when the holding space welcome + banner was first shown to when the user first pinned an item to holding + space from the Files app. If the holding space welcome banner was not shown + prior to the first pin, zero is recorded. + </summary> +</histogram> + <histogram name="FileBrowser.ImportController.DeviceYanked" enum="Boolean" expires_after="M92"> <owner>slangley@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml index fd98cd4..2bac8f5 100644 --- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -7875,11 +7875,10 @@ label="In product help new incognito tab tip."/> <suffix name="IPH_NewTab" label="In product help new tab."/> <suffix name="IPH_NewTabPageButton" - label="In product help new tab page button."> - <obsolete> - This feature was deprecated in M79 - </obsolete> - </suffix> + label="In product help for new tab page button. This feature was used + for feature in M79- then deprecated; in M88+ this histogram was + reused for a different experiment. Be sure to apply filter on + milestone for this histogram to get the meaningful data."/> <suffix name="IPH_NewTabTip" label="In product help new tab tip."/> <suffix name="IPH_PasswordsAccountStorage" label="In product help for passwords account storage."/> @@ -7899,6 +7898,8 @@ <suffix name="IPH_TabGroupsYourTabsTogether" label="In product help for tab switcher cards with multiple tab thumbnails."/> + <suffix name="IPH_TabSwitcherButton" + label="In product help for tab swticher button."/> <suffix name="IPH_TranslateMenuButton" label="In product help translate menu button."/> <suffix name="IPH_WebUITabStrip" @@ -12114,6 +12115,8 @@ Removed in M89. </obsolete> </suffix> + <suffix name="ShoppingPagePredictor" + label="Determines if a page is shopping related or not"/> <affected-histogram name="OptimizationGuide.ApplyDecision"/> <affected-histogram name="OptimizationGuide.ApplyDecisionAsync"/> <affected-histogram name="OptimizationGuide.OptimizationFilterStatus"/>
diff --git a/tools/metrics/histograms/histograms_xml/holding_space/histograms.xml b/tools/metrics/histograms/histograms_xml/holding_space/histograms.xml index 9b0e353..8539303 100644 --- a/tools/metrics/histograms/histograms_xml/holding_space/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/holding_space/histograms.xml
@@ -31,6 +31,16 @@ </summary> </histogram> +<histogram name="HoldingSpace.FilesAppChip.Action.All" + enum="HoldingSpaceFilesAppChipAction" expires_after="2021-09-24"> + <owner>dmblack@google.com</owner> + <owner>gzadina@google.com</owner> + <summary> + Records an action taken on the Files app chip in holding space UI at the + moment the action is performed. + </summary> +</histogram> + <histogram base="true" name="HoldingSpace.Item.Action" enum="HoldingSpaceItemType" expires_after="2021-09-24"> <!-- Name completed by histogram_suffixes name="HoldingSpaceActionType" -->
diff --git a/tools/metrics/histograms/histograms_xml/net/histograms.xml b/tools/metrics/histograms/histograms_xml/net/histograms.xml index 15ee999..ab499e7 100644 --- a/tools/metrics/histograms/histograms_xml/net/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/net/histograms.xml
@@ -4854,6 +4854,19 @@ </summary> </histogram> +<histogram base="true" name="Net.TrustTokens.IssuanceHelperLocalFulfillResult" + enum="FulfillTrustTokenIssuanceAnswerStatus" expires_after="2021-07-30"> + <owner>davidvc@chromium.org</owner> + <owner>privacy-sandbox-dev@chromium.org</owner> + <summary> + For locally diverted platform-provided trust token issuance requests, the + results of the LocalOperationDelegate issuance delegation call. This is a + liveness metric that allows verifying that platform-provided trust token + issuance is working during the feature's initial rollout (and, if it isn't, + that helps debug the failures). + </summary> +</histogram> + <histogram base="true" name="Net.TrustTokens.NetErrorForFetchFailure" enum="NetErrorCodes" expires_after="2021-05-30"> <!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
diff --git a/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml b/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml index cb78c35..a278c9e4 100644 --- a/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml
@@ -996,6 +996,9 @@ <histogram name="Omnibox.UserTextCleared" enum="OmniboxUserTextCleared" expires_after="M85"> + <obsolete> + Removed 2021-01. + </obsolete> <owner>kenjibaheux@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>jdonnelly@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml index a554251..f20d5b5 100644 --- a/tools/metrics/histograms/histograms_xml/others/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -15777,103 +15777,6 @@ <token key="TextFragmentSource" variants="TextFragmentSource"/> </histogram> -<histogram name="TextToSpeech.Event" enum="TextToSpeechEvent" - expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <summary> - Events fired by the text-to-speech engine when speaking an utterance. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.FromExtensionAPI" - enum="TextToSpeechFromExtensionAPI" expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - Indicates if an utterance spoken via synthesized text-to-speech was - triggered by the Chrome TTS extension API or the web speech API. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.HasGender" enum="TextToSpeechHasGender" - expires_after="M73"> - <owner>dmazzoni@chromium.org</owner> - <summary> - True if an utterance spoken via synthesized text-to-speech requested a - specific gender. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.HasLang" enum="TextToSpeechHasLang" - expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - True if an utterance spoken via synthesized text-to-speech specified a - language code. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.HasPitch" enum="TextToSpeechHasPitch" - expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - True if an utterance spoken via synthesized text-to-speech requested a - specific pitch other than the default. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.HasRate" enum="TextToSpeechHasRate" - expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - True if an utterance spoken via synthesized text-to-speech requested a - specific speech rate other than the default. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.HasVoiceName" - enum="TextToSpeechHasVoiceName" expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - True if an utterance spoken via synthesized text-to-speech requested a - specific voice by name. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.HasVolume" enum="TextToSpeechHasVolume" - expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - True if an utterance spoken via synthesized text-to-speech requested a - specific volume other than the default. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.Native" enum="TextToSpeechNative" - expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - True if an utterance is spoken with native speech provided by the operating - system, otherwise it's spoken via a Chrome extension that implements - text-to-speech support. - </summary> -</histogram> - -<histogram name="TextToSpeech.Utterance.TextLength" units="bytes" - expires_after="M89"> - <owner>dmazzoni@chromium.org</owner> - <owner>katie@chromium.org</owner> - <summary> - The length of an utterance to be spoken via synthesized text-to-speech. - </summary> -</histogram> - <histogram name="ThirdPartyModules.Certificates.Microsoft" units="certificates" expires_after="M85"> <owner>chrisha@chromium.org</owner> @@ -17696,8 +17599,9 @@ </histogram> <histogram name="Webapp.Update.ManifestUpdateResult" - enum="WebAppManifestUpdateResult" expires_after="M89"> + enum="WebAppManifestUpdateResult" expires_after="M92"> <owner>alancutter@chromium.org</owner> + <owner>desktop-pwas-team@chromium.org</owner> <owner>loyso@chromium.org</owner> <owner>raymes@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/signin/histograms.xml b/tools/metrics/histograms/histograms_xml/signin/histograms.xml index 10bda5a..8965ded 100644 --- a/tools/metrics/histograms/histograms_xml/signin/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/signin/histograms.xml
@@ -439,10 +439,6 @@ <histogram name="Signin.Intercept.SessionStartupDuration" units="ms" expires_after="2021-08-12"> - <obsolete> - Replaced in M89 by Signin.Intercept.SessionStartupDuration.Multilogin and - Signin.Intercept.SessionStartupDuration.Reconcilor. - </obsolete> <owner>alexilin@chromium.org</owner> <owner>droger@chromium.org</owner> <summary> @@ -451,20 +447,6 @@ </summary> </histogram> -<histogram name="Signin.Intercept.SessionStartupDuration.{Method}" units="ms" - expires_after="2021-08-12"> - <owner>alexilin@chromium.org</owner> - <owner>droger@chromium.org</owner> - <summary> - Records the duration of session startup time after signin interception using - {Method}. This includes waiting for the account to be available on the web. - </summary> - <token key="Method"> - <variant name="Multilogin"/> - <variant name="Reconcilor"/> - </token> -</histogram> - <histogram name="Signin.Intercept.SessionStartupReconcileError" enum="BooleanPresent" expires_after="2021-08-12"> <owner>alexilin@chromium.org</owner> @@ -476,16 +458,6 @@ </summary> </histogram> -<histogram name="Signin.Intercept.SessionStartupResult" - enum="SigninInterceptSessionStartupResult" expires_after="2021-08-12"> - <owner>alexilin@chromium.org</owner> - <owner>droger@chromium.org</owner> - <summary> - Records the result of session startup after signin interception, which adds - the account on the web. - </summary> -</histogram> - <histogram base="true" name="Signin.InterceptResult" enum="SigninInterceptResult" expires_after="2021-08-12"> <!-- Name completed by histogram_suffixes name="SigninInterceptType" -->
diff --git a/tools/metrics/histograms/histograms_xml/software/histograms.xml b/tools/metrics/histograms/histograms_xml/software/histograms.xml index 24e2f4b8..62055f8 100644 --- a/tools/metrics/histograms/histograms_xml/software/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/software/histograms.xml
@@ -167,7 +167,7 @@ </histogram> <histogram name="SoftwareReporter.ConfigurationErrors" - enum="SoftwareReporterConfigurationError" expires_after="2021-01-30"> + enum="SoftwareReporterConfigurationError" expires_after="2021-07-30"> <owner>bdea@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 3955257..1d3761b 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@ { "trace_processor_shell": { "win": { - "hash": "55e3995717f28e7c5096709cf8bcc916674bd052", - "remote_path": "perfetto_binaries/trace_processor_shell/win/4dde23fea5996c50208504f79c85264f27e21aea/trace_processor_shell.exe" + "hash": "15c06e9115e3c136010eb972e8d07c530258357a", + "remote_path": "perfetto_binaries/trace_processor_shell/win/7f2db542af0fae7d4f406a316ab088554bb33fde/trace_processor_shell.exe" }, "mac": { - "hash": "e1c9721f43a06fd1c7f30ff819236d0124a2eed3", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/4dde23fea5996c50208504f79c85264f27e21aea/trace_processor_shell" + "hash": "b57312a7ab23b0430eb253fd4dff7f09636dc2f5", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/f902efb9511c1db328d62326f654467b689067cd/trace_processor_shell" }, "linux": { - "hash": "4daecf1a4d9ee3fb10a7bb4b26fb330cf1b3f928", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/4dde23fea5996c50208504f79c85264f27e21aea/trace_processor_shell" + "hash": "f6b014ca6a115d5b60c582bf91ebc532477c1558", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/7f2db542af0fae7d4f406a316ab088554bb33fde/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/variations/fieldtrial_to_struct.py b/tools/variations/fieldtrial_to_struct.py index a5fb64d..9ecf3897 100755 --- a/tools/variations/fieldtrial_to_struct.py +++ b/tools/variations/fieldtrial_to_struct.py
@@ -35,6 +35,7 @@ 'android_weblayer', 'android_webview', 'chromeos', + 'chromeos_lacros', 'fuchsia', 'ios', 'linux',
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn index 94a749246..22d0ec9 100644 --- a/ui/aura/BUILD.gn +++ b/ui/aura/BUILD.gn
@@ -37,6 +37,7 @@ "scoped_enable_unadjusted_mouse_events.h", "scoped_keyboard_hook.h", "scoped_simple_keyboard_hook.h", + "scoped_window_capture_request.h", "scoped_window_event_targeting_blocker.h", "scoped_window_targeter.h", "window.h", @@ -79,6 +80,7 @@ "null_window_targeter.cc", "scoped_keyboard_hook.cc", "scoped_simple_keyboard_hook.cc", + "scoped_window_capture_request.cc", "scoped_window_event_targeting_blocker.cc", "scoped_window_targeter.cc", "window.cc",
diff --git a/ui/aura/client/aura_constants.cc b/ui/aura/client/aura_constants.cc index 3fa9141b..75108ad 100644 --- a/ui/aura/client/aura_constants.cc +++ b/ui/aura/client/aura_constants.cc
@@ -77,6 +77,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(int, kTopViewInset, 0) DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia, kWindowIconKey, nullptr) DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowCornerRadiusKey, -1) +DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowWorkspaceKey, kUnassignedWorkspace) DEFINE_UI_CLASS_PROPERTY_KEY(ui::ZOrderLevel, kZOrderingKey, ui::ZOrderLevel::kNormal)
diff --git a/ui/aura/client/aura_constants.h b/ui/aura/client/aura_constants.h index 1380691..eb22477 100644 --- a/ui/aura/client/aura_constants.h +++ b/ui/aura/client/aura_constants.h
@@ -30,6 +30,9 @@ constexpr int kResizeBehaviorCanMaximize = 1 << 1; constexpr int kResizeBehaviorCanMinimize = 1 << 2; +// A value used to represent an unassigned workspace for kWindowWorkspaceKey. +constexpr int kUnassignedWorkspace = -1; + // Alphabetical sort. // A property key to store whether accessibility focus falls back to widget or @@ -158,6 +161,10 @@ // Default is -1, meaning "unspecified". 0 Ensures corners are square. AURA_EXPORT extern const WindowProperty<int>* const kWindowCornerRadiusKey; +// A property key to indicate a desk index of a workspace this window belongs +// to. The default value is kUnassignedWorkspace. +AURA_EXPORT extern const WindowProperty<int>* const kWindowWorkspaceKey; + // A property key to store the z-ordering. AURA_EXPORT extern const WindowProperty<ui::ZOrderLevel>* const kZOrderingKey;
diff --git a/ui/aura/scoped_window_capture_request.cc b/ui/aura/scoped_window_capture_request.cc new file mode 100644 index 0000000..0d7c3f2 --- /dev/null +++ b/ui/aura/scoped_window_capture_request.cc
@@ -0,0 +1,42 @@ +// Copyright 2020 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 "ui/aura/scoped_window_capture_request.h" + +#include "ui/aura/window.h" + +namespace aura { + +ScopedWindowCaptureRequest::ScopedWindowCaptureRequest( + ScopedWindowCaptureRequest&& other) + : window_(other.window_) { + other.window_ = nullptr; +} + +ScopedWindowCaptureRequest& ScopedWindowCaptureRequest::operator=( + ScopedWindowCaptureRequest&& rhs) { + if (window_) + window_->OnScopedWindowCaptureRequestRemoved(); + window_ = rhs.window_; + rhs.window_ = nullptr; + return *this; +} + +ScopedWindowCaptureRequest::~ScopedWindowCaptureRequest() { + if (window_) + window_->OnScopedWindowCaptureRequestRemoved(); +} + +viz::SubtreeCaptureId ScopedWindowCaptureRequest::GetCaptureId() const { + return window_ ? window_->subtree_capture_id() : viz::SubtreeCaptureId(); +} + +ScopedWindowCaptureRequest::ScopedWindowCaptureRequest(Window* window) + : window_(window) { + DCHECK(window_); + DCHECK(!window_->IsRootWindow()); + window_->OnScopedWindowCaptureRequestAdded(); +} + +} // namespace aura
diff --git a/ui/aura/scoped_window_capture_request.h b/ui/aura/scoped_window_capture_request.h new file mode 100644 index 0000000..ee7e4f95 --- /dev/null +++ b/ui/aura/scoped_window_capture_request.h
@@ -0,0 +1,50 @@ +// Copyright 2020 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 UI_AURA_SCOPED_WINDOW_CAPTURE_REQUEST_H_ +#define UI_AURA_SCOPED_WINDOW_CAPTURE_REQUEST_H_ + +#include "components/viz/common/surfaces/subtree_capture_id.h" +#include "ui/aura/aura_export.h" + +namespace aura { + +class Window; + +// A scoped move-only object which is associated with a request to make a +// non-root window individually capturable by a FrameSinkVideoCapturer. This +// request is tracked as long as this object lives. Once all requests are +// destroyed, the window will no longer be uniquely identifiable by a +// viz::SubtreeCaptureId, and can no longer be individually capturable by the +// FrameSinkVideoCapturer. +// Note that making a window capturable forces the layer tree root at its layer +// to be promoted to a render surface that draw into a render pass. +// See https://crbug.com/1143930 for more details. +class AURA_EXPORT ScopedWindowCaptureRequest { + public: + // Creates an empty request that doesn't affect any window. + ScopedWindowCaptureRequest() = default; + ScopedWindowCaptureRequest(ScopedWindowCaptureRequest&& other); + ScopedWindowCaptureRequest& operator=(ScopedWindowCaptureRequest&& rhs); + ~ScopedWindowCaptureRequest(); + + Window* window() const { return window_; } + + viz::SubtreeCaptureId GetCaptureId() const; + + private: + friend class Window; + + // Private so it can only be called through Window::MakeWindowCapturable(). + explicit ScopedWindowCaptureRequest(Window* window); + + // The window on which this request has been made. Can be |nullptr| if this is + // an empty request (created by the default ctor), or if this object was + // std::move()'d from. + Window* window_ = nullptr; +}; + +} // namespace aura + +#endif // UI_AURA_SCOPED_WINDOW_CAPTURE_REQUEST_H_
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 5fa9986..413d676 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -283,6 +283,13 @@ return visible_ ? layer()->IsDrawn() : false; } +ScopedWindowCaptureRequest Window::MakeWindowCapturable() { + DCHECK(!IsRootWindow()) << "Root windows can already be captured using their " + "FrameSinkId; no need to call this."; + + return ScopedWindowCaptureRequest(this); +} + gfx::Rect Window::GetBoundsInRootWindow() const { // TODO(beng): There may be a better way to handle this, and the existing code // is likely wrong anyway in a multi-display world, but this will @@ -1413,6 +1420,18 @@ return screen_location; } +std::unique_ptr<ui::Layer> Window::ReleaseLayer() { + if (number_of_capture_requests_) { + // Before we release our own layer, if this window was marked for capture, + // we need to reset the SubtreeCaptureId on that layer as it will no longer + // be associated with us. + DCHECK(subtree_capture_id_.is_valid()); + if (layer()) + layer()->SetSubtreeCaptureId(viz::SubtreeCaptureId()); + } + return LayerOwner::ReleaseLayer(); +} + std::unique_ptr<ui::Layer> Window::RecreateLayer() { WindowOcclusionTracker::ScopedPause pause_occlusion_tracking; @@ -1430,6 +1449,12 @@ if (GetFrameSinkId().is_valid() && old_layer) AllocateLocalSurfaceId(); + // The old layer subtree must no longer be capturable. + // Note that we don't need to worry about the newly recreated layer since + // Window::SetLayer() will have taken care of it already. + if (number_of_capture_requests_ && old_layer) + old_layer->SetSubtreeCaptureId(viz::SubtreeCaptureId()); + // Observers are guaranteed to be notified when an opacity or transform // animation ends. if (was_animating_opacity) { @@ -1451,6 +1476,17 @@ return old_layer; } +void Window::SetLayer(std::unique_ptr<ui::Layer> alayer) { + LayerOwner::SetLayer(std::move(alayer)); + if (number_of_capture_requests_) { + // If this window was marked for capture before, then the new layer that we + // own now should be given the current SubtreeCaptureId that we have. + DCHECK(subtree_capture_id_.is_valid()); + if (layer()) + layer()->SetSubtreeCaptureId(subtree_capture_id_); + } +} + void Window::OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) { DCHECK_EQ(surface_info.id().frame_sink_id(), GetFrameSinkId()); layer()->SetShowSurface(surface_info.id(), bounds().size(), SK_ColorWHITE, @@ -1508,4 +1544,32 @@ return parent_local_surface_id_allocator_.get() != nullptr; } +void Window::OnScopedWindowCaptureRequestAdded() { + if (++number_of_capture_requests_ == 1) { + DCHECK(!subtree_capture_id_.is_valid()); + DCHECK(!layer() || !layer()->GetSubtreeCaptureId().is_valid()); + + subtree_capture_id_ = + Env::GetInstance()->context_factory()->AllocateSubtreeCaptureId(); + if (layer()) + layer()->SetSubtreeCaptureId(subtree_capture_id_); + } + + DCHECK(subtree_capture_id_.is_valid()); +} + +void Window::OnScopedWindowCaptureRequestRemoved() { + DCHECK(subtree_capture_id_.is_valid()); + DCHECK(number_of_capture_requests_); + + --number_of_capture_requests_; + DCHECK_GE(number_of_capture_requests_, 0); + + if (number_of_capture_requests_ == 0) { + subtree_capture_id_ = viz::SubtreeCaptureId(); + if (layer()) + layer()->SetSubtreeCaptureId(subtree_capture_id_); + } +} + } // namespace aura
diff --git a/ui/aura/window.h b/ui/aura/window.h index 2dfa559..ca46ecf 100644 --- a/ui/aura/window.h +++ b/ui/aura/window.h
@@ -26,9 +26,11 @@ #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "components/viz/common/surfaces/scoped_surface_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/host/host_frame_sink_client.h" #include "ui/aura/aura_export.h" #include "ui/aura/client/window_types.h" +#include "ui/aura/scoped_window_capture_request.h" #include "ui/aura/window_observer.h" #include "ui/base/class_property.h" #include "ui/compositor/layer_animator.h" @@ -233,6 +235,28 @@ return occluded_region_in_root_; } + // Makes this *non-root* window individually capturable by the + // |FrameSinkVideoCapturer| by tagging its layer with a unique + // |viz::SubtreeCaptureId| which will force the layer tree root at this + // window's layer to a render surface that draws into a render pass that is + // identifiable by the capturer using that ID. + // + // Note that this should only be called for non-root windows. Root windows are + // already capturable by the capturer as they're identifiable by their + // |viz::FrameSinkId| and thei associated root render pass, so there's no need + // to call this. + // + // This returns a scoped object associated with this request to make the + // window capturable, since multiple capturers can capture the same window at + // the same time. Once all requests are destroyed, this window will no longer + // be individually capturable, and its layer won't be tagged with a valid + // |viz::SubtreeCaptureId|. + // See https://crbug.com/1143930 for more details. + ScopedWindowCaptureRequest MakeWindowCapturable() WARN_UNUSED_RESULT; + const viz::SubtreeCaptureId& subtree_capture_id() const { + return subtree_capture_id_; + } + // Returns the window's bounds in root window's coordinates. gfx::Rect GetBoundsInRootWindow() const; @@ -400,8 +424,10 @@ float new_device_scale_factor) override; void UpdateVisualState() override; - // Overridden from ui::LayerOwner: + // ui::LayerOwner: + std::unique_ptr<ui::Layer> ReleaseLayer() override; std::unique_ptr<ui::Layer> RecreateLayer() override; + void SetLayer(std::unique_ptr<ui::Layer> layer) override; #if DCHECK_IS_ON() // These methods are useful when debugging. @@ -508,6 +534,7 @@ friend class HitTestDataProviderAura; friend class LayoutManager; friend class PropertyConverter; + friend class ScopedWindowCaptureRequest; friend class ScopedWindowEventTargetingBlocker; friend class WindowTargeter; friend class test::WindowTestApi; @@ -628,6 +655,14 @@ const viz::LocalSurfaceId& GetCurrentLocalSurfaceId() const; bool IsEmbeddingExternalContent() const; + // Called by the constructor of ScopedWindowCaptureRequest to add a request to + // make this non-root window capturable by the FrameSinkVideoCapturer. + void OnScopedWindowCaptureRequestAdded(); + + // Called by the destructor of ScopedWindowCaptureRequest to remove a request + // to make this non-root window capturable by the FrameSinkVideoCapturer. + void OnScopedWindowCaptureRequestRemoved(); + // Bounds of this window relative to the parent. This is cached as the bounds // of the Layer and Window are not necessarily the same. In particular bounds // of the Layer are relative to the first ancestor with a Layer, where as this @@ -688,6 +723,22 @@ base::ReentrantObserverList<WindowObserver, true> observers_; + // Video capturing support --------------------------------------------------- + + // A non-root window must be marked with a viz::SubtreeCaptureId so that it + // can be captured by a FrameSinkVideoCapturer. Multiple clients can request + // to capture the same window at the same time. This is the number of those + // requests, which once it goes to zero, we well clear the + // viz::SubtreeCaptureId from the layer associated with this window. + int number_of_capture_requests_ = 0; + + // The ID allocated for the layer tree rooted at this window's layer, so that + // it can be uniquely identified by the FrameSinkVideoCapturer. This can only + // be set for non-root windows. Root windows can be captured normally by the + // capturer using their frame sink ID, since those root windows are already + // associated with a root compositor render pass. + viz::SubtreeCaptureId subtree_capture_id_; + // Embedding support --------------------------------------------------------- // Used to detect changes in device scale factor that require generating a
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc index 6bf4c71..a30c5ee1 100644 --- a/ui/aura/window_unittest.cc +++ b/ui/aura/window_unittest.cc
@@ -6,6 +6,7 @@ #include <limits.h> +#include <memory> #include <string> #include <utility> #include <vector> @@ -24,6 +25,7 @@ #include "ui/aura/client/visibility_client.h" #include "ui/aura/client/window_parenting_client.h" #include "ui/aura/layout_manager.h" +#include "ui/aura/scoped_window_capture_request.h" #include "ui/aura/scoped_window_event_targeting_blocker.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/aura_test_utils.h" @@ -368,6 +370,92 @@ EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10))); } +TEST_F(WindowTest, MakeWindowCapturable) { + std::unique_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); + // Initailly the window is not capturable. + EXPECT_FALSE(w1->subtree_capture_id().is_valid()); + + // Creating requests makes the window capturable as long as those requests + // remain alive. + ScopedWindowCaptureRequest request1 = w1->MakeWindowCapturable(); + EXPECT_TRUE(w1->subtree_capture_id().is_valid()); + EXPECT_EQ(request1.GetCaptureId(), w1->subtree_capture_id()); + EXPECT_EQ(request1.GetCaptureId(), w1->layer()->GetSubtreeCaptureId()); + + // A new request does not affect the subtree capture ID. + const viz::SubtreeCaptureId current_id = w1->subtree_capture_id(); + ScopedWindowCaptureRequest request2 = w1->MakeWindowCapturable(); + EXPECT_EQ(current_id, w1->subtree_capture_id()); + EXPECT_EQ(request1.GetCaptureId(), request2.GetCaptureId()); + + // Create a new request, then move an existing request into it. This should + // invalidate the moved-from request. + ScopedWindowCaptureRequest request3 = w1->MakeWindowCapturable(); + EXPECT_EQ(current_id, request3.GetCaptureId()); + request3 = std::move(request2); + EXPECT_FALSE(request2.window()); + EXPECT_FALSE(request2.GetCaptureId().is_valid()); + EXPECT_TRUE(w1->subtree_capture_id().is_valid()); + + // Destroying |request2| does nothing. + auto consume_request = [](ScopedWindowCaptureRequest request) {}; + consume_request(std::move(request2)); + EXPECT_TRUE(w1->subtree_capture_id().is_valid()); + EXPECT_EQ(current_id, w1->subtree_capture_id()); + + // Destroying |request1| won't affect the window, it will remain capturable, + // since |request3| is still alive. + consume_request(std::move(request1)); + EXPECT_FALSE(request1.window()); + EXPECT_FALSE(request1.GetCaptureId().is_valid()); + EXPECT_TRUE(w1->subtree_capture_id().is_valid()); + EXPECT_EQ(current_id, w1->subtree_capture_id()); + + // Once all requests are destroyed, the window no longer has a valid capture + // ID. + consume_request(std::move(request3)); + EXPECT_FALSE(w1->subtree_capture_id().is_valid()); + EXPECT_FALSE(w1->layer()->GetSubtreeCaptureId().is_valid()); +} + +TEST_F(WindowTest, LayerReleasingAndSettingOfCapturableWindow) { + std::unique_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); + EXPECT_FALSE(w1->subtree_capture_id().is_valid()); + ScopedWindowCaptureRequest request = w1->MakeWindowCapturable(); + EXPECT_TRUE(w1->layer()->GetSubtreeCaptureId().is_valid()); + + // Releasing the capturable window's layer (i.e. it's no longer associated + // with the window) will clear its capture ID. However, the window remains + // marked as capturable with a valid SubtreeCaptureId even though it has no + // layer. + std::unique_ptr<ui::Layer> taken_layer = w1->ReleaseLayer(); + EXPECT_FALSE(w1->layer()); + EXPECT_FALSE(taken_layer->GetSubtreeCaptureId().is_valid()); + EXPECT_TRUE(w1->subtree_capture_id().is_valid()); + + // Setting a new layer on the window will set the layer's capture ID. + auto new_layer = std::make_unique<ui::Layer>(); + taken_layer->parent()->Add(new_layer.get()); + w1->Reset(std::move(new_layer)); + EXPECT_TRUE(w1->layer()->GetSubtreeCaptureId().is_valid()); + EXPECT_EQ(request.GetCaptureId(), w1->layer()->GetSubtreeCaptureId()); +} + +TEST_F(WindowTest, RecreateLayerOfCapturableWindow) { + std::unique_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); + EXPECT_FALSE(w1->subtree_capture_id().is_valid()); + ScopedWindowCaptureRequest request = w1->MakeWindowCapturable(); + EXPECT_TRUE(w1->layer()->GetSubtreeCaptureId().is_valid()); + + // Recreating the layer of a capturable window will preserve the capture ID + // on the newly recreated window, and clears it from the old layer. + const viz::SubtreeCaptureId current_id = w1->subtree_capture_id(); + std::unique_ptr<ui::Layer> old_layer = w1->RecreateLayer(); + EXPECT_FALSE(old_layer->GetSubtreeCaptureId().is_valid()); + EXPECT_EQ(current_id, w1->subtree_capture_id()); + EXPECT_EQ(current_id, w1->layer()->GetSubtreeCaptureId()); +} + TEST_F(WindowTest, ConvertPointToWindow) { // Window::ConvertPointToWindow is mostly identical to // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
diff --git a/ui/base/models/list_selection_model.cc b/ui/base/models/list_selection_model.cc index cee62e62..238fbd3 100644 --- a/ui/base/models/list_selection_model.cc +++ b/ui/base/models/list_selection_model.cc
@@ -79,7 +79,6 @@ for (auto i = selected_indices_.begin(); i != selected_indices_.end(); ++i) { IncrementFromImpl(index, &(*i)); } - reset_index_set(); IncrementFromImpl(index, &anchor_); IncrementFromImpl(index, &active_); } @@ -92,27 +91,23 @@ ++i; } } - reset_index_set(); DecrementFromImpl(index, &anchor_); DecrementFromImpl(index, &active_); } void ListSelectionModel::SetSelectedIndex(int index) { anchor_ = active_ = index; - clear_indices(); + selected_indices_.clear(); if (index != kUnselectedIndex) - add_index(index); + selected_indices_.insert(index); } bool ListSelectionModel::IsSelected(int index) const { - return base::Contains(selected_indices_set_, index); + return base::Contains(selected_indices_, index); } void ListSelectionModel::AddIndexToSelection(int index) { - if (!IsSelected(index)) { - add_index(index); - std::sort(selected_indices_.begin(), selected_indices_.end()); - } + selected_indices_.insert(index); } void ListSelectionModel::AddIndexRangeToSelection(int index_start, @@ -120,18 +115,12 @@ DCHECK_LT(index_start, index_end); for (int i = index_start; i <= index_end; ++i) { - if (!IsSelected(i)) - add_index(i); + selected_indices_.insert(i); } - std::sort(selected_indices_.begin(), selected_indices_.end()); } void ListSelectionModel::RemoveIndexFromSelection(int index) { - auto i = std::find(selected_indices_.begin(), selected_indices_.end(), index); - if (i != selected_indices_.end()) { - selected_indices_.erase(i); - selected_indices_set_.erase(index); - } + selected_indices_.erase(index); } void ListSelectionModel::SetSelectionFromAnchorTo(int index) { @@ -139,11 +128,10 @@ SetSelectedIndex(index); } else { int delta = std::abs(index - anchor_); - SelectedIndices new_selection(delta + 1, 0); + SelectedIndices new_selection; for (int i = 0, min = std::min(index, anchor_); i <= delta; ++i) - new_selection[i] = i + min; + new_selection.insert(i + min); selected_indices_.swap(new_selection); - reset_index_set(); active_ = index; } } @@ -154,10 +142,8 @@ } else { for (int i = std::min(index, anchor_), end = std::max(index, anchor_); i <= end; ++i) { - if (!IsSelected(i)) - add_index(i); + selected_indices_.insert(i); } - std::sort(selected_indices_.begin(), selected_indices_.end()); active_ = index; } } @@ -173,7 +159,6 @@ // by 2. if (new_index > old_index) { Move(old_index + length, old_index, new_index - old_index); - reset_index_set(); return; } @@ -213,29 +198,11 @@ // still sorted piecewise, and |pivot_value| is a lower bound for elements in // [low, middle), and an upper bound for [middle, high). std::rotate(low, middle, high); - DCHECK(std::is_sorted(selected_indices_.begin(), selected_indices_.end())); - reset_index_set(); } void ListSelectionModel::Clear() { anchor_ = active_ = kUnselectedIndex; - clear_indices(); -} - -void ListSelectionModel::add_index(int index) { - selected_indices_.push_back(index); - selected_indices_set_.insert(index); -} - -void ListSelectionModel::reset_index_set() { - auto set = - SelectedIndicesSet(selected_indices_.begin(), selected_indices_.end()); - selected_indices_set_.swap(set); -} - -void ListSelectionModel::clear_indices() { selected_indices_.clear(); - selected_indices_set_.clear(); } } // namespace ui
diff --git a/ui/base/models/list_selection_model.h b/ui/base/models/list_selection_model.h index 44850db..7c672f9 100644 --- a/ui/base/models/list_selection_model.h +++ b/ui/base/models/list_selection_model.h
@@ -7,10 +7,8 @@ #include <stddef.h> -#include <set> -#include <vector> - #include "base/component_export.h" +#include "base/containers/flat_set.h" namespace ui { @@ -28,8 +26,7 @@ // active index correspond to the same thing. class COMPONENT_EXPORT(UI_BASE) ListSelectionModel { public: - using SelectedIndices = std::vector<int>; - using SelectedIndicesSet = std::set<int>; + using SelectedIndices = base::flat_set<int>; // Used to identify no selection. static constexpr int kUnselectedIndex = -1; @@ -116,13 +113,7 @@ const SelectedIndices& selected_indices() const { return selected_indices_; } private: - void add_index(int index); - void reset_index_set(); - void clear_indices(); - // TODO(crbug.com/1159585): Refactor to only use one backing store for - // selections. SelectedIndices selected_indices_; - SelectedIndicesSet selected_indices_set_; int active_ = kUnselectedIndex;
diff --git a/ui/base/models/list_selection_model_unittest.cc b/ui/base/models/list_selection_model_unittest.cc index bafbafb..7b8ae0e 100644 --- a/ui/base/models/list_selection_model_unittest.cc +++ b/ui/base/models/list_selection_model_unittest.cc
@@ -24,10 +24,14 @@ " selection="; const ListSelectionModel::SelectedIndices& selection( model.selected_indices()); - for (size_t i = 0; i < selection.size(); ++i) { - if (i != 0) + bool first = true; + for (int index : selection) { + if (first) { + first = false; + } else { result += " "; - result += base::NumberToString(selection[i]); + } + result += base::NumberToString(index); } return result; }
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 8509026..6b60c00 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -77,7 +77,8 @@ // Enables GPU rasterization for all UI drawing (where not blocklisted). const base::Feature kUiGpuRasterization = {"UiGpuRasterization", -#if defined(OS_APPLE) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_FUCHSIA) +#if defined(OS_APPLE) || BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_FUCHSIA) || \ + BUILDFLAG(IS_CHROMEOS_LACROS) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index d87ee0d..e1db8f7 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h
@@ -26,6 +26,7 @@ #include "cc/trees/layer_tree_host_single_thread_client.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/host/host_frame_sink_client.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom-forward.h" @@ -125,6 +126,9 @@ // Allocate a new client ID for the display compositor. virtual viz::FrameSinkId AllocateFrameSinkId() = 0; + // Allocates a new capture ID for a layer subtree within a frame sink. + virtual viz::SubtreeCaptureId AllocateSubtreeCaptureId() = 0; + // Gets the frame sink manager host instance. virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0; };
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 5f5eecd..fb7c472 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -459,6 +459,14 @@ return animator_.get(); } +void Layer::SetSubtreeCaptureId(viz::SubtreeCaptureId subtree_id) { + cc_layer_->SetSubtreeCaptureId(subtree_id); +} + +viz::SubtreeCaptureId Layer::GetSubtreeCaptureId() const { + return cc_layer_->subtree_capture_id(); +} + void Layer::SetTransform(const gfx::Transform& transform) { GetAnimator()->SetTransform(transform); } @@ -781,6 +789,7 @@ new_layer->SetBackgroundColor(cc_layer_->background_color()); new_layer->SetSafeOpaqueBackgroundColor( cc_layer_->SafeOpaqueBackgroundColor()); + new_layer->SetSubtreeCaptureId(cc_layer_->subtree_capture_id()); new_layer->SetCacheRenderSurface(cc_layer_->cache_render_surface()); new_layer->SetTrilinearFiltering(cc_layer_->trilinear_filtering()); new_layer->SetRoundedCorner(cc_layer_->corner_radii());
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index f2a863d..e82ad7e 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -23,6 +23,7 @@ #include "cc/layers/surface_layer.h" #include "cc/layers/texture_layer_client.h" #include "components/viz/common/resources/transferable_resource.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer_animation_delegate.h" @@ -169,6 +170,23 @@ // been set. Will not return NULL. LayerAnimator* GetAnimator(); + // Sets the given |subtree_id| on the cc::Layer associated with this, so that + // the layer subtree rooted here can be uniquely identified by a + // FrameSinkVideoCapturer. The existence of a valid SubtreeCaptureId on this + // layer will force it to be drawn into a separate CompositorRenderPass. + // Setting a non-valid (i.e. default-constructed SubtreeCaptureId) will clear + // this property. + // It is not allowed to change this ID from a valid ID to another valid ID, + // since a client might already using the existing valid ID to make this layer + // subtree identifiable by a capturer. + // + // Note that this is useful when it's desired to video record a layer subtree + // of a non-root layer using a FrameSinkVideoCapturer, since non-root layers + // are usually not drawn into their own CompositorRenderPass, while the ui + // compositor's root layer always is. + void SetSubtreeCaptureId(viz::SubtreeCaptureId subtree_id); + viz::SubtreeCaptureId GetSubtreeCaptureId() const; + // The transform, relative to the parent. void SetTransform(const gfx::Transform& transform); const gfx::Transform& transform() const { return cc_layer_->transform(); }
diff --git a/ui/compositor/layer_owner.h b/ui/compositor/layer_owner.h index c541ca9..f3ea42e7 100644 --- a/ui/compositor/layer_owner.h +++ b/ui/compositor/layer_owner.h
@@ -44,7 +44,7 @@ std::unique_ptr<Layer> AcquireLayer(); // Similar to AcquireLayer(), but layer() will be set to nullptr immediately. - std::unique_ptr<Layer> ReleaseLayer(); + virtual std::unique_ptr<Layer> ReleaseLayer(); // Releases the ownership of the current layer, and takes ownership of // |layer|. @@ -63,7 +63,7 @@ bool OwnsLayer() const; protected: - void SetLayer(std::unique_ptr<Layer> layer); + virtual void SetLayer(std::unique_ptr<Layer> layer); void DestroyLayer(); private:
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc index b4db7e4..9806e412 100644 --- a/ui/compositor/layer_unittest.cc +++ b/ui/compositor/layer_unittest.cc
@@ -39,6 +39,7 @@ #include "components/viz/common/frame_sinks/copy_output_result.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id.h" #include "components/viz/common/surfaces/surface_id.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -755,6 +756,7 @@ layer->SetClipRect(clip_rect); layer->SetRoundedCornerRadius({1, 2, 4, 5}); layer->SetIsFastRoundedCorner(true); + layer->SetSubtreeCaptureId(viz::SubtreeCaptureId(1)); auto clone = layer->Clone(); @@ -773,6 +775,10 @@ EXPECT_EQ(layer->rounded_corner_radii(), clone->rounded_corner_radii()); EXPECT_EQ(layer->is_fast_rounded_corner(), clone->is_fast_rounded_corner()); + // However, the SubtreeCaptureId is not cloned. + EXPECT_TRUE(layer->GetSubtreeCaptureId().is_valid()); + EXPECT_FALSE(clone->GetSubtreeCaptureId().is_valid()); + layer->SetTransform(gfx::Transform()); layer->SetColor(SK_ColorGREEN); layer->SetLayerInverted(false); @@ -1018,6 +1024,8 @@ constexpr gfx::RoundedCornersF kCornerRadii(1, 2, 3, 4); l1->SetRoundedCornerRadius(kCornerRadii); l1->SetIsFastRoundedCorner(true); + constexpr viz::SubtreeCaptureId kSubtreeCaptureId(22); + l1->SetSubtreeCaptureId(kSubtreeCaptureId); EXPECT_EQ(gfx::Point3F(), l1->cc_layer_for_testing()->transform_origin()); EXPECT_TRUE(l1->cc_layer_for_testing()->DrawsContent()); @@ -1027,6 +1035,9 @@ EXPECT_TRUE(l1->cc_layer_for_testing()->HasRoundedCorner()); EXPECT_EQ(l1->cc_layer_for_testing()->corner_radii(), kCornerRadii); EXPECT_TRUE(l1->cc_layer_for_testing()->is_fast_rounded_corner()); + EXPECT_EQ(kSubtreeCaptureId, + l1->cc_layer_for_testing()->subtree_capture_id()); + EXPECT_EQ(kSubtreeCaptureId, l1->GetSubtreeCaptureId()); cc::Layer* before_layer = l1->cc_layer_for_testing(); @@ -1050,6 +1061,9 @@ EXPECT_TRUE(l1->cc_layer_for_testing()->HasRoundedCorner()); EXPECT_EQ(l1->cc_layer_for_testing()->corner_radii(), kCornerRadii); EXPECT_TRUE(l1->cc_layer_for_testing()->is_fast_rounded_corner()); + EXPECT_EQ(kSubtreeCaptureId, + l1->cc_layer_for_testing()->subtree_capture_id()); + EXPECT_EQ(kSubtreeCaptureId, l1->GetSubtreeCaptureId()); EXPECT_FALSE(callback1_run); bool callback2_run = false;
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 033f94d8..ea06f14 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -437,6 +437,10 @@ return frame_sink_id_allocator_.NextFrameSinkId(); } +viz::SubtreeCaptureId InProcessContextFactory::AllocateSubtreeCaptureId() { + return subtree_capture_id_allocator_.NextSubtreeCaptureId(); +} + viz::HostFrameSinkManager* InProcessContextFactory::GetHostFrameSinkManager() { return host_frame_sink_manager_; }
diff --git a/ui/compositor/test/in_process_context_factory.h b/ui/compositor/test/in_process_context_factory.h index 1e8e1c2e..98de309 100644 --- a/ui/compositor/test/in_process_context_factory.h +++ b/ui/compositor/test/in_process_context_factory.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "cc/test/test_task_graph_runner.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" +#include "components/viz/common/surfaces/subtree_capture_id_allocator.h" #include "components/viz/service/display/display.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" #include "components/viz/test/test_gpu_memory_buffer_manager.h" @@ -69,6 +70,7 @@ gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager() override; cc::TaskGraphRunner* GetTaskGraphRunner() override; viz::FrameSinkId AllocateFrameSinkId() override; + viz::SubtreeCaptureId AllocateSubtreeCaptureId() override; viz::HostFrameSinkManager* GetHostFrameSinkManager() override; SkMatrix44 GetOutputColorMatrix(Compositor* compositor) const; @@ -90,6 +92,7 @@ viz::TestImageFactory image_factory_; cc::TestTaskGraphRunner task_graph_runner_; viz::FrameSinkIdAllocator frame_sink_id_allocator_; + viz::SubtreeCaptureIdAllocator subtree_capture_id_allocator_; bool use_test_surface_; bool disable_vsync_ = false; double refresh_rate_ = 60.0;
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn index d5d612d0..717f98cc 100644 --- a/ui/file_manager/BUILD.gn +++ b/ui/file_manager/BUILD.gn
@@ -127,6 +127,7 @@ "file_manager/common/js/file_type.m.js", "file_manager/common/js/files_app_entry_types.m.js", "file_manager/common/js/lru_cache.m.js", + "file_manager/common/js/metrics.m.js", "file_manager/common/js/metrics_base.m.js", # Externs:
diff --git a/ui/file_manager/externs/background/BUILD.gn b/ui/file_manager/externs/background/BUILD.gn index d0a5d3e..1cdfa0b0 100644 --- a/ui/file_manager/externs/background/BUILD.gn +++ b/ui/file_manager/externs/background/BUILD.gn
@@ -24,6 +24,22 @@ ] } +js_library("file_browser_background_full.m") { + sources = [ "$root_gen_dir/ui/file_manager/externs/background/file_browser_background_full.m.js" ] + deps = [ + ":background_base.m", + ":crostini.m", + ":drive_sync_handler.m", + ":file_operation_manager.m", + ":import_history.m", + ":media_import_handler.m", + ":media_scanner.m", + ":progress_center.m", + ] + + extra_deps = [ ":modulize" ] +} + js_library("background_base.m") { sources = [ "$root_gen_dir/ui/file_manager/externs/background/background_base.m.js", @@ -124,6 +140,7 @@ js_modulizer("modulize") { input_files = [ + "file_browser_background_full.js", "background_base.js", "crostini.js", "drive_sync_handler.js",
diff --git a/ui/file_manager/externs/background/file_browser_background_full.js b/ui/file_manager/externs/background/file_browser_background_full.js index b5e6435..e8c2e7d 100644 --- a/ui/file_manager/externs/background/file_browser_background_full.js +++ b/ui/file_manager/externs/background/file_browser_background_full.js
@@ -3,10 +3,27 @@ // found in the LICENSE file. /** + * @fileoverview + * @suppress {externsValidation} this file is used as externs and also + * as JS module, Closure fails to compile as JS module. + */ + +// #import {DriveSyncHandler} from './drive_sync_handler.m.js'; +// #import {ProgressCenter} from './progress_center.m.js'; +// #import {FileOperationManager} from './file_operation_manager.m.js'; +// #import {mediaImportInterfaces} from './media_import_handler.m.js'; +// #import {mediaScannerInterfaces} from './media_scanner.m.js'; +// #import {importerHistoryInterfaces} from './import_history.m.js'; +// #import {Crostini} from './crostini.m.js'; +// #import {BackgroundBase} from './background_base.m.js'; + +/** * @interface */ -class FileBrowserBackgroundFull extends BackgroundBase { +/* #export */ class FileBrowserBackgroundFull extends BackgroundBase { constructor() { + super(); + /** * @type {!DriveSyncHandler} */
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn index ad64fa34..61fad689 100644 --- a/ui/file_manager/file_manager/background/js/BUILD.gn +++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -74,6 +74,7 @@ deps = [ ":app_window_wrapper.m", ":app_windows.m", + ":background.m", ":background_base.m", ":crostini.m", ":device_handler.m", @@ -224,6 +225,47 @@ ] } +js_library("background.m") { + sources = [ + "$root_gen_dir/ui/file_manager/file_manager/background/js/background.m.js", + ] + deps = [ + ":background_base.m", + ":crostini.m", + ":device_handler.m", + ":drive_sync_handler.m", + ":duplicate_finder.m", + ":file_operation_handler.m", + ":file_operation_manager.m", + ":file_operation_util.m", + ":import_history.m", + ":launcher.m", + ":launcher_search.m", + ":media_import_handler.m", + ":media_scanner.m", + ":mount_metrics.m", + ":progress_center.m", + ":volume_manager_factory.m", + "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/externs:volume_info.m", + "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/externs/background:crostini.m", + "//ui/file_manager/externs/background:drive_sync_handler.m", + "//ui/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/externs/background:file_browser_background_full.m", + "//ui/file_manager/externs/background:file_operation_manager.m", + "//ui/file_manager/externs/background:import_history.m", + "//ui/file_manager/externs/background:media_import_handler.m", + "//ui/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/externs/background:progress_center.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:util.m", + ] + + extra_deps = [ ":modulize" ] +} + js_library("background_base") { visibility += related_apps deps = [ @@ -550,7 +592,6 @@ "//ui/file_manager/externs/background:file_operation_manager.m", "//ui/file_manager/file_manager/common/js:async_util.m", "//ui/file_manager/file_manager/common/js:file_operation_common.m", - "//ui/file_manager/file_manager/common/js:mock_entry.m", "//ui/file_manager/file_manager/common/js:trash.m", "//ui/file_manager/file_manager/common/js:util.m", "//ui/webui/resources/js:assert.m", @@ -993,6 +1034,12 @@ js_library("test_util_base.m") { visibility += related_apps sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/test_util_base.m.js" ] + deps = [ + "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:util.m", + "//ui/webui/resources/js:assert.m", + ] extra_deps = [ ":modulize" ] } @@ -1237,6 +1284,7 @@ "device_handler.js", "launcher.js", "launcher_search.js", + "background.js", ] namespace_rewrites = cr_namespace_rewrites
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js index c2cbf62..3cf30a8 100644 --- a/ui/file_manager/file_manager/background/js/background.js +++ b/ui/file_manager/file_manager/background/js/background.js
@@ -2,6 +2,40 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {VolumeInfo} from '../../../externs/volume_info.m.js'; +// #import {VolumeManager} from '../../../externs/volume_manager.m.js'; +// #import {Crostini} from '../../../externs/background/crostini.m.js'; +// #import {FileBrowserBackgroundFull} from '../../../externs/background/file_browser_background_full.m.js'; +// #import {mediaImportInterfaces} from '../../../externs/background/media_import_handler.m.js'; +// #import {mediaScannerInterfaces} from '../../../externs/background/media_scanner.m.js'; +// #import {duplicateFinderInterfaces} from '../../../externs/background/duplicate_finder.m.js'; +// #import {DriveSyncHandler} from '../../../externs/background/drive_sync_handler.m.js'; +// #import {importerHistoryInterfaces} from '../../../externs/background/import_history.m.js'; +// #import {FileOperationManager} from '../../../externs/background/file_operation_manager.m.js'; +// #import {ProgressCenter} from '../../../externs/background/progress_center.m.js'; +// #import {util, str} from '../../common/js/util.m.js'; +// #import {metrics} from '../../common/js/metrics.m.js'; +// #import {fileOperationUtil} from './file_operation_util.m.js'; +// #import {launcher, LaunchType, nextFileManagerWindowID, FILES_ID_PATTERN} from './launcher.m.js'; +// #import {FileOperationHandler} from './file_operation_handler.m.js'; +// #import {FileOperationManagerImpl} from './file_operation_manager.m.js'; +// #import {VolumeManagerCommon} from '../../../base/js/volume_manager_types.m.js'; +// #import {volumeManagerFactory} from './volume_manager_factory.m.js'; +// #import {LauncherSearch} from './launcher_search.m.js'; +// #import {MountMetrics} from './mount_metrics.m.js'; +// #import {CrostiniImpl} from './crostini.m.js'; +// #import {mediaImport} from './media_import_handler.m.js'; +// #import {mediaScanner} from './media_scanner.m.js'; +// #import {duplicateFinder} from './duplicate_finder.m.js'; +// #import {DriveSyncHandlerImpl} from './drive_sync_handler.m.js'; +// #import {DeviceHandler} from './device_handler.m.js'; +// #import {importer} from '../../common/js/importer_common.m.js'; +// #import {importerHistory} from './import_history.m.js'; +// #import {ProgressCenterImpl} from './progress_center.m.js'; +// #import {BackgroundBaseImpl} from './background_base.m.js'; +// clang-format on + /** * Root class of the background page. * @implements {FileBrowserBackgroundFull} @@ -524,7 +558,7 @@ * * @param {!Window} dialogWindow Window of the dialog. */ -function registerDialog(dialogWindow) { +/* #export */ function registerDialog(dialogWindow) { const id = DIALOG_ID_PREFIX + (nextFileManagerDialogID++); window.background.dialogs[id] = dialogWindow; if (window.IN_TEST) {
diff --git a/ui/file_manager/file_manager/background/js/file_operation_manager.js b/ui/file_manager/file_manager/background/js/file_operation_manager.js index 1755041..59fbf3a 100644 --- a/ui/file_manager/file_manager/background/js/file_operation_manager.js +++ b/ui/file_manager/file_manager/background/js/file_operation_manager.js
@@ -7,7 +7,6 @@ // #import {FakeEntry} from '../../../externs/files_app_entry_interfaces.m.js'; // #import {VolumeManager} from '../../../externs/volume_manager.m.js'; // #import {EntryLocation} from '../../../externs/entry_location.m.js'; -// #import {MockEntry} from '../../common/js/mock_entry.m.js'; // #import {FileOperationManager} from '../../../externs/background/file_operation_manager.m.js'; // #import {assert} from 'chrome://resources/js/assert.m.js'; // #import {metadataProxy} from './metadata_proxy.m.js';
diff --git a/ui/file_manager/file_manager/background/js/launcher.js b/ui/file_manager/file_manager/background/js/launcher.js index 301192cb..59a7450 100644 --- a/ui/file_manager/file_manager/background/js/launcher.js +++ b/ui/file_manager/file_manager/background/js/launcher.js
@@ -36,7 +36,7 @@ * Value of the next file manager window ID. * @type {number} */ -let nextFileManagerWindowID = 0; +/* #export */ let nextFileManagerWindowID = 0; /** * File manager window create options. @@ -60,7 +60,8 @@ * Regexp matching a file manager window ID. * @const {!RegExp} */ -const FILES_ID_PATTERN = new RegExp('^' + FILES_ID_PREFIX + '(\\d*)$'); +/* #export */ const FILES_ID_PATTERN = + new RegExp('^' + FILES_ID_PREFIX + '(\\d*)$'); /** * Promise to serialize asynchronous calls.
diff --git a/ui/file_manager/file_manager/background/js/test_util_base.js b/ui/file_manager/file_manager/background/js/test_util_base.js index 18ba6aa7..88166da 100644 --- a/ui/file_manager/file_manager/background/js/test_util_base.js +++ b/ui/file_manager/file_manager/background/js/test_util_base.js
@@ -8,8 +8,9 @@ */ // clang-format off -// #import * as wrappedVolumeManagerCommon from '../../../base/js/volume_manager_types.m.js'; const {VolumeManagerCommon} = wrappedVolumeManagerCommon; -// #import * as wrappedUtil from '../../common/js/util.m.js'; const {util} = wrappedUtil; +// #import {VolumeManagerCommon} from '../../../base/js/volume_manager_types.m.js'; +// #import {util} from '../../common/js/util.m.js'; +// #import {metrics} from '../../common/js/metrics.m.js'; // #import {assert} from 'chrome://resources/js/assert.m.js'; // clang-format on @@ -102,6 +103,7 @@ window.VolumeManagerCommon = VolumeManagerCommon; window.util = util; window.assert = assert; + window.metrics = metrics; // Asynchronously load the testing functions. const script = document.createElement('script');
diff --git a/ui/file_manager/file_manager/common/js/metrics_base.js b/ui/file_manager/file_manager/common/js/metrics_base.js index eb358e95..6364493f 100644 --- a/ui/file_manager/file_manager/common/js/metrics_base.js +++ b/ui/file_manager/file_manager/common/js/metrics_base.js
@@ -120,11 +120,24 @@ /** * Records an elapsed time of no more than 10 seconds. * @param {string} name Short metric name. + * @param {!chrome.metricsPrivate.MetricTypeType} type + * @param {number} min + * @param {number} max + * @param {number} buckets * @param {number} value Numeric value to be recorded in units * that match the histogram definition (in histograms.xml). */ -metricsBase.recordValue = (name, value) => { - metricsBase.call_('recordValue', [metricsBase.convertName_(name), value]); +metricsBase.recordValue = (name, type, min, max, buckets, value) => { + metricsBase.call_('recordValue', [ + { + 'metricName': metricsBase.convertName_(name), + 'type': type, + 'min': min, + 'max': max, + 'buckets': buckets + }, + value + ]); }; /**
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js index 2161809..449f1c0 100644 --- a/ui/file_manager/file_manager/common/js/util.js +++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1776,26 +1776,6 @@ loadTimeData.getBoolean('SHARESHEET_ENABLED'); }; -/** @return {boolean} */ -util.isHoldingSpaceEnabled = () => { - return loadTimeData.valueExists('HOLDING_SPACE_ENABLED') && - loadTimeData.getBoolean('HOLDING_SPACE_ENABLED'); -}; - -/** - * Returns the volume types for which the holding space feature is allowed. - * @return {!Array<VolumeManagerCommon.VolumeType>} - */ -util.getHoldingSpaceAllowedVolumeTypes = () => { - return [ - VolumeManagerCommon.VolumeType.ANDROID_FILES, - VolumeManagerCommon.VolumeType.CROSTINI, - VolumeManagerCommon.VolumeType.DRIVE, - VolumeManagerCommon.VolumeType.DOWNLOADS, - VolumeManagerCommon.VolumeType.MY_FILES, - ]; -}; - util.isDriveDssPinEnabled = () => { return loadTimeData.valueExists('DRIVE_DSS_PIN_ENABLED') && loadTimeData.getBoolean('DRIVE_DSS_PIN_ENABLED');
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 2b086d9..876192939 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -545,6 +545,7 @@ ":file_selection", ":file_tasks", ":file_transfer_controller", + ":holding_space_util", ":naming_controller", ":providers_model", ":spinner_controller", @@ -711,6 +712,14 @@ ] } +js_library("holding_space_util") { + deps = [ + "//ui/file_manager/base/js:volume_manager_types", + "//ui/webui/resources/js:assert", + "//ui/webui/resources/js:load_time_data", + ] +} + js_library("import_controller") { deps = [ ":actions_controller",
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index f8886c1..58f9b893 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1783,19 +1783,23 @@ const entries = fileManager.selectionHandler.selection.entries; chrome.fileManagerPrivate.toggleAddedToHoldingSpace( entries, this.addsItems_); + + if (this.addsItems_) { + HoldingSpaceUtil.maybeStoreTimeOfFirstPin(); + } } /** @override */ canExecute(event, fileManager) { const command = event.command; - if (!util.isHoldingSpaceEnabled()) { + if (!HoldingSpaceUtil.isFeatureEnabled()) { event.canExecute = false; command.setHidden(true); return; } - const allowedVolumeTypes = util.getHoldingSpaceAllowedVolumeTypes(); + const allowedVolumeTypes = HoldingSpaceUtil.getAllowedVolumeTypes(); const currentVolumeInfo = fileManager.directoryModel.getCurrentVolumeInfo(); if (!currentVolumeInfo || !allowedVolumeTypes.includes(currentVolumeInfo.volumeType)) {
diff --git a/ui/file_manager/file_manager/foreground/js/holding_space_util.js b/ui/file_manager/file_manager/foreground/js/holding_space_util.js new file mode 100644 index 0000000..97b6276 --- /dev/null +++ b/ui/file_manager/file_manager/foreground/js/holding_space_util.js
@@ -0,0 +1,138 @@ +// Copyright 2020 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. + +/** + * @fileoverview Utility methods for the holding space feature. + */ + +class HoldingSpaceUtil { + /** + * Returns the key in localStorage to store the time (in milliseconds) of the + * first pin to holding space. + * @return {string} + * @private + */ + static get TIME_OF_FIRST_PIN_KEY_() { + return 'holdingSpaceTimeOfFirstPin'; + } + + /** + * Returns the key in localStorage to store the time (in milliseconds) of the + * first showing of the holding space welcome banner. + * @constructor + * @private + */ + static get TIME_OF_FIRST_WELCOME_BANNER_SHOW_KEY_() { + return 'holdingSpaceTimeOfFirstWelcomeBannerShow'; + } + + /** @return {boolean} */ + static isFeatureEnabled() { + return loadTimeData.valueExists('HOLDING_SPACE_ENABLED') && + loadTimeData.getBoolean('HOLDING_SPACE_ENABLED'); + } + + /** + * Returns the volume types for which the holding space feature is allowed. + * @return {!Array<VolumeManagerCommon.VolumeType>} + */ + static getAllowedVolumeTypes() { + return [ + VolumeManagerCommon.VolumeType.ANDROID_FILES, + VolumeManagerCommon.VolumeType.CROSTINI, + VolumeManagerCommon.VolumeType.DRIVE, + VolumeManagerCommon.VolumeType.DOWNLOADS, + VolumeManagerCommon.VolumeType.MY_FILES, + ]; + } + + /** + * Returns a promise which resolves to the time (in milliseconds) of the first + * pin to holding space. If no pin has occurred, resolves to `undefined`. + * @return {Promise<?number>} + * @private + */ + static getTimeOfFirstPin_() { + return new Promise(resolve => { + const key = HoldingSpaceUtil.TIME_OF_FIRST_PIN_KEY_; + chrome.storage.local.get(key, values => { + resolve(values[key]); + }); + }); + } + + /** + * Returns a promise which resolves to the time (in milliseconds) of the first + * showing of the holding space welcome banner. If no showing has occurred, + * resolves to `undefined`. + * @return {Promise<?number>} + * @private + */ + static getTimeOfFirstWelcomeBannerShow_() { + return new Promise(resolve => { + const key = HoldingSpaceUtil.TIME_OF_FIRST_WELCOME_BANNER_SHOW_KEY_; + chrome.storage.local.get(key, values => { + resolve(values[key]); + }); + }); + } + + /** + * If not previously stored, stores now (in milliseconds) as the time of the + * first pin to holding space. + */ + static async maybeStoreTimeOfFirstPin() { + const now = Date.now(); + + // Time of first pin should only be stored once. + if (await HoldingSpaceUtil.getTimeOfFirstPin_()) { + return; + } + + // Store time of first pin. + const values = {}; + values[HoldingSpaceUtil.TIME_OF_FIRST_PIN_KEY_] = now; + chrome.storage.local.set(values); + + // Record a metric of the interval from the first time the holding space + // welcome banner was shown to the time of the first pin to holding space. + // If the welcome banner was not shown prior to the first pin, record zero. + const timeOfFirstWelcomeBannerShow = + await HoldingSpaceUtil.getTimeOfFirstWelcomeBannerShow_() || now; + const timeFromFirstWelcomeBannerShowToFirstPin = + now - timeOfFirstWelcomeBannerShow; + + // The histogram will use min values of 1 second and max of 1 day. Note + // that it's permissible to record values smaller/larger than the min/max + // and they will fall into the histogram's underflow/overflow bucket + // respectively. + const oneSecondInMillis = 1000; + const oneDayInMillis = 24 * 60 * 60 * 1000; + metrics.recordValue( + /*name=*/ 'HoldingSpace.TimeFromFirstWelcomeBannerShowToFirstPin', + /*type=*/ 'histogram-log', + /*min=*/ oneSecondInMillis, + /*max=*/ oneDayInMillis, + /*buckets=*/ 50, + /*value=*/ timeFromFirstWelcomeBannerShowToFirstPin); + } + + /** + * If not previously stored, stores now (in milliseconds) as the time of the + * first showing of the holding space welcome banner. + */ + static async maybeStoreTimeOfFirstWelcomeBannerShow() { + const now = Date.now(); + + // Time of first show should only be stored once. + if (await HoldingSpaceUtil.getTimeOfFirstWelcomeBannerShow_()) { + return; + } + + // Store time of first show. + const values = {}; + values[HoldingSpaceUtil.TIME_OF_FIRST_WELCOME_BANNER_SHOW_KEY_] = now; + chrome.storage.local.set(values); + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/main_scripts.js b/ui/file_manager/file_manager/foreground/js/main_scripts.js index 75ccb2a7..916c34d 100644 --- a/ui/file_manager/file_manager/foreground/js/main_scripts.js +++ b/ui/file_manager/file_manager/foreground/js/main_scripts.js
@@ -130,6 +130,7 @@ // <include src="folder_shortcuts_data_model.js"> // <include src="sort_menu_controller.js"> // <include src="gear_menu_controller.js"> +// <include src="holding_space_util.js"> // <include src="import_controller.js"> // <include src="last_modified_controller.js"> // <include src="launch_param.js">
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index 292132e..3d1e045 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -126,6 +126,7 @@ "//ui/file_manager/base/js:volume_manager_types", "//ui/file_manager/file_manager/common/js:util", "//ui/file_manager/file_manager/foreground/js:directory_model", + "//ui/file_manager/file_manager/foreground/js:holding_space_util", "//ui/webui/resources/js:assert", "//ui/webui/resources/js/cr:event_target", ]
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners.js b/ui/file_manager/file_manager/foreground/js/ui/banners.js index f9f75df..bd2c6669 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners.js
@@ -292,7 +292,7 @@ * @private */ prepareAndShowHoldingSpaceWelcomeBanner_() { - assert(util.isHoldingSpaceEnabled()); + assert(HoldingSpaceUtil.isFeatureEnabled()); this.showHoldingSpaceWelcomeBanner_(true); // Do not recreate the banner. @@ -552,7 +552,7 @@ * @private */ closeHoldingSpaceWelcomeBanner_() { - assert(util.isHoldingSpaceEnabled()); + assert(HoldingSpaceUtil.isFeatureEnabled()); this.cleanupHoldingSpaceWelcomeBanner_(); // Stop showing the welcome banner. @@ -614,7 +614,7 @@ * @private */ async maybeShowHoldingSpaceWelcomeBanner_() { - if (!util.isHoldingSpaceEnabled()) { + if (!HoldingSpaceUtil.isFeatureEnabled()) { return; } @@ -624,7 +624,7 @@ // its banner should only be shown for those volumes. Note that the holding // space banner is explicitly disallowed from showing in `DRIVE` to prevent // the possibility of it being shown alongside the Drive banner. - const allowedVolumeTypes = util.getHoldingSpaceAllowedVolumeTypes(); + const allowedVolumeTypes = HoldingSpaceUtil.getAllowedVolumeTypes(); const currentVolumeInfo = this.directoryModel_.getCurrentVolumeInfo(); if (!currentVolumeInfo || !allowedVolumeTypes.includes(currentVolumeInfo.volumeType) || @@ -721,7 +721,7 @@ * @private */ showHoldingSpaceWelcomeBanner_(show) { - assert(util.isHoldingSpaceEnabled()); + assert(HoldingSpaceUtil.isFeatureEnabled()); const /** boolean */ hidden = !show; if (this.holdingSpaceWelcomeBanner_.hasAttribute('hidden') == hidden) { @@ -732,6 +732,7 @@ this.holdingSpaceWelcomeBanner_.setAttribute('hidden', ''); } else { this.holdingSpaceWelcomeBanner_.removeAttribute('hidden'); + HoldingSpaceUtil.maybeStoreTimeOfFirstWelcomeBannerShow(); } this.requestRelayout_(200); // Resize only after the animation is done. @@ -894,7 +895,7 @@ * @private */ cleanupHoldingSpaceWelcomeBanner_() { - assert(util.isHoldingSpaceEnabled()); + assert(HoldingSpaceUtil.isFeatureEnabled()); this.showHoldingSpaceWelcomeBanner_(false); }
diff --git a/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js b/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js index f780073..bed0fbe 100644 --- a/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js +++ b/ui/file_manager/file_manager/test/js/chrome_api_test_impl.js
@@ -115,8 +115,8 @@ recordUserAction: (action) => { chrome.metricsPrivate.userActions_.push(action); }, - recordValue: (metricName, value) => { - chrome.metricsPrivate.values_.push([metricName, value]); + recordValue: (metric, value) => { + chrome.metricsPrivate.values_.push([metric, value]); }, },
diff --git a/ui/gl/gl_surface_egl_surface_control.cc b/ui/gl/gl_surface_egl_surface_control.cc index 8c92259..b0e7c0f 100644 --- a/ui/gl/gl_surface_egl_surface_control.cc +++ b/ui/gl/gl_surface_egl_surface_control.cc
@@ -10,9 +10,7 @@ #include "base/android/build_info.h" #include "base/android/scoped_hardware_buffer_fence_sync.h" #include "base/bind.h" -#include "base/debug/dump_without_crashing.h" #include "base/posix/eintr_wrapper.h" -#include "base/rand_util.h" #include "base/strings/strcat.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" @@ -685,11 +683,6 @@ LOG(ERROR) << "Transaction id " << transaction_id << " haven't received any ack from past 5 second which indicates " "it hanged"; - - // Hang detection logic here. we want to limit the number of dumps to 10% of - // the cases to avoid seeing too many instances in crash report. - if (base::RandInt(1, 10) == 1) - base::debug::DumpWithoutCrashing(); } } // namespace gl
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index 93e1ca9..f44eed4 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -26,7 +26,6 @@ #include "ui/ozone/platform/wayland/host/wayland_data_device_manager.h" #include "ui/ozone/platform/wayland/host/wayland_data_drag_controller.h" #include "ui/ozone/platform/wayland/host/wayland_data_source.h" -#include "ui/ozone/platform/wayland/host/wayland_toplevel_window.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" #include "ui/ozone/platform/wayland/test/mock_surface.h" #include "ui/ozone/platform/wayland/test/test_data_device.h" @@ -154,6 +153,12 @@ return connection_->data_device_manager()->GetDevice(); } + MockDropHandler* drop_handler() { return drop_handler_.get(); } + + MockDragHandlerDelegate* drag_handler() { + return drag_handler_delegate_.get(); + } + WaylandConnection* connection() { return connection_.get(); } WaylandWindow* window() { return window_.get(); } @@ -168,6 +173,22 @@ return ++serial; } + std::unique_ptr<WaylandWindow> CreateTestWindow( + PlatformWindowType type, + const gfx::Size& size, + MockPlatformWindowDelegate* delegate) { + DCHECK(delegate); + PlatformWindowInitProperties properties{gfx::Rect(size)}; + properties.type = type; + EXPECT_CALL(*delegate, OnAcceleratedWidgetAvailable(_)).Times(1); + auto window = WaylandWindow::Create(delegate, connection_.get(), + std::move(properties)); + SetWmDropHandler(window.get(), drop_handler_.get()); + EXPECT_NE(gfx::kNullAcceleratedWidget, window->GetWidget()); + Sync(); + return window; + } + // TODO(crbug.com/1163544): Deduplicate DnD test helper code. void SendDndEnter(WaylandWindow* window, const gfx::Point& location) { EXPECT_TRUE(data_device_manager_->data_source()); @@ -232,6 +253,13 @@ ScheduleTestTask(base::BindOnce( [](WaylandDataDragControllerTest* self) { self->SendDndCancelled(); + + // DnD handlers expect DragLeave to be sent before DragFinished when + // drag sessions end up with no data transfer (cancelled). Otherwise, + // it might lead to issues like https://crbug.com/1109324. + EXPECT_CALL(*self->drop_handler(), OnDragLeave).Times(1); + EXPECT_CALL(*self->drag_handler(), OnDragFinished).Times(1); + self->Sync(); }, base::Unretained(this))); @@ -278,10 +306,9 @@ base::BindOnce(&WaylandDataDragControllerTest::ReadDataWhenSourceIsReady, base::Unretained(this))); - static_cast<WaylandToplevelWindow*>(window_.get()) - ->StartDrag(os_exchange_data, - DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE, {}, true, - drag_handler_delegate_.get()); + window_->StartDrag(os_exchange_data, + DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE, {}, + /*can_grab_pointer=*/true, drag_handler_delegate_.get()); Sync(); EXPECT_FALSE(data_device()->drag_delegate_); @@ -537,24 +564,12 @@ const bool restored_focus = window_->has_pointer_focus(); window_->SetPointerFocus(true); - ASSERT_EQ(PlatformWindowType::kWindow, window_->type()); + ScheduleDragCancel(); + OSExchangeData os_exchange_data; os_exchange_data.SetString(sample_text_for_dnd()); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&WaylandDataDragControllerTest::ScheduleDragCancel, - base::Unretained(this))); - - // DnD handlers expect DragLeave to be sent before DragFinished when drag - // sessions end up with no data transfer (cancelled). Otherwise, it might lead - // to issues like https://crbug.com/1109324. - EXPECT_CALL(*drop_handler_, OnDragLeave()).Times(1); - EXPECT_CALL(*drag_handler_delegate_, OnDragFinished(_)).Times(1); - - static_cast<WaylandToplevelWindow*>(window_.get()) - ->StartDrag(os_exchange_data, DragDropTypes::DRAG_COPY, {}, true, - drag_handler_delegate_.get()); + window_->StartDrag(os_exchange_data, DragDropTypes::DRAG_COPY, {}, + /*can_grab_pointer=*/true, drag_handler_delegate_.get()); Sync(); window_->SetPointerFocus(restored_focus); @@ -595,7 +610,7 @@ // Regression test for https://crbug.com/1143707. TEST_P(WaylandDataDragControllerTest, DestroyEnteredSurface) { - auto* window_1 = static_cast<WaylandToplevelWindow*>(window_.get()); + auto* window_1 = window_.get(); const bool restored_focus = window_1->has_pointer_focus(); window_1->SetPointerFocus(true); ASSERT_EQ(PlatformWindowType::kWindow, window_1->type()); @@ -605,14 +620,9 @@ self->SendDndEnter(self->window(), gfx::Point(10, 10)); // Init and open |target_window|. - PlatformWindowInitProperties properties{gfx::Rect{80, 80}}; - properties.type = PlatformWindowType::kWindow; MockPlatformWindowDelegate delegate_2; - EXPECT_CALL(delegate_2, OnAcceleratedWidgetAvailable(_)).Times(1); - auto window_2 = WaylandWindow::Create(&delegate_2, self->connection(), - std::move(properties)); - ASSERT_NE(gfx::kNullAcceleratedWidget, window_2->GetWidget()); - self->Sync(); + auto window_2 = self->CreateTestWindow(PlatformWindowType::kWindow, + gfx::Size(80, 80), &delegate_2); // Leave |window_1| and enter |window_2|. self->SendDndLeave(); @@ -644,6 +654,60 @@ window_1->SetPointerFocus(restored_focus); } +// Ensures drag/drop events are properly propagated to non-toplevel windows. +TEST_P(WaylandDataDragControllerTest, DragToNonToplevelWindows) { + auto* origin_window = window_.get(); + const bool restored_focus = origin_window->has_pointer_focus(); + origin_window->SetPointerFocus(true); + + auto test = [](WaylandDataDragControllerTest* self, + PlatformWindowType window_type) { + // Emulate server sending an dnd offer + enter events for |origin_window|. + self->SendDndEnter(self->window(), gfx::Point(10, 10)); + EXPECT_CALL(*self->drop_handler(), MockOnDragEnter()).Times(1); + EXPECT_CALL(*self->drop_handler(), MockDragMotion(_, _, _)).Times(1); + self->Sync(); + + // Init and open |target_window|. + MockPlatformWindowDelegate delegate_2; + auto window_2 = + self->CreateTestWindow(window_type, gfx::Size(100, 40), &delegate_2); + + // Leave |origin_window| and enter non-toplevel |window_2|. + self->SendDndLeave(); + EXPECT_CALL(*self->drop_handler(), OnDragLeave).Times(1); + + self->SendDndEnter(window_2.get(), {}); + EXPECT_CALL(*self->drop_handler(), MockOnDragEnter()).Times(1); + EXPECT_CALL(*self->drop_handler(), MockDragMotion(_, _, _)).Times(1); + self->Sync(); + + self->SendDndLeave(); + EXPECT_CALL(*self->drop_handler(), OnDragLeave).Times(1); + self->Sync(); + }; + + // Post test tasks, for each non-toplevel window type, to be performed + // asynchronously once the dnd-related protocol objects are ready. + constexpr PlatformWindowType kNonToplevelWindowTypes[]{ + PlatformWindowType::kPopup, PlatformWindowType::kMenu, + PlatformWindowType::kTooltip, PlatformWindowType::kBubble}; + for (auto window_type : kNonToplevelWindowTypes) + ScheduleTestTask(base::BindOnce(test, base::Unretained(this), window_type)); + + // Post a wl_data_source::cancelled notifying the client to tear down the drag + // session. + ScheduleDragCancel(); + + // Request to start the drag session, which spins a nested run loop. + OSExchangeData os_exchange_data; + os_exchange_data.SetString(sample_text_for_dnd()); + origin_window->StartDrag(os_exchange_data, DragDropTypes::DRAG_COPY, {}, true, + drag_handler_delegate_.get()); + Sync(); + origin_window->SetPointerFocus(restored_focus); +} + INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, WaylandDataDragControllerTest, ::testing::Values(kXdgShellStable));
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc index 1ea4c1a3..1de78dcc 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -9,21 +9,17 @@ #include "base/run_loop.h" #include "base/unguessable_token.h" #include "build/chromeos_buildflags.h" -#include "ui/base/dragdrop/drag_drop_types.h" -#include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/hit_test.h" #include "ui/gfx/native_widget_types.h" #include "ui/ozone/platform/wayland/host/shell_object_factory.h" #include "ui/ozone/platform/wayland/host/shell_surface_wrapper.h" #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" -#include "ui/ozone/platform/wayland/host/wayland_data_drag_controller.h" #include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" #include "ui/ozone/platform/wayland/host/wayland_window_drag_controller.h" #include "ui/ozone/platform/wayland/host/wayland_zaura_shell.h" #include "ui/platform_window/extensions/wayland_extension.h" -#include "ui/platform_window/wm/wm_drop_handler.h" #if BUILDFLAG(IS_CHROMEOS_LACROS) // TODO(jamescook): The nogncheck is to work around false-positive failures on @@ -40,18 +36,9 @@ // Set a class property key, which allows |this| to be used for interactive // events, e.g. move or resize. SetWmMoveResizeHandler(this, AsWmMoveResizeHandler()); - - // Set a class property key, which allows |this| to be used for drag action. - SetWmDragHandler(this, this); } -WaylandToplevelWindow::~WaylandToplevelWindow() { - if (drag_handler_delegate_) { - drag_handler_delegate_->OnDragFinished( - DragDropTypes::DragOperation::DRAG_NONE); - } - CancelDrag(); -} +WaylandToplevelWindow::~WaylandToplevelWindow() = default; bool WaylandToplevelWindow::CreateShellSurface() { ShellObjectFactory factory; @@ -99,31 +86,6 @@ connection()->ScheduleFlush(); } -bool WaylandToplevelWindow::StartDrag(const ui::OSExchangeData& data, - int operation, - gfx::NativeCursor cursor, - bool can_grab_pointer, - WmDragHandler::Delegate* delegate) { - DCHECK(!drag_handler_delegate_); - drag_handler_delegate_ = delegate; - connection()->data_drag_controller()->StartSession(data, operation); - - base::RunLoop drag_loop(base::RunLoop::Type::kNestableTasksAllowed); - drag_loop_quit_closure_ = drag_loop.QuitClosure(); - - auto alive = weak_ptr_factory_.GetWeakPtr(); - drag_loop.Run(); - if (!alive) - return false; - return true; -} - -void WaylandToplevelWindow::CancelDrag() { - if (drag_loop_quit_closure_.is_null()) - return; - std::move(drag_loop_quit_closure_).Run(); -} - void WaylandToplevelWindow::Show(bool inactive) { if (shell_surface_) return; @@ -321,59 +283,6 @@ delegate()->OnActivationChanged(is_active_); } -void WaylandToplevelWindow::OnDragEnter(const gfx::PointF& point, - std::unique_ptr<OSExchangeData> data, - int operation) { - WmDropHandler* drop_handler = GetWmDropHandler(*this); - if (!drop_handler) - return; - - // Wayland sends locations in DIP so they need to be translated to - // physical pixels. - // TODO(crbug.com/1102857): get the real event modifier here. - drop_handler->OnDragEnter( - gfx::ScalePoint(point, buffer_scale(), buffer_scale()), std::move(data), - operation, - /*modifiers=*/0); -} - -int WaylandToplevelWindow::OnDragMotion(const gfx::PointF& point, - int operation) { - WmDropHandler* drop_handler = GetWmDropHandler(*this); - if (!drop_handler) - return 0; - - // Wayland sends locations in DIP so they need to be translated to - // physical pixels. - // TODO(crbug.com/1102857): get the real event modifier here. - return drop_handler->OnDragMotion( - gfx::ScalePoint(point, buffer_scale(), buffer_scale()), operation, - /*modifiers=*/0); -} - -void WaylandToplevelWindow::OnDragDrop() { - WmDropHandler* drop_handler = GetWmDropHandler(*this); - if (!drop_handler) - return; - // TODO(crbug.com/1102857): get the real event modifier here. - drop_handler->OnDragDrop({}, /*modifiers=*/0); -} - -void WaylandToplevelWindow::OnDragLeave() { - WmDropHandler* drop_handler = GetWmDropHandler(*this); - if (!drop_handler) - return; - drop_handler->OnDragLeave(); -} - -void WaylandToplevelWindow::OnDragSessionClose(uint32_t dnd_action) { - DCHECK(drag_handler_delegate_); - drag_handler_delegate_->OnDragFinished(dnd_action); - drag_handler_delegate_ = nullptr; - connection()->event_source()->ResetPointerFlags(); - std::move(drag_loop_quit_closure_).Run(); -} - bool WaylandToplevelWindow::OnInitialize( PlatformWindowInitProperties properties) { #if BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h index a6f2b82..591ca199 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.h +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.h
@@ -9,7 +9,6 @@ #include "ui/gfx/geometry/vector2d.h" #include "ui/ozone/platform/wayland/host/wayland_window.h" #include "ui/platform_window/extensions/wayland_extension.h" -#include "ui/platform_window/wm/wm_drag_handler.h" #include "ui/platform_window/wm/wm_move_loop_handler.h" #include "ui/platform_window/wm/wm_move_resize_handler.h" @@ -19,7 +18,6 @@ class WaylandToplevelWindow : public WaylandWindow, public WmMoveResizeHandler, - public WmDragHandler, public WmMoveLoopHandler, public WaylandExtension { public: @@ -40,14 +38,6 @@ int hittest, const gfx::Point& pointer_location_in_px) override; - // WmDragHandler - bool StartDrag(const ui::OSExchangeData& data, - int operation, - gfx::NativeCursor cursor, - bool can_grab_pointer, - WmDragHandler::Delegate* delegate) override; - void CancelDrag() override; - // PlatformWindow void Show(bool inactive) override; void Hide() override; @@ -72,13 +62,6 @@ bool is_maximized, bool is_fullscreen, bool is_activated) override; - void OnDragEnter(const gfx::PointF& point, - std::unique_ptr<OSExchangeData> data, - int operation) override; - int OnDragMotion(const gfx::PointF& point, int operation) override; - void OnDragDrop() override; - void OnDragLeave() override; - void OnDragSessionClose(uint32_t dnd_action) override; bool OnInitialize(PlatformWindowInitProperties properties) override; bool IsActive() const override; @@ -113,8 +96,6 @@ // Wrappers around shell surface. std::unique_ptr<ShellSurfaceWrapper> shell_surface_; - WmDragHandler::Delegate* drag_handler_delegate_ = nullptr; - // These bounds attributes below have suffices that indicate units used. // Wayland operates in DIP but the platform operates in physical pixels so // our WaylandToplevelWindow is the link that has to translate the units. See @@ -153,8 +134,6 @@ base::Optional<gfx::Size> min_size_; base::Optional<gfx::Size> max_size_; - base::OnceClosure drag_loop_quit_closure_; - wl::Object<zaura_surface> aura_surface_; // When use_native_frame is false, client-side decoration is set, @@ -162,8 +141,6 @@ // When use_native_frame is true, server-side decoration is set, // e.g. lacros-taskmanager. bool use_native_frame_ = false; - - base::WeakPtrFactory<WaylandToplevelWindow> weak_ptr_factory_{this}; }; } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc index 69d11bf..f14adef 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -8,24 +8,32 @@ #include <memory> #include "base/bind.h" +#include "base/run_loop.h" #include "build/chromeos_buildflags.h" #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h" +#include "ui/base/dragdrop/drag_drop_types.h" +#include "ui/base/dragdrop/os_exchange_data.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/ozone/events_ozone.h" #include "ui/events/platform/platform_event_source.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/native_widget_types.h" #include "ui/ozone/common/features.h" #include "ui/ozone/platform/wayland/common/wayland_util.h" #include "ui/ozone/platform/wayland/host/wayland_buffer_manager_host.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" #include "ui/ozone/platform/wayland/host/wayland_cursor_position.h" +#include "ui/ozone/platform/wayland/host/wayland_data_drag_controller.h" +#include "ui/ozone/platform/wayland/host/wayland_event_source.h" #include "ui/ozone/platform/wayland/host/wayland_output_manager.h" #include "ui/ozone/platform/wayland/host/wayland_pointer.h" #include "ui/ozone/platform/wayland/host/wayland_subsurface.h" #include "ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.h" #include "ui/ozone/public/mojom/wayland/wayland_overlay_config.mojom.h" +#include "ui/platform_window/wm/wm_drag_handler.h" +#include "ui/platform_window/wm/wm_drop_handler.h" namespace { @@ -45,7 +53,10 @@ connection_(connection), wayland_overlay_delegation_enabled_(IsWaylandOverlayDelegationEnabled()), accelerated_widget_( - connection->wayland_window_manager()->AllocateAcceleratedWidget()) {} + connection->wayland_window_manager()->AllocateAcceleratedWidget()) { + // Set a class property key, which allows |this| to be used for drag action. + SetWmDragHandler(this, this); +} WaylandWindow::~WaylandWindow() { shutting_down_ = true; @@ -65,6 +76,12 @@ if (parent_window_) parent_window_->set_child_window(nullptr); + + if (drag_handler_delegate_) { + drag_handler_delegate_->OnDragFinished( + DragDropTypes::DragOperation::DRAG_NONE); + } + CancelDrag(); } void WaylandWindow::OnWindowLostCapture() { @@ -124,6 +141,31 @@ } } +bool WaylandWindow::StartDrag(const ui::OSExchangeData& data, + int operation, + gfx::NativeCursor cursor, + bool can_grab_pointer, + WmDragHandler::Delegate* delegate) { + DCHECK(!drag_handler_delegate_); + drag_handler_delegate_ = delegate; + connection()->data_drag_controller()->StartSession(data, operation); + + base::RunLoop drag_loop(base::RunLoop::Type::kNestableTasksAllowed); + drag_loop_quit_closure_ = drag_loop.QuitClosure(); + + auto alive = weak_ptr_factory_.GetWeakPtr(); + drag_loop.Run(); + if (!alive) + return false; + return true; +} + +void WaylandWindow::CancelDrag() { + if (drag_loop_quit_closure_.is_null()) + return; + std::move(drag_loop_quit_closure_).Run(); +} + void WaylandWindow::Show(bool inactive) { if (background_buffer_id_ != 0u) should_attach_background_buffer_ = true; @@ -354,17 +396,58 @@ void WaylandWindow::OnDragEnter(const gfx::PointF& point, std::unique_ptr<OSExchangeData> data, - int operation) {} + int operation) { + WmDropHandler* drop_handler = GetWmDropHandler(*this); + if (!drop_handler) + return; -int WaylandWindow::OnDragMotion(const gfx::PointF& point, int operation) { - return -1; + auto location_px = gfx::ScalePoint(TranslateLocationToRootWindow(point), + buffer_scale(), buffer_scale()); + + // Wayland sends locations in DIP so they need to be translated to + // physical pixels. + // TODO(crbug.com/1102857): get the real event modifier here. + drop_handler->OnDragEnter(location_px, std::move(data), operation, + /*modifiers=*/0); } -void WaylandWindow::OnDragDrop() {} +int WaylandWindow::OnDragMotion(const gfx::PointF& point, int operation) { + WmDropHandler* drop_handler = GetWmDropHandler(*this); + if (!drop_handler) + return 0; -void WaylandWindow::OnDragLeave() {} + auto location_px = gfx::ScalePoint(TranslateLocationToRootWindow(point), + buffer_scale(), buffer_scale()); -void WaylandWindow::OnDragSessionClose(uint32_t dnd_action) {} + // Wayland sends locations in DIP so they need to be translated to + // physical pixels. + // TODO(crbug.com/1102857): get the real event modifier here. + return drop_handler->OnDragMotion(location_px, operation, + /*modifiers=*/0); +} + +void WaylandWindow::OnDragDrop() { + WmDropHandler* drop_handler = GetWmDropHandler(*this); + if (!drop_handler) + return; + // TODO(crbug.com/1102857): get the real event modifier here. + drop_handler->OnDragDrop({}, /*modifiers=*/0); +} + +void WaylandWindow::OnDragLeave() { + WmDropHandler* drop_handler = GetWmDropHandler(*this); + if (!drop_handler) + return; + drop_handler->OnDragLeave(); +} + +void WaylandWindow::OnDragSessionClose(uint32_t dnd_action) { + DCHECK(drag_handler_delegate_); + drag_handler_delegate_->OnDragFinished(dnd_action); + drag_handler_delegate_ = nullptr; + connection()->event_source()->ResetPointerFlags(); + std::move(drag_loop_quit_closure_).Run(); +} void WaylandWindow::SetBoundsDip(const gfx::Rect& bounds_dip) { SetBounds(gfx::ScaleToRoundedRect(bounds_dip, buffer_scale())); @@ -482,8 +565,16 @@ } } -WaylandWindow* WaylandWindow::GetTopLevelWindow() { - return parent_window_ ? parent_window_->GetTopLevelWindow() : this; +gfx::PointF WaylandWindow::TranslateLocationToRootWindow( + const gfx::PointF& location) { + auto* root_window = GetRootParentWindow(); + DCHECK(root_window); + if (root_window == this) + return location; + + gfx::Vector2d offset = + GetBounds().origin() - root_window->GetBounds().origin(); + return location + gfx::Vector2dF(offset); } WaylandWindow* WaylandWindow::GetTopMostChildWindow() {
diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h index 860ca85d..4e0a01c 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.h +++ b/ui/ozone/platform/wayland/host/wayland_window.h
@@ -15,6 +15,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "ui/events/platform/platform_event_dispatcher.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" @@ -23,10 +24,7 @@ #include "ui/platform_window/platform_window.h" #include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/platform_window_init_properties.h" - -namespace gfx { -class PointF; -} +#include "ui/platform_window/wm/wm_drag_handler.h" namespace ui { @@ -38,7 +36,9 @@ using WidgetSubsurfaceSet = base::flat_set<std::unique_ptr<WaylandSubsurface>>; -class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher { +class WaylandWindow : public PlatformWindow, + public PlatformEventDispatcher, + public WmDragHandler { public: ~WaylandWindow() override; @@ -111,6 +111,14 @@ // Returns current type of the window. PlatformWindowType type() const { return type_; } + // WmDragHandler + bool StartDrag(const ui::OSExchangeData& data, + int operation, + gfx::NativeCursor cursor, + bool can_grab_pointer, + WmDragHandler::Delegate* delegate) override; + void CancelDrag() override; + // PlatformWindow void Show(bool inactive) override; void Hide() override; @@ -211,7 +219,7 @@ void UpdateCursorPositionFromEvent(std::unique_ptr<Event> event); - WaylandWindow* GetTopLevelWindow(); + gfx::PointF TranslateLocationToRootWindow(const gfx::PointF& location); uint32_t DispatchEventToDelegate(const PlatformEvent& native_event); @@ -288,6 +296,12 @@ // AcceleratedWidget for this window. This will be unique even over time. gfx::AcceleratedWidget accelerated_widget_; + WmDragHandler::Delegate* drag_handler_delegate_ = nullptr; + + base::OnceClosure drag_loop_quit_closure_; + + base::WeakPtrFactory<WaylandWindow> weak_ptr_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(WaylandWindow); };
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc index 937da975..aa9197b 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -1511,29 +1511,26 @@ ZXDG_POSITIONER_V6_ANCHOR_BOTTOM | ZXDG_POSITIONER_V6_ANCHOR_RIGHT, ZXDG_POSITIONER_V6_GRAVITY_BOTTOM | ZXDG_POSITIONER_V6_GRAVITY_RIGHT, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y}; + ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y}; nested_menu_window_positioner = { gfx::Rect(4, 80, 279, 1), gfx::Size(305, 99), ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_RIGHT, ZXDG_POSITIONER_V6_GRAVITY_BOTTOM | ZXDG_POSITIONER_V6_GRAVITY_RIGHT, ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y}; + ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y}; } else { - menu_window_positioner = { - gfx::Rect(439, 46, 1, 30), gfx::Size(287, 409), - XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT, - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y}; + menu_window_positioner = {gfx::Rect(439, 46, 1, 30), gfx::Size(287, 409), + XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT, + XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT, + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y}; + nested_menu_window_positioner = { gfx::Rect(4, 80, 279, 1), gfx::Size(305, 99), XDG_POSITIONER_ANCHOR_TOP_RIGHT, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT, XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y}; + XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y}; } auto* toplevel_window = window_.get();
diff --git a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc index 356de27..cee4e46 100644 --- a/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc +++ b/ui/ozone/platform/wayland/host/xdg_popup_wrapper_impl.cc
@@ -236,19 +236,17 @@ switch (menu_type) { case MenuType::TYPE_RIGHT_CLICK: - constraint = - WlConstraintAdjustment::SlideX | WlConstraintAdjustment::SlideY | - WlConstraintAdjustment::FlipY | WlConstraintAdjustment::ResizeY; + constraint = WlConstraintAdjustment::SlideX | + WlConstraintAdjustment::SlideY | + WlConstraintAdjustment::FlipY; break; case MenuType::TYPE_3DOT_PARENT_MENU: - constraint = WlConstraintAdjustment::SlideX | - WlConstraintAdjustment::FlipY | - WlConstraintAdjustment::ResizeY; + constraint = + WlConstraintAdjustment::SlideX | WlConstraintAdjustment::FlipY; break; case MenuType::TYPE_3DOT_CHILD_MENU: - constraint = WlConstraintAdjustment::SlideY | - WlConstraintAdjustment::FlipX | - WlConstraintAdjustment::ResizeY; + constraint = + WlConstraintAdjustment::SlideY | WlConstraintAdjustment::FlipX; break; case MenuType::TYPE_UNKNOWN: NOTREACHED() << "Unsupported menu type";
diff --git a/ui/views/controls/button/menu_button.h b/ui/views/controls/button/menu_button.h index 44a66ee2..a05b763a 100644 --- a/ui/views/controls/button/menu_button.h +++ b/ui/views/controls/button/menu_button.h
@@ -5,9 +5,10 @@ #ifndef UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_H_ #define UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_H_ -#include "base/macros.h" #include "base/strings/string16.h" #include "ui/views/controls/button/label_button.h" +#include "ui/views/metadata/metadata_header_macros.h" +#include "ui/views/metadata/view_factory.h" namespace views { @@ -23,10 +24,11 @@ class VIEWS_EXPORT MenuButton : public LabelButton { public: METADATA_HEADER(MenuButton); - explicit MenuButton(PressedCallback callback = PressedCallback(), const base::string16& text = base::string16(), int button_context = style::CONTEXT_BUTTON); + MenuButton(const MenuButton&) = delete; + MenuButton& operator=(const MenuButton&) = delete; ~MenuButton() override; MenuButtonController* button_controller() const { @@ -41,10 +43,13 @@ private: MenuButtonController* menu_button_controller_; - - DISALLOW_COPY_AND_ASSIGN(MenuButton); }; +BEGIN_VIEW_BUILDER(VIEWS_EXPORT, MenuButton, LabelButton) +END_VIEW_BUILDER + } // namespace views +DEFINE_VIEW_BUILDER(VIEWS_EXPORT, MenuButton) + #endif // UI_VIEWS_CONTROLS_BUTTON_MENU_BUTTON_H_
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc index c5cdb51..0381eb3 100644 --- a/ui/views/controls/label.cc +++ b/ui/views/controls/label.cc
@@ -152,6 +152,23 @@ OnPropertyChanged(&text_style_, kPropertyEffectsPreferredSizeChanged); } +void Label::SetTextStyleRange(int style, const gfx::Range& range) { + if (style == text_style_ || !range.IsValid() || range.is_empty() || + !gfx::Range(0, GetText().size()).Contains(range)) + return; + + const auto details = style::GetFontDetails(text_context_, style); + // This function is not prepared to handle style requests that vary by + // anything other than weight. + DCHECK_EQ(details.typeface, + style::GetFontDetails(text_context_, text_style_).typeface); + DCHECK_EQ(details.size_delta, + style::GetFontDetails(text_context_, text_style_).size_delta); + full_text_->ApplyWeight(details.weight, range); + ClearDisplayText(); + PreferredSizeChanged(); +} + bool Label::GetAutoColorReadabilityEnabled() const { return auto_color_readability_enabled_; } @@ -659,17 +676,13 @@ : elide_behavior_; std::unique_ptr<gfx::RenderText> render_text = - gfx::RenderText::CreateRenderText(); + full_text_->CreateInstanceOfSameStyle(GetText()); render_text->SetHorizontalAlignment(GetHorizontalAlignment()); render_text->SetVerticalAlignment(GetVerticalAlignment()); - render_text->SetDirectionalityMode(full_text_->directionality_mode()); render_text->SetElideBehavior(elide_behavior); render_text->SetObscured(GetObscured()); render_text->SetMinLineHeight(GetLineHeight()); - render_text->SetFontList(font_list()); render_text->set_shadows(GetShadows()); - render_text->SetCursorEnabled(false); - render_text->SetText(GetText()); const bool multiline = GetMultiLine(); render_text->SetMultiline(multiline); render_text->SetMaxLines(multiline ? GetMaxLines() : 0);
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h index 4848b88..2426029 100644 --- a/ui/views/controls/label.h +++ b/ui/views/controls/label.h
@@ -106,6 +106,10 @@ int GetTextStyle() const; void SetTextStyle(int style); + // Applies |style| to a specific |range|. This is unimplemented for styles + // that vary from the global text style by anything besides weight. + void SetTextStyleRange(int style, const gfx::Range& range); + // Enables or disables auto-color-readability (enabled by default). If this // is enabled, then calls to set any foreground or background color will // trigger an automatic mapper that uses color_utils::BlendForMinContrast()
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc index d5aaeaf..7e08774 100644 --- a/ui/views/controls/table/table_view.cc +++ b/ui/views/controls/table/table_view.cc
@@ -267,7 +267,9 @@ } int TableView::GetFirstSelectedRow() const { - return selection_model_.empty() ? -1 : selection_model_.selected_indices()[0]; + return selection_model_.empty() + ? -1 + : *selection_model_.selected_indices().begin(); } void TableView::SetColumnVisibility(int id, bool is_visible) {
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc index 3445cbcd..a40a32e 100644 --- a/ui/views/controls/table/table_view_unittest.cc +++ b/ui/views/controls/table/table_view_unittest.cc
@@ -471,10 +471,14 @@ " selection="; const ui::ListSelectionModel::SelectedIndices& selection( model.selected_indices()); - for (size_t i = 0; i < selection.size(); ++i) { - if (i != 0) + bool first = true; + for (int index : selection) { + if (first) { + first = false; + } else { result += " "; - result += base::NumberToString(selection[i]); + } + result += base::NumberToString(index); } return result; }
diff --git a/ui/views/layout/layout_manager.h b/ui/views/layout/layout_manager.h index 5ff7e10..22a3a60 100644 --- a/ui/views/layout/layout_manager.h +++ b/ui/views/layout/layout_manager.h
@@ -91,7 +91,7 @@ protected: // Sets the visibility of a view without triggering ViewVisibilitySet(). - // During Layout(), use this method instead of View::SetVisibility(). + // During Layout(), use this method instead of View::SetVisible(). void SetViewVisibility(View* view, bool visible); // Gets the child views of the specified view in paint order (reverse
diff --git a/ui/views/layout/layout_manager_base.h b/ui/views/layout/layout_manager_base.h index 8812cb5..7982811e 100644 --- a/ui/views/layout/layout_manager_base.h +++ b/ui/views/layout/layout_manager_base.h
@@ -106,7 +106,7 @@ // Returns whether the specified child view can be visible. To be able to be // visible, |child| must be a child of the host view, and must have been - // visible when it was added or most recently had GetVisible(true) called on + // visible when it was added or most recently had SetVisible(true) called on // it by non-layout code. bool CanBeVisible(const View* child) const;
diff --git a/ui/views/view.cc b/ui/views/view.cc index 2e1850f14..b6dd5a1 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -56,6 +56,7 @@ #include "ui/views/controls/scroll_view.h" #include "ui/views/drag_controller.h" #include "ui/views/metadata/metadata_impl_macros.h" +#include "ui/views/view_class_properties.h" #include "ui/views/view_observer.h" #include "ui/views/view_tracker.h" #include "ui/views/views_features.h" @@ -3125,14 +3126,18 @@ void View::DefaultFillLayout::Layout(View* host) { const gfx::Rect contents_bounds = host->GetContentsBounds(); - for (auto* child : host->children()) - child->SetBoundsRect(contents_bounds); + for (auto* child : host->children()) { + if (!child->GetProperty(kViewIgnoredByLayoutKey)) + child->SetBoundsRect(contents_bounds); + } } gfx::Size View::DefaultFillLayout::GetPreferredSize(const View* host) const { gfx::Size preferred_size; - for (auto* child : host->children()) - preferred_size.SetToMax(child->GetPreferredSize()); + for (auto* child : host->children()) { + if (!child->GetProperty(kViewIgnoredByLayoutKey)) + preferred_size.SetToMax(child->GetPreferredSize()); + } return preferred_size; } @@ -3140,10 +3145,13 @@ int width) const { const gfx::Insets insets = host->GetInsets(); int preferred_height = 0; - for (auto* child : host->children()) - preferred_height = std::max( - preferred_height, - child->GetHeightForWidth(width - insets.width()) + insets.height()); + for (auto* child : host->children()) { + if (!child->GetProperty(kViewIgnoredByLayoutKey)) { + preferred_height = std::max( + preferred_height, + child->GetHeightForWidth(width - insets.width()) + insets.height()); + } + } return preferred_height; }
diff --git a/ui/views/view_class_properties.cc b/ui/views/view_class_properties.cc index a2799b0..1335c4d3 100644 --- a/ui/views/view_class_properties.cc +++ b/ui/views/view_class_properties.cc
@@ -41,5 +41,6 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(LayoutAlignment, kCrossAxisAlignmentKey, nullptr) +DEFINE_UI_CLASS_PROPERTY_KEY(bool, kViewIgnoredByLayoutKey, false) } // namespace views
diff --git a/ui/views/view_class_properties.h b/ui/views/view_class_properties.h index bf7abfd..260742d4 100644 --- a/ui/views/view_class_properties.h +++ b/ui/views/view_class_properties.h
@@ -58,6 +58,12 @@ VIEWS_EXPORT extern const ui::ClassProperty<LayoutAlignment*>* const kCrossAxisAlignmentKey; +// Property indicating whether a view should be ignored by a layout. Supported +// by View::DefaultFillLayout. +// TODO(kylixrd): Revisit using for FillLayout. +VIEWS_EXPORT extern const ui::ClassProperty<bool>* const + kViewIgnoredByLayoutKey; + } // namespace views // Declaring the template specialization here to make sure that the
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc index 9f5dff10..ede9124 100644 --- a/ui/views/widget/native_widget_aura.cc +++ b/ui/views/widget/native_widget_aura.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/location.h" #include "base/single_thread_task_runner.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -171,6 +172,14 @@ *params.corner_radius); } window_->SetProperty(aura::client::kShowStateKey, params.show_state); + + int desk_index; + // Set workspace property of this window created with a specified workspace + // in InitParams. The desk index can be kActiveWorkspace=-1, representing + // an active desk. + if (base::StringToInt(params.workspace, &desk_index)) + window_->SetProperty(aura::client::kWindowWorkspaceKey, desk_index); + if (params.type == Widget::InitParams::TYPE_BUBBLE) wm::SetHideOnDeactivate(window_, true); window_->SetTransparent(params.opacity == @@ -491,7 +500,10 @@ } std::string NativeWidgetAura::GetWorkspace() const { - return std::string(); + int desk_index = window_->GetProperty(aura::client::kWindowWorkspaceKey); + return desk_index == aura::client::kUnassignedWorkspace + ? std::string() + : base::NumberToString(desk_index); } void NativeWidgetAura::SetBounds(const gfx::Rect& bounds) { @@ -955,6 +967,9 @@ intptr_t old) { if (key == aura::client::kShowStateKey) delegate_->OnNativeWidgetWindowShowStateChanged(); + + if (key == aura::client::kWindowWorkspaceKey) + delegate_->OnNativeWidgetWorkspaceChanged(); } void NativeWidgetAura::OnResizeLoopStarted(aura::Window* window) {
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc index c97bf189..6960fd33 100644 --- a/ui/views/widget/root_view.cc +++ b/ui/views/widget/root_view.cc
@@ -22,8 +22,8 @@ #include "ui/events/keycodes/keyboard_codes.h" #include "ui/gfx/canvas.h" #include "ui/views/drag_controller.h" -#include "ui/views/layout/fill_layout.h" #include "ui/views/metadata/metadata_impl_macros.h" +#include "ui/views/view_class_properties.h" #include "ui/views/view_targeter.h" #include "ui/views/widget/root_view_targeter.h" #include "ui/views/widget/widget.h" @@ -210,7 +210,7 @@ << "Can't be called until after the native widget is created!"; // The ContentsView must be set up _after_ the window is created so that its // Widget pointer is valid. - SetLayoutManager(std::make_unique<FillLayout>()); + SetUseDefaultFillLayout(true); if (!children().empty()) RemoveAllChildViews(true); AddChildView(contents_view); @@ -268,8 +268,7 @@ DCHECK(GetContentsView()); if (!announce_view_) { announce_view_ = AddChildView(std::make_unique<AnnounceTextView>()); - static_cast<FillLayout*>(GetLayoutManager()) - ->SetChildViewIgnoredByLayout(announce_view_, true); + announce_view_->SetProperty(kViewIgnoredByLayoutKey, true); } announce_view_->Announce(text); #endif
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java index f7558ae..b7385f69 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/BrowserFragmentLifecycleTest.java
@@ -215,7 +215,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void restoresTabData() throws Throwable { Bundle extras = new Bundle(); extras.putString(InstrumentationActivity.EXTRA_PERSISTENCE_ID, "x"); @@ -227,7 +226,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void restoreTabDataAfterRecreate() throws Throwable { Map<String, String> initialData = new HashMap<>(); initialData.put("foo", "bar"); @@ -255,7 +253,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void getAndRemoveBrowserPersistenceIds() throws Throwable { // Creates a browser with the persistence id 'x'. final String persistenceId = "x"; @@ -387,7 +384,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void twoFragmentsDifferentIncognitoProfiles() throws Throwable { // This test creates two browsers with different profile names and persistence ids. final String persistenceId1 = "x"; @@ -467,7 +463,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void twoFragmentsSameIncognitoProfile() throws Throwable { // This test creates two browsers with the same profile, but different persistence ids. final String persistenceId1 = "x";
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/CookieManagerTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/CookieManagerTest.java index 1afabe3..3b27c24 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/CookieManagerTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/CookieManagerTest.java
@@ -47,7 +47,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testSetCookie() throws Exception { Assert.assertTrue(setCookie("foo=bar")); @@ -59,7 +58,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testSetCookieInvalid() throws Exception { TestThreadUtils.runOnUiThreadBlocking(() -> { try { @@ -73,7 +71,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testSetCookieNotSet() throws Exception { // Attempting to set a Secure cookie from an insecure origin is rejected. // A different hostname must be used because non-cryptographic localhost origins such as @@ -84,7 +81,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testSetCookieNullCallback() throws Exception { TestThreadUtils.runOnUiThreadBlocking( () -> { mCookieManager.setCookie(mBaseUri, "foo=bar", null); }); @@ -100,7 +96,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testGetCookie() throws Exception { Assert.assertEquals(getCookie(), ""); Assert.assertTrue(setCookie("foo=")); @@ -111,7 +106,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testCookieChanged() throws Exception { CookieChangedCallbackHelper helper = new CookieChangedCallbackHelper(); TestThreadUtils.runOnUiThreadBlocking( @@ -132,7 +126,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testCookieChangedRemoveCallback() throws Exception { CookieChangedCallbackHelper helper = new CookieChangedCallbackHelper(); Runnable remove = TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -155,7 +148,6 @@ @Test @SmallTest - @MinWebLayerVersion(83) public void testCookieChangedRemoveCallbackAfterProfileDestroyed() throws Exception { // Removing change callback should be a no-op after the profile is destroyed. TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DisplayCutoutTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DisplayCutoutTest.java index 5bccfa5..fa08542d 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DisplayCutoutTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DisplayCutoutTest.java
@@ -39,7 +39,6 @@ Assert.assertNotNull(mActivity); } - @MinWebLayerVersion(86) @Test @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.P) @@ -62,7 +61,6 @@ }); } - @MinWebLayerVersion(86) @Test @SmallTest @MinAndroidSdkLevel(Build.VERSION_CODES.P)
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java index 162ae09..5470b35f 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/DownloadCallbackTest.java
@@ -31,7 +31,6 @@ import org.chromium.weblayer.Profile; import org.chromium.weblayer.Tab; import org.chromium.weblayer.TabListCallback; -import org.chromium.weblayer.WebLayer; import org.chromium.weblayer.shell.InstrumentationActivity; import java.io.File; @@ -47,8 +46,6 @@ public InstrumentationActivityTestRule mActivityTestRule = new InstrumentationActivityTestRule(); - private static boolean sIsFileNameSupported; - private InstrumentationActivity mActivity; private Callback mCallback; @@ -94,9 +91,7 @@ public void onDownloadCompleted(Download download) { mSeenCompleted = true; mLocation = download.getLocation().toString(); - if (sIsFileNameSupported) { - mFileName = download.getFileNameToReportToUser().toString(); - } + mFileName = download.getFileNameToReportToUser().toString(); mState = download.getState(); mError = download.getError(); mMimetype = download.getMimeType(); @@ -142,9 +137,6 @@ Profile profile = mActivity.getBrowser().getProfile(); profile.setDownloadCallback(mCallback); profile.setDownloadDirectory(new File(tempDownloadDirectory)); - - sIsFileNameSupported = - WebLayer.getSupportedMajorVersion(mActivity.getApplicationContext()) >= 86; }); } @@ -188,7 +180,6 @@ */ @Test @SmallTest - @MinWebLayerVersion(86) // Behavior landed in 86. public void testFirstNavigationIsDownloadClosesTab() throws Throwable { // Set up listening for the tab removal that we expect to happen. CallbackHelper onTabRemovedCallbackHelper = new CallbackHelper(); @@ -251,9 +242,7 @@ Assert.assertTrue(mCallback.mLocation.contains( "org.chromium.weblayer.shell/cache/weblayer/Downloads/")); - if (sIsFileNameSupported) { - Assert.assertTrue(mCallback.mFileName.contains("test")); - } + Assert.assertTrue(mCallback.mFileName.contains("test")); Assert.assertEquals(DownloadState.COMPLETE, mCallback.mState); Assert.assertEquals(DownloadError.NO_ERROR, mCallback.mError); Assert.assertEquals("text/html", mCallback.mMimetype);
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ErrorPageCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ErrorPageCallbackTest.java index 78d8ed76..941231c0 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ErrorPageCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ErrorPageCallbackTest.java
@@ -149,7 +149,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testOverrideErrorPage() throws Throwable { mCallback.mErrorPage = new ErrorPage("<html><head><title>test error</title>"); TestThreadUtils.runOnUiThreadBlocking(
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java index 392038b8..ac59040 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ExternalNavigationTest.java
@@ -740,7 +740,6 @@ */ @Test @SmallTest - @MinWebLayerVersion(87) public void testDisableIntentProcessing() throws Throwable { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(ABOUT_BLANK_URL); IntentInterceptor intentInterceptor = new IntentInterceptor();
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FaviconFetcherTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FaviconFetcherTest.java index b19653f9..4f96547 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FaviconFetcherTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FaviconFetcherTest.java
@@ -30,7 +30,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testFaviconFetcher() throws Exception { mActivity = mActivityTestRule.launchShellWithUrl("about:blank");
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FindInPageTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FindInPageTest.java index 73aea7a..ae97689 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FindInPageTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FindInPageTest.java
@@ -128,7 +128,6 @@ @Test @SmallTest - @MinWebLayerVersion(82) public void testHideOnNavigate() { setUp("shakespeare.html");
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenSizeTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenSizeTest.java index ce5aeaf..0d997bc9 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenSizeTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenSizeTest.java
@@ -35,7 +35,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testOsk() { // For this test to function, it *cannot* use {@link TestFullscreenCallback}, as that // overrides the fullscreen handling in {@link InstrumentationActivity}.
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GoogleAccountsTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GoogleAccountsTest.java index 2028013d..2646935f 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GoogleAccountsTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/GoogleAccountsTest.java
@@ -48,7 +48,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testBasic() throws Exception { GoogleAccountsCallbackImpl callback = new GoogleAccountsCallbackImpl(); TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -65,7 +64,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testRequestHeader() throws Exception { GoogleAccountsCallbackImpl callback = new GoogleAccountsCallbackImpl(); TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java index e3f37cf..c0247968 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/InstrumentationActivityTestRule.java
@@ -140,14 +140,6 @@ (new NavigationWaiter(url, tab, true /* expectFailure */, waitForPaint)).navigateAndWait(); } - /** - * Recreates the Activity, blocking until finished. - * After calling this, getActivity() returns the new Activity. - */ - public void recreateActivity() { - setActivity(ApplicationTestUtils.recreateActivity(getActivity())); - } - public void recreateByRotatingToLandscape() { setActivity(ApplicationTestUtils.waitForActivityWithClass( InstrumentationActivity.class, Stage.RESUMED, () -> {
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java index ca4eba2..7aafd3f 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java
@@ -16,7 +16,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; -import android.support.test.InstrumentationRegistry; import android.webkit.WebResourceResponse; import androidx.fragment.app.Fragment; @@ -24,7 +23,6 @@ import org.hamcrest.Matchers; import org.junit.Assert; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -45,7 +43,6 @@ import org.chromium.weblayer.Tab; import org.chromium.weblayer.TabCallback; import org.chromium.weblayer.TabListCallback; -import org.chromium.weblayer.WebLayer; import org.chromium.weblayer.shell.InstrumentationActivity; import java.io.ByteArrayInputStream; @@ -85,8 +82,6 @@ private static final String INTENT_TO_CHROME_URL = "intent://play.google.com/store/apps/details?id=com.facebook.katana/#Intent;scheme=https;action=android.intent.action.VIEW;package=com.android.chrome;end"; - private static boolean sShouldTrackPageInitiated; - // An IntentInterceptor that simply drops intents to ensure that intent launches don't interfere // with running of tests. private class IntentInterceptor implements InstrumentationActivity.IntentInterceptor { @@ -115,10 +110,8 @@ mLoadError = navigation.getLoadError(); mNavigationState = navigation.getState(); mIsKnownProtocol = navigation.isKnownProtocol(); + mIsPageInitiatedNavigation = navigation.isPageInitiated(); mIsServedFromBackForwardCache = navigation.isServedFromBackForwardCache(); - if (sShouldTrackPageInitiated) { - mIsPageInitiatedNavigation = navigation.isPageInitiated(); - } notifyCalled(); } @@ -165,7 +158,6 @@ } public boolean isPageInitiated() { - assert sShouldTrackPageInitiated; return mIsPageInitiatedNavigation; } } @@ -319,16 +311,6 @@ private final Callback mCallback = new Callback(); - @Before - public void setUp() throws Throwable { - TestThreadUtils.runOnUiThreadBlocking(() -> { - sShouldTrackPageInitiated = - WebLayer.getSupportedMajorVersion( - InstrumentationRegistry.getTargetContext().getApplicationContext()) - >= 86; - }); - } - @Test @SmallTest public void testNavigationEvents() throws Exception { @@ -350,7 +332,6 @@ assertEquals(mCallback.onCompletedCallback.getHttpStatusCode(), 200); } - @MinWebLayerVersion(85) @Test @SmallTest public void testOldPageNoLongerRendered() throws Exception { @@ -887,7 +868,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testSetUserAgentString() throws Exception { TestWebServer testServer = TestWebServer.start(); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(null); @@ -969,7 +949,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void testSkippedNavigationEntry() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); setNavigationCallback(activity); @@ -996,7 +975,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void testIndexOutOfBounds() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(null); runOnUiThreadBlocking(() -> { @@ -1022,7 +1000,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testPageInitiated() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(null); setNavigationCallback(activity); @@ -1036,7 +1013,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testPageInitiatedFromClient() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); setNavigationCallback(activity); @@ -1052,7 +1028,6 @@ // This is a regression test for https://crbug.com/1121388. @Test @SmallTest - @MinWebLayerVersion(85) public void testDestroyTabWithModalDialog() throws Exception { // Load a page with a form. InstrumentationActivity activity = @@ -1105,7 +1080,6 @@ */ @Test @SmallTest - @MinWebLayerVersion(86) public void testDestroyTabInNavigationFailed() throws Throwable { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(null); CallbackHelper callbackHelper = new CallbackHelper(); @@ -1155,7 +1129,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testWebResponse() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); // The code asserts that when InputStreams are used that the stock URL bar is not visible. @@ -1168,7 +1141,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testWebResponseMimeSniff() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); }); @@ -1180,7 +1152,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testWebResponseNoCacheControl() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); }); @@ -1198,7 +1169,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testWebResponseCached() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); }); @@ -1218,7 +1188,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testWebResponseCachedWithSniffedMimeType() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); }); @@ -1238,7 +1207,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testWebResponseNoStore() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); }); @@ -1256,7 +1224,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testWebResponseExpired() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(URL1); TestThreadUtils.runOnUiThreadBlocking(() -> { activity.getBrowser().setTopView(null); });
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PageInfoTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PageInfoTest.java index 9a5fad0..a374938 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PageInfoTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PageInfoTest.java
@@ -36,7 +36,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testPageInfoLaunches() { Bundle extras = new Bundle(); extras.putBoolean(InstrumentationActivity.EXTRA_URLBAR_TEXT_CLICKABLE, false); @@ -64,7 +63,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) public void testSingleTappableContainer() { Bundle extras = new Bundle(); extras.putBoolean(InstrumentationActivity.EXTRA_URLBAR_TEXT_CLICKABLE, true);
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PrerenderControllerTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PrerenderControllerTest.java index e01b7e5b..3d4c005 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PrerenderControllerTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/PrerenderControllerTest.java
@@ -53,7 +53,6 @@ @Test @SmallTest @Feature({"WebLayer"}) - @MinWebLayerVersion(87) public void testAddingPrerender() throws Exception { TestWebServer testServer = TestWebServer.start(); testServer.setRequestHandler(mRequestHandler);
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java index 006ee2c..7fea2f0a 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ProfileTest.java
@@ -91,7 +91,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testDestroyAndDeleteDataFromDiskSoonWhenInUse() throws Exception { WebLayer weblayer = mActivityTestRule.getWebLayer(); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank"); @@ -263,7 +262,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testMultipleIncognitoProfiles() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank");
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ScrollOffsetCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ScrollOffsetCallbackTest.java index efe11f35..6427f630 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ScrollOffsetCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/ScrollOffsetCallbackTest.java
@@ -30,7 +30,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testBasic() throws Throwable { final String url = mActivityTestRule.getTestDataURL("tall_page.html"); InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(url);
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SiteSettingsTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SiteSettingsTest.java index 4f42a67..6fca5ff 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SiteSettingsTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/SiteSettingsTest.java
@@ -46,7 +46,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testSiteSettingsLaunches() throws InterruptedException { mSettingsTestRule.launchActivity( SiteSettingsActivity.createIntentForSiteSettingsCategoryList( @@ -57,7 +56,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testAllSitesLaunches() throws InterruptedException { mSettingsTestRule.launchActivity( SiteSettingsActivity.createIntentForSiteSettingsCategoryList( @@ -71,7 +69,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testJavascriptExceptionPopupLaunches() throws InterruptedException { mSettingsTestRule.launchActivity( SiteSettingsActivity.createIntentForSiteSettingsCategoryList( @@ -85,7 +82,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testSingleSiteSoundPopupLaunches() throws InterruptedException { mSettingsTestRule.launchActivity(SettingsTestUtils.createIntentForSiteSettingsSingleWebsite( mSettingsTestRule.getContext(), PROFILE_NAME, /*isIncognito=*/false, GOOGLE_URL)); @@ -97,7 +93,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testSingleSiteClearPopupLaunches() throws InterruptedException { mSettingsTestRule.launchActivity(SettingsTestUtils.createIntentForSiteSettingsSingleWebsite( mSettingsTestRule.getContext(), PROFILE_NAME, /*isIncognito=*/false, GOOGLE_URL)); @@ -110,7 +105,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testSingleSiteLocationAccess() throws InterruptedException { try { Intents.init();
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java index 514c26f..44e8f94 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabCallbackTest.java
@@ -111,7 +111,6 @@ return params[0]; } - // Requires implementation M82. @Test @SmallTest public void testShowContextMenu() throws TimeoutException { @@ -121,7 +120,6 @@ Assert.assertEquals("anchor text", params.linkText); } - // Requires implementation M82. @Test @SmallTest public void testShowContextMenuImg() throws TimeoutException { @@ -345,7 +343,6 @@ CriteriaHelper.pollUiThread(() -> Criteria.checkThat(titles[0], Matchers.is("foobar"))); } - @MinWebLayerVersion(85) @Test @SmallTest public void testOnBackgroundColorChanged() throws TimeoutException { @@ -374,7 +371,6 @@ Assert.assertEquals(0xffff0000, (int) backgroundColors[0]); } - @MinWebLayerVersion(85) @Test @SmallTest public void testScrollNotificationDirectionChange() throws TimeoutException {
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java index 3df85f3..e5ead80 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabListCallbackTest.java
@@ -16,7 +16,6 @@ import org.chromium.weblayer.Browser; import org.chromium.weblayer.Tab; import org.chromium.weblayer.TabListCallback; -import org.chromium.weblayer.WebLayer; import org.chromium.weblayer.shell.InstrumentationActivity; import java.util.ArrayList; @@ -186,12 +185,9 @@ browser.registerTabListCallback(new TabListCallback() { @Override public void onTabRemoved(Tab tab) { - if (WebLayer.getSupportedMajorVersion(mActivity) >= 87) { - // |tab| should not be destroyed at this point. getGuid() is a good proxy - // for verifying the tab hasn't been destroyed. Prior to 87 the tab was - // destroyed at this point. - tab.getGuid(); - } + // |tab| should not be destroyed at this point. getGuid() is a good proxy + // for verifying the tab hasn't been destroyed. + tab.getGuid(); callbackHelper.notifyCalled(); } });
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabPrivateTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabPrivateTest.java index 6dbc21d1..8f448c9 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabPrivateTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabPrivateTest.java
@@ -52,7 +52,6 @@ @Test @SmallTest - @MinWebLayerVersion(87) public void testAutoReloadOnBackgroundCrash() throws Exception { InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl("about:blank"); activity.setIgnoreRendererCrashes();
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java index be1fb81..0069f322 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/TabTest.java
@@ -46,7 +46,6 @@ @Test @SmallTest - @MinWebLayerVersion(82) public void testBeforeUnload() { String url = mActivityTestRule.getTestDataURL("before_unload.html"); mActivity = mActivityTestRule.launchShellWithUrl(url); @@ -151,7 +150,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testCaptureScreenShot() throws TimeoutException { String url = mActivityTestRule.getTestDataURL("quadrant_colors.html"); mActivity = mActivityTestRule.launchShellWithUrl(url); @@ -168,7 +166,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void testCaptureScreenShotDoesNotHang() throws TimeoutException { String startupUrl = "about:blank"; mActivity = mActivityTestRule.launchShellWithUrl(startupUrl); @@ -187,7 +184,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void testSetData() { String startupUrl = "about:blank"; mActivity = mActivityTestRule.launchShellWithUrl(startupUrl); @@ -206,7 +202,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void testSetDataMaxSize() { String startupUrl = "about:blank"; mActivity = mActivityTestRule.launchShellWithUrl(startupUrl); @@ -226,7 +221,6 @@ @Test @SmallTest - @MinWebLayerVersion(85) public void testCreateTab() throws Exception { mActivity = mActivityTestRule.launchShellWithUrl("about:blank"); CallbackHelper helper = new CallbackHelper(); @@ -252,7 +246,6 @@ @Test @SmallTest - @MinWebLayerVersion(86) // New behavior added in 86 public void testViewDetachedTabIsInvisible() throws Exception { mActivity = mActivityTestRule.launchShellWithUrl("about:blank");
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerTest.java index e2e9fc1d..71f9395d 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerTest.java
@@ -24,7 +24,6 @@ @Test @SmallTest - @MinWebLayerVersion(84) public void getUserAgentString() { final String userAgent = TestThreadUtils.runOnUiThreadBlockingNoException( () -> { return mActivityTestRule.getWebLayer().getUserAgentString(); });
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebMessageTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebMessageTest.java index c520c8d..3e438914 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebMessageTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebMessageTest.java
@@ -28,7 +28,6 @@ /** * Verifies WebMessage related APIs. */ -@MinWebLayerVersion(85) @RunWith(WebLayerJUnit4ClassRunner.class) public class WebMessageTest { @Rule
diff --git a/weblayer/browser/browser_main_parts_impl.cc b/weblayer/browser/browser_main_parts_impl.cc index 652d2df..c8cf179 100644 --- a/weblayer/browser/browser_main_parts_impl.cc +++ b/weblayer/browser/browser_main_parts_impl.cc
@@ -158,15 +158,6 @@ crash_reporter::InitializeCrashKeys(); - // MediaSession was implemented in M85, and requires both implementation and - // client libraries to be at least that new. The version check has to be in - // the browser process, but the command line flag is automatically propagated - // to renderers. - if (WebLayerFactoryImplAndroid::GetClientMajorVersion() < 85) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - ::switches::kDisableMediaSessionAPI); - } - // WebLayer initializes the MetricsService once consent is determined. // Determining consent is async and potentially slow. VariationsIdsProvider // is responsible for updating the X-Client-Data header. To ensure the header
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java index ef0184f..7b9e155db 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java
@@ -507,7 +507,7 @@ @CalledByNative private void onRestoreCompleted() throws RemoteException { - if (WebLayerFactoryImpl.getClientMajorVersion() >= 87) mClient.onRestoreCompleted(); + mClient.onRestoreCompleted(); } public View getFragmentView() {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java index 1d70425..b5a3d22 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserViewController.java
@@ -303,8 +303,6 @@ } private void onDialogVisibilityChanged(boolean showing) { - if (WebLayerFactoryImpl.getClientMajorVersion() < 82) return; - if (mModalDialogManager.getCurrentType() == ModalDialogType.TAB) { // This shouldn't be called when |mTab| is null and the modal dialog type is TAB. OTOH, // when an app-modal is displayed for a javascript dialog, this method can be called
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ContactsPickerAdapter.java b/weblayer/browser/java/org/chromium/weblayer_private/ContactsPickerAdapter.java index 30f9b9ee6..4872c07 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/ContactsPickerAdapter.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/ContactsPickerAdapter.java
@@ -97,10 +97,6 @@ @Nullable private IUserIdentityCallbackClient getUserIdentityCallback() { - if (WebLayerFactoryImpl.getClientMajorVersion() < 87) { - return null; - } - return BrowserImpl.fromWindowAndroid(mWindowAndroid) .getProfile() .getUserIdentityCallbackClient();
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java index d973245ba..347a551 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/DownloadCallbackProxy.java
@@ -79,11 +79,6 @@ private void continueAllowDownload(String url, String requestMethod, String requestInitiator, long callbackId) throws RemoteException { - if (WebLayerFactoryImpl.getClientMajorVersion() < 81) { - DownloadCallbackProxyJni.get().allowDownload(callbackId, true); - return; - } - if (mClient == null) { DownloadCallbackProxyJni.get().allowDownload(callbackId, true); return;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ErrorPageCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/ErrorPageCallbackProxy.java index f1fd12a..0a6d8b2 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/ErrorPageCallbackProxy.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/ErrorPageCallbackProxy.java
@@ -45,7 +45,6 @@ @CalledByNative private String getErrorPageContent(NavigationImpl navigation) throws RemoteException { - if (WebLayerFactoryImpl.getClientMajorVersion() < 86) return null; return mClient.getErrorPageContent(navigation.getClientNavigation()); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java index 6a2f3e64..917c3d73 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/InterceptNavigationDelegateClientImpl.java
@@ -166,10 +166,6 @@ } static void closeTab(TabImpl tab) { - // Prior to 84 the client was not equipped to handle the case of WebLayer initiating the - // last tab being closed, so we simply short-circuit out here in that case. - if (WebLayerFactoryImpl.getClientMajorVersion() < 84) return; - tab.getBrowser().destroyTab(tab); } }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java index 4b84d66..cd451840 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java
@@ -248,7 +248,6 @@ @CalledByNative private void onOldPageNoLongerRendered(String uri) throws RemoteException { - if (WebLayerFactoryImpl.getClientMajorVersion() < 85) return; mNavigationControllerClient.onOldPageNoLongerRendered(uri); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java index 53bc4bf..4c186cc 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java
@@ -57,7 +57,6 @@ private IUserIdentityCallbackClient mUserIdentityCallbackClient; private List<Intent> mDownloadNotificationIntents = new ArrayList<>(); - // This was added in 87, and is null in any version before that. private IProfileClient mClient; // If non-null, indicates when no browsers reference this Profile the Profile is destroyed. The
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/RemoteFragmentImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/RemoteFragmentImpl.java index 0d21c685..746b5c5 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/RemoteFragmentImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/RemoteFragmentImpl.java
@@ -50,9 +50,6 @@ } public final View getView() { - if (WebLayerFactoryImpl.getClientMajorVersion() < 84) { - return null; - } try { return ObjectWrapper.unwrap(mClient.getView(), View.class); } catch (RemoteException e) { @@ -61,9 +58,6 @@ } public void removeFragmentFromFragmentManager() { - if (WebLayerFactoryImpl.getClientMajorVersion() < 87) { - return; - } try { mClient.removeFragmentFromFragmentManager(); } catch (RemoteException e) { @@ -204,13 +198,6 @@ // IRemoteFragment implementation below. @Override - @Deprecated - public final IObjectWrapper deprecatedHandleOnCreateView() { - StrictModeWorkaround.apply(); - return ObjectWrapper.wrap(onCreateView()); - } - - @Override public final IObjectWrapper handleOnCreateView( IObjectWrapper container, IObjectWrapper savedInstanceState) { StrictModeWorkaround.apply();
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java b/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java index fad37a2..80d858c 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/TabCallbackProxy.java
@@ -44,7 +44,6 @@ @CalledByNative private void onTitleUpdated(String title) throws RemoteException { - if (WebLayerFactoryImpl.getClientMajorVersion() < 83) return; mClient.onTitleUpdated(ObjectWrapper.wrap(title)); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java index e3ae8c07..932712f2 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/TabImpl.java
@@ -60,7 +60,6 @@ import org.chromium.url.GURL; import org.chromium.weblayer_private.interfaces.APICallException; import org.chromium.weblayer_private.interfaces.IContextMenuParams; -import org.chromium.weblayer_private.interfaces.IDownloadCallbackClient; import org.chromium.weblayer_private.interfaces.IErrorPageCallbackClient; import org.chromium.weblayer_private.interfaces.IFaviconFetcher; import org.chromium.weblayer_private.interfaces.IFaviconFetcherClient; @@ -207,27 +206,23 @@ @Override public void onBackgroundColorChanged(int color) { - if (WebLayerFactoryImpl.getClientMajorVersion() >= 85) { - try { - mClient.onBackgroundColorChanged(color); - } catch (RemoteException e) { - throw new APICallException(e); - } + try { + mClient.onBackgroundColorChanged(color); + } catch (RemoteException e) { + throw new APICallException(e); } } @Override protected void onVerticalScrollDirectionChanged( boolean directionUp, float currentScrollRatio) { - if (WebLayerFactoryImpl.getClientMajorVersion() >= 85) { - try { - mClient.onScrollNotification(directionUp - ? ScrollNotificationType.DIRECTION_CHANGED_UP - : ScrollNotificationType.DIRECTION_CHANGED_DOWN, - currentScrollRatio); - } catch (RemoteException e) { - throw new APICallException(e); - } + try { + mClient.onScrollNotification(directionUp + ? ScrollNotificationType.DIRECTION_CHANGED_UP + : ScrollNotificationType.DIRECTION_CHANGED_DOWN, + currentScrollRatio); + } catch (RemoteException e) { + throw new APICallException(e); } } } @@ -311,13 +306,8 @@ // addObserver() calls to observer when added. WebLayerAccessibilityUtil.get().addObserver(mAccessibilityObserver); - // MediaSession only works if the client is new enough. Sadly, passing - // kDisableMediaSessionAPI does not fully disable the API, so a check is also necessary - // before installing this observer. - if (WebLayerFactoryImpl.getClientMajorVersion() >= 85) { - mMediaSessionHelper = new MediaSessionHelper( - mWebContents, MediaSessionManager.createMediaSessionHelperDelegate(this)); - } + mMediaSessionHelper = new MediaSessionHelper( + mWebContents, MediaSessionManager.createMediaSessionHelperDelegate(this)); } private void doInitAfterSettingContainerView() { @@ -548,12 +538,6 @@ } @Override - public void setDownloadCallbackClient(IDownloadCallbackClient client) { - StrictModeWorkaround.apply(); - mProfile.setDownloadCallbackClient(client); - } - - @Override public void setErrorPageCallbackClient(IErrorPageCallbackClient client) { StrictModeWorkaround.apply(); if (client != null) { @@ -915,10 +899,6 @@ @CalledByNative private void handleCloseFromWebContents() throws RemoteException { - // On clients < 84 WebContents-initiated tab closing was delegated to the client; this flow - // should not be used, as the client will not be expecting it. - assert WebLayerFactoryImpl.getClientMajorVersion() >= 84; - if (getBrowser() == null) return; getBrowser().destroyTab(this); } @@ -955,14 +935,12 @@ TabImplJni.get().removeTabFromBrowserBeforeDestroying(mNativeTab); - if (WebLayerFactoryImpl.getClientMajorVersion() >= 84) { - // Notify the client that this instance is being destroyed to prevent it from calling - // back into this object if the embedder mistakenly tries to do so. - try { - mClient.onTabDestroyed(); - } catch (RemoteException e) { - throw new APICallException(e); - } + // Notify the client that this instance is being destroyed to prevent it from calling + // back into this object if the embedder mistakenly tries to do so. + try { + mClient.onTabDestroyed(); + } catch (RemoteException e) { + throw new APICallException(e); } if (mDisplayCutoutController != null) { @@ -1105,7 +1083,6 @@ @CalledByNative private void showContextMenu(ContextMenuParams params, long nativeContextMenuParams) throws RemoteException { - if (WebLayerFactoryImpl.getClientMajorVersion() < 82) return; if (WebLayerFactoryImpl.getClientMajorVersion() < 88) { mClient.showContextMenu(ObjectWrapper.wrap(params.getPageUrl().getSpec()), ObjectWrapper.wrap(nonEmptyOrNull(params.getLinkUrl().getSpec())),
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/UrlBarControllerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/UrlBarControllerImpl.java index 7500f3e4..e400ac0 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/UrlBarControllerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/UrlBarControllerImpl.java
@@ -90,13 +90,6 @@ } @Override - @Deprecated - public IObjectWrapper /* View */ deprecatedCreateUrlBarView(Bundle options) { - return createUrlBarView( - options, /* OnLongClickListener */ null, /* OnLongClickListener */ null); - } - - @Override public IObjectWrapper /* View */ createUrlBarView(Bundle options, @Nullable IObjectWrapper /* OnLongClickListener */ clickListener, @Nullable IObjectWrapper /* OnLongClickListener */ longClickListener) {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java index 7c85555..3ba5374 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java
@@ -50,9 +50,7 @@ @Override public boolean isClientSupported() { StrictModeWorkaround.apply(); - // Client changes were required to support WebLayer in a split. - if (ProductConfig.IS_BUNDLE && WebLayerBundleUtils.IS_WEBLAYER_IN_SPLIT - && sClientMajorVersion < 86) { + if (sClientMajorVersion < WebLayerVersionConstants.MIN_VERSION) { return false; } int implMajorVersion = getImplementationMajorVersion();
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java index 3be26781..a0bd66e 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -412,8 +412,6 @@ if (intent.getAction().startsWith(DownloadImpl.getIntentPrefix())) { DownloadImpl.forwardIntent(context, intent, mProfileManager); - } else if (intent.getAction().startsWith(MediaStreamManager.getIntentPrefix())) { - MediaStreamManager.forwardIntent(intent); } }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java index 67da892..0c9c1bf 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/BrowserFragmentArgs.java
@@ -10,8 +10,6 @@ String PERSISTENCE_ID = "persistence_id"; /** * A boolean value indicating whether the profile is incognito. - * - * @since 87 */ String IS_INCOGNITO = "is_incognito"; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl index e126205..9b3f859 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowser.aidl
@@ -41,7 +41,6 @@ in boolean onlyExpandControlsAtPageTop, in boolean animate) = 12; - // Added in 87. boolean isRestoringPreviousState() = 14; // Added in 88.
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl index e7bbb45..85a2b7d7 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IBrowserClient.aidl
@@ -11,8 +11,6 @@ void onActiveTabChanged(in int activeTabId) = 0; void onTabAdded(in ITab tab) = 1; void onTabRemoved(in int tabId) = 2; - - // Added in 87. IRemoteFragment createMediaRouteDialogFragment() = 3; void onRestoreCompleted() = 5;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownloadCallbackClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownloadCallbackClient.aidl index 682512c2..aee6a61 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownloadCallbackClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IDownloadCallbackClient.aidl
@@ -20,6 +20,5 @@ void downloadProgressChanged(IClientDownload download) = 4; void downloadCompleted(IClientDownload download) = 5; void downloadFailed(IClientDownload download) = 6; - // Removed in 87. - // Intent createIntent() = 7; + // ID 7 was createIntent and was removed in M87. }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl index d035355..00d369b0 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigation.aidl
@@ -30,7 +30,6 @@ boolean wasStopCalled() = 10; - // @since 86 boolean isPageInitiated() = 11; boolean isReload() = 12;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationController.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationController.aidl index dde2663a..d4c563dc 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationController.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationController.aidl
@@ -9,6 +9,7 @@ import org.chromium.weblayer_private.interfaces.NavigateParams; interface INavigationController { + // Deprecated in M89. void navigate(in String uri, in NavigateParams params) = 0; void goBack() = 1; @@ -33,20 +34,17 @@ String getNavigationEntryTitle(in int index) = 11; - // Added in 82, removed in 83. - // void replace(in String uri) = 12; + // ID 12 was replace and was removed in M83. - // Added in 85. boolean isNavigationEntrySkippable(int index) = 13; - // Added in 86. + // Deprecated in M89. void navigate2(in String uri, in boolean shouldReplaceEntry, in boolean disableIntentProcessing, in boolean disableNetworkErrorAutoReload, in boolean enableAutoPlay) = 14; - // Added in 87 INavigateParams createNavigateParams() = 15; void navigate3(in String uri, in INavigateParams params) = 16;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl index 0c3fa33d..3a9f3ce7 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/INavigationControllerClient.aidl
@@ -31,7 +31,6 @@ void onFirstContentfulPaint() = 8; - // Added in M85. void onOldPageNoLongerRendered(in String uri) = 9; // Added in M88.
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IPrerenderController.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IPrerenderController.aidl index b620600..217058f 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IPrerenderController.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IPrerenderController.aidl
@@ -5,6 +5,5 @@ package org.chromium.weblayer_private.interfaces; interface IPrerenderController { - // Since 87 void prerender(in String url) = 0; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl index 5702583..ca9b169e 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl
@@ -21,30 +21,23 @@ void setDownloadDirectory(String directory) = 3; - // Added in Version 82. void destroyAndDeleteDataFromDisk(in IObjectWrapper completionCallback) = 4; - // Added in Version 83. void setDownloadCallbackClient(IDownloadCallbackClient client) = 5; - // Added in Version 83. ICookieManager getCookieManager() = 6; - // Added in Version 84. void setBooleanSetting(int type, boolean value) = 7; boolean getBooleanSetting(int type) = 8; - // Added in Version 85. void getBrowserPersistenceIds(in IObjectWrapper resultCallback) = 9; void removeBrowserPersistenceStorage(in String[] ids, in IObjectWrapper resultCallback) = 10; void prepareForPossibleCrossOriginNavigation() = 11; - // Added in Version 86. void getCachedFaviconForPageUri(in String uri, in IObjectWrapper resultCallback) = 12; - // Added in Version 87. void setUserIdentityCallbackClient(IUserIdentityCallbackClient client) = 13; IPrerenderController getPrerenderController() = 15; boolean isIncognito() = 16;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragment.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragment.aidl index 52c9363..9967f06d 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragment.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragment.aidl
@@ -11,8 +11,7 @@ void handleOnCreate(in IObjectWrapper savedInstanceState) = 0; void handleOnAttach(in IObjectWrapper context) = 1; void handleOnActivityCreated(in IObjectWrapper savedInstanceState) = 2; - // Deprecated in 84, use handleOnCreateView(ViewGroup, Bundle) instead. - IObjectWrapper deprecatedHandleOnCreateView() = 3; + // ID 3 was deprecatedHandleOnCreateView and was removed in M89. void handleOnStart() = 4; void handleOnResume() = 5; void handleOnPause() = 6; @@ -28,7 +27,6 @@ void handleOnRequestPermissionsResult(int requestCode, in String[] permissions, in int[] grantResults) = 13; - // Since 84 IObjectWrapper /* View */ handleOnCreateView(in IObjectWrapper /* ViewGroup */ container, in IObjectWrapper /* Bundle */ savedInstanceState) = 14; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl index ebb86747..e88f1721 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IRemoteFragmentClient.aidl
@@ -32,8 +32,6 @@ in IObjectWrapper options) = 13; boolean shouldShowRequestPermissionRationale(String permission) = 14; void requestPermissions(in String[] permissions, int requestCode) = 15; - // Since 84 IObjectWrapper /* View */ getView() = 16; - // Since 87 void removeFragmentFromFragmentManager() = 17; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl index 03f1d69..064122d 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITab.aidl
@@ -26,8 +26,7 @@ INavigationController createNavigationController(in INavigationControllerClient client) = 1; - // Deprecated, use Profile.setDownloadCallbackClient. - void setDownloadCallbackClient(IDownloadCallbackClient client) = 2; + // ID 2 was setDownloadCallbackClient and was removed in M89. void setErrorPageCallbackClient(IErrorPageCallbackClient client) = 3; @@ -56,10 +55,8 @@ void setMediaCaptureCallbackClient(in IMediaCaptureCallbackClient client) = 14; void stopMediaCapturing() = 15; - // Added in 84 void captureScreenShot(in float scale, in IObjectWrapper resultCallback) = 16; - // Added in 85 boolean setData(in Map data) = 17; Map getData() = 18; void registerWebMessageCallback(in String jsObjectName, @@ -69,12 +66,10 @@ boolean canTranslate() = 21; void showTranslateUi() = 22; - // Added in 86 void setGoogleAccountsCallbackClient(IGoogleAccountsCallbackClient client) = 23; IFaviconFetcher createFaviconFetcher(IFaviconFetcherClient client) = 24; void setTranslateTargetLanguage(in String targetLanguage) = 25; - // Added in 87 void setScrollOffsetsEnabled(in boolean enabled) = 26; // Added in 88
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITabClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITabClient.aidl index 1b8028c..21bf2d7 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITabClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/ITabClient.aidl
@@ -18,35 +18,26 @@ void onRenderProcessGone() = 2; - // Removed in 87. - // void onCloseTab() = 3; + // ID 3 was onCloseTab and was removed in M87. - // Added in M82. // Deprecated in M88. void showContextMenu(in IObjectWrapper pageUrl, in IObjectWrapper linkUrl, in IObjectWrapper linkText, in IObjectWrapper titleOrAltText, in IObjectWrapper srcUrl) = 4; - // Added in M82. void onTabModalStateChanged(in boolean isTabModalShowing) = 5; - // Added in M83. void onTitleUpdated(in IObjectWrapper title) = 6; - // Added in M84. void bringTabToFront() = 7; - // Added in M84. void onTabDestroyed() = 8; - // Added in M85. void onBackgroundColorChanged(in int color) = 9; - // Added in M85 void onScrollNotification( in int notificationType, in float currentScrollRatio) = 10; - // Added in M87 void onVerticalScrollOffsetChanged(in int offset) = 11; // Added in M88
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUrlBarController.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUrlBarController.aidl index c69b042..3ea5816 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUrlBarController.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUrlBarController.aidl
@@ -8,10 +8,8 @@ interface IUrlBarController { - // Deprecated in 84, use createUrlBarView with three arguments. - IObjectWrapper /* View */ deprecatedCreateUrlBarView(in Bundle options) = 0; + // ID 0 was deprecatedCreateUrlBarView and was removed in M89. - // Since 86 IObjectWrapper /* View */ createUrlBarView( in Bundle options, in IObjectWrapper /* View.OnClickListener */ textClickListener,
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUserIdentityCallbackClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUserIdentityCallbackClient.aidl index 52eef8e6..e5f61e1 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUserIdentityCallbackClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IUserIdentityCallbackClient.aidl
@@ -6,7 +6,6 @@ import org.chromium.weblayer_private.interfaces.IObjectWrapper; -// Since 87 interface IUserIdentityCallbackClient { String getEmail() = 0; String getFullName() = 1;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl index 908ac95..6408410a 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayer.aidl
@@ -70,16 +70,12 @@ // Forwards broadcast from a notification to the implementation. void onReceivedBroadcast(in IObjectWrapper appContext, in Intent intent) = 11; - // Added in Version 82. void enumerateAllProfileNames(in IObjectWrapper valueCallback) = 12; - // Added in Version 83. void setClient(in IWebLayerClient client) = 13; - // Added in Version 84. String getUserAgentString() = 14; - // Added in Version 84. void registerExternalExperimentIDs(in String trialName, in int[] experimentIds) = 15; // Creates the WebLayer counterpart to a SiteSettingsFragment - a SiteSettingsFragmentImpl @@ -88,20 +84,16 @@ // WebLayer can call methods on Fragment. // @param fragmentArgs Bundle of arguments with which the Fragment was created on the client side // (see Fragment#setArguments). - // Added in Version 84. ISiteSettingsFragment createSiteSettingsFragmentImpl( in IRemoteFragmentClient remoteFragmentClient, in IObjectWrapper fragmentArgs) = 16; - // Added in Version 85. void onMediaSessionServiceStarted(in IObjectWrapper sessionService, in Intent intent) = 17; void onMediaSessionServiceDestroyed() = 18; - // Added in Version 86. IBinder initializeImageDecoder(in IObjectWrapper appContext, in IObjectWrapper remoteContext) = 19; - // Added in Version 87. IObjectWrapper getApplicationContext() = 20; IMediaRouteDialogFragment createMediaRouteDialogFragmentImpl( in IRemoteFragmentClient remoteFragmentClient) = 21;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayerClient.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayerClient.aidl index 933e8507..e8f34f60 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayerClient.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IWebLayerClient.aidl
@@ -10,8 +10,6 @@ Intent createIntent() = 0; Intent createMediaSessionServiceIntent() = 1; int getMediaSessionNotificationId() = 2; - - // Since Version 86. Intent createImageDecoderServiceIntent() = 3; // Since Version 88.
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java index a76b13c3..4d786a4 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java
@@ -16,4 +16,9 @@ * @see WebLayer#isAvailable() */ int MAX_SKEW = 4; + + /** + * Minimum version of client and implementation. + */ + int MIN_VERSION = 87; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/media/MediaStreamManager.java b/weblayer/browser/java/org/chromium/weblayer_private/media/MediaStreamManager.java index 3208aea..579f186 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/media/MediaStreamManager.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/media/MediaStreamManager.java
@@ -27,7 +27,6 @@ import org.chromium.content_public.browser.WebContents; import org.chromium.weblayer_private.IntentUtils; import org.chromium.weblayer_private.TabImpl; -import org.chromium.weblayer_private.WebLayerFactoryImpl; import org.chromium.weblayer_private.WebLayerImpl; import org.chromium.weblayer_private.WebLayerNotificationChannels; import org.chromium.weblayer_private.WebLayerNotificationWrapperBuilder; @@ -45,8 +44,6 @@ @JNINamespace("weblayer") public class MediaStreamManager { private static final String WEBRTC_PREFIX = "org.chromium.weblayer.webrtc"; - private static final String EXTRA_TAB_ID = WEBRTC_PREFIX + ".TAB_ID"; - private static final String ACTIVATE_TAB_INTENT = WEBRTC_PREFIX + ".ACTIVATE_TAB"; private static final String AV_STREAM_TAG = WEBRTC_PREFIX + ".avstream"; /** @@ -70,32 +67,6 @@ private long mNative; /** - * @return a string that prefixes all intents that can be handled by {@link forwardIntent}. - * @Deprecated in M85+, this class does not handle intents. Remove in M88. - */ - public static String getIntentPrefix() { - return WEBRTC_PREFIX; - } - - /** - * Handles an intent coming from a media streaming notification. - * @param intent the intent which was previously posted via {@link update}. - * @Deprecated in M85+, this class does not handle intents. Remove in M88. - */ - public static void forwardIntent(Intent intent) { - assert intent.getAction().equals(ACTIVATE_TAB_INTENT); - int tabId = intent.getIntExtra(EXTRA_TAB_ID, -1); - TabImpl tab = TabImpl.getTabById(tabId); - if (tab == null) return; - - try { - tab.getClient().bringTabToFront(); - } catch (RemoteException e) { - throw new AndroidRuntimeException(e); - } - } - - /** * To be called when WebLayer is started. Clears notifications that may have persisted from * before a crash. */ @@ -208,23 +179,13 @@ */ @CalledByNative private void update(boolean audio, boolean video) { - // The notification intent is not handled in the client prior to M84. - if (WebLayerFactoryImpl.getClientMajorVersion() < 84) return; - if (!audio && !video) { cancelNotification(); return; } Context appContext = ContextUtils.getApplicationContext(); - Intent intent = null; - if (WebLayerFactoryImpl.getClientMajorVersion() >= 85) { - intent = IntentUtils.createBringTabToFrontIntent(mNotificationId); - } else { - intent = WebLayerImpl.createIntent(); - intent.putExtra(EXTRA_TAB_ID, mNotificationId); - intent.setAction(ACTIVATE_TAB_INTENT); - } + Intent intent = IntentUtils.createBringTabToFrontIntent(mNotificationId); PendingIntentProvider contentIntent = PendingIntentProvider.getBroadcast(appContext, mNotificationId, intent, 0);
diff --git a/weblayer/browser/subresource_filter_browsertest.cc b/weblayer/browser/subresource_filter_browsertest.cc index 2a4a3b18..b0f77ef 100644 --- a/weblayer/browser/subresource_filter_browsertest.cc +++ b/weblayer/browser/subresource_filter_browsertest.cc
@@ -4,7 +4,6 @@ #include "base/json/json_reader.h" #include "build/build_config.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" #include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" #include "components/subresource_filter/content/browser/ruleset_service.h" @@ -16,7 +15,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/resource/resource_bundle.h" #include "weblayer/browser/browser_process.h" -#include "weblayer/browser/host_content_settings_map_factory.h" #include "weblayer/browser/subresource_filter_client_impl.h" #include "weblayer/browser/tab_impl.h" #include "weblayer/grit/weblayer_resources.h" @@ -296,68 +294,6 @@ EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents->GetMainFrame())); } -IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest, - ContentSettingsAllowlist_DoNotActivate) { - auto* web_contents = static_cast<TabImpl*>(shell()->tab())->web_contents(); - - GURL test_url( - embedded_test_server()->GetURL("/frame_with_included_script.html")); - - ASSERT_NO_FATAL_FAILURE( - SetRulesetToDisallowURLsWithPathSuffix("included_script.js")); - ActivateSubresourceFilterInWebContentsForURL(web_contents, test_url); - - NavigateAndWaitForCompletion(test_url, shell()); - EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents->GetMainFrame())); - - content::WebContentsConsoleObserver console_observer(web_contents); - console_observer.SetPattern(subresource_filter::kActivationConsoleMessage); - - // Simulate explicitly allowlisting via content settings. - HostContentSettingsMap* settings_map = - HostContentSettingsMapFactory::GetForBrowserContext( - web_contents->GetBrowserContext()); - settings_map->SetContentSettingDefaultScope( - test_url, test_url, ContentSettingsType::ADS, CONTENT_SETTING_ALLOW); - - NavigateAndWaitForCompletion(test_url, shell()); - EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents->GetMainFrame())); - - // No message for allowlisted url. - EXPECT_TRUE(console_observer.messages().empty()); -} - -IN_PROC_BROWSER_TEST_F(SubresourceFilterBrowserTest, - ContentSettingsAllowlistGlobal_DoNotActivate) { - auto* web_contents = static_cast<TabImpl*>(shell()->tab())->web_contents(); - - GURL test_url( - embedded_test_server()->GetURL("/frame_with_included_script.html")); - - ASSERT_NO_FATAL_FAILURE( - SetRulesetToDisallowURLsWithPathSuffix("included_script.js")); - ActivateSubresourceFilterInWebContentsForURL(web_contents, test_url); - - NavigateAndWaitForCompletion(test_url, shell()); - EXPECT_FALSE(WasParsedScriptElementLoaded(web_contents->GetMainFrame())); - - content::WebContentsConsoleObserver console_observer(web_contents); - console_observer.SetPattern(subresource_filter::kActivationConsoleMessage); - - // Simulate globally allowing ads via content settings. - HostContentSettingsMap* settings_map = - HostContentSettingsMapFactory::GetForBrowserContext( - web_contents->GetBrowserContext()); - settings_map->SetDefaultContentSetting(ContentSettingsType::ADS, - CONTENT_SETTING_ALLOW); - - NavigateAndWaitForCompletion(test_url, shell()); - EXPECT_TRUE(WasParsedScriptElementLoaded(web_contents->GetMainFrame())); - - // No message for loads that are not activated. - EXPECT_TRUE(console_observer.messages().empty()); -} - #if defined(OS_ANDROID) // Test that the ads blocked infobar is presented when visiting a page where the // subresource filter blocks resources from being loaded and is removed when
diff --git a/weblayer/browser/subresource_filter_client_impl.cc b/weblayer/browser/subresource_filter_client_impl.cc index a99f17ce..ba3eebb 100644 --- a/weblayer/browser/subresource_filter_client_impl.cc +++ b/weblayer/browser/subresource_filter_client_impl.cc
@@ -9,7 +9,6 @@ #include "base/macros.h" #include "build/build_config.h" #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" -#include "components/subresource_filter/content/browser/profile_interaction_manager.h" #include "components/subresource_filter/content/browser/ruleset_service.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" #include "components/subresource_filter/core/common/activation_decision.h" @@ -19,7 +18,6 @@ #include "content/public/browser/render_frame_host.h" #include "weblayer/browser/browser_process.h" #include "weblayer/browser/safe_browsing/safe_browsing_service.h" -#include "weblayer/browser/subresource_filter_profile_context_factory.h" #if defined(OS_ANDROID) #include "components/safe_browsing/android/remote_database_manager.h" @@ -55,12 +53,7 @@ #if defined(OS_ANDROID) web_contents_(web_contents), #endif - database_manager_(GetDatabaseManagerFromSafeBrowsingService()), - profile_interaction_manager_( - std::make_unique<subresource_filter::ProfileInteractionManager>( - web_contents, - SubresourceFilterProfileContextFactory::GetForBrowserContext( - web_contents->GetBrowserContext()))) { + database_manager_(GetDatabaseManagerFromSafeBrowsingService()) { } SubresourceFilterClientImpl::~SubresourceFilterClientImpl() = default; @@ -94,6 +87,16 @@ #endif } +subresource_filter::mojom::ActivationLevel +SubresourceFilterClientImpl::OnPageActivationComputed( + content::NavigationHandle* navigation_handle, + subresource_filter::mojom::ActivationLevel initial_activation_level, + subresource_filter::ActivationDecision* decision) { + DCHECK(navigation_handle->IsInMainFrame()); + + return initial_activation_level; +} + void SubresourceFilterClientImpl::OnAdsViolationTriggered( content::RenderFrameHost* rfh, subresource_filter::mojom::AdsViolation triggered_violation) {} @@ -103,9 +106,4 @@ return database_manager_; } -subresource_filter::ProfileInteractionManager* -SubresourceFilterClientImpl::GetProfileInteractionManager() { - return profile_interaction_manager_.get(); -} - } // namespace weblayer
diff --git a/weblayer/browser/subresource_filter_client_impl.h b/weblayer/browser/subresource_filter_client_impl.h index cceb5d20..1debbf2 100644 --- a/weblayer/browser/subresource_filter_client_impl.h +++ b/weblayer/browser/subresource_filter_client_impl.h
@@ -43,13 +43,15 @@ // SubresourceFilterClient: void ShowNotification() override; + subresource_filter::mojom::ActivationLevel OnPageActivationComputed( + content::NavigationHandle* navigation_handle, + subresource_filter::mojom::ActivationLevel initial_activation_level, + subresource_filter::ActivationDecision* decision) override; void OnAdsViolationTriggered( content::RenderFrameHost* rfh, subresource_filter::mojom::AdsViolation triggered_violation) override; const scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> GetSafeBrowsingDatabaseManager() override; - subresource_filter::ProfileInteractionManager* GetProfileInteractionManager() - override; void OnReloadRequested() override; // Sets the SafeBrowsingDatabaseManager instance used to |database_manager|. @@ -68,8 +70,6 @@ std::unique_ptr<subresource_filter::ContentSubresourceFilterThrottleManager> throttle_manager_; scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_; - std::unique_ptr<subresource_filter::ProfileInteractionManager> - profile_interaction_manager_; }; } // namespace weblayer
diff --git a/weblayer/public/java/org/chromium/weblayer/Browser.java b/weblayer/public/java/org/chromium/weblayer/Browser.java index cfd3221..83b56124 100644 --- a/weblayer/public/java/org/chromium/weblayer/Browser.java +++ b/weblayer/public/java/org/chromium/weblayer/Browser.java
@@ -98,13 +98,6 @@ for (TabListCallback callback : mTabListCallbacks) { callback.onWillDestroyBrowserAndAllTabs(); } - - // See comment in Tab$TabClientImpl.onTabDestroyed for details on this. - if (WebLayer.getSupportedMajorVersionInternal() >= 87) return; - - for (Tab tab : getTabs()) { - Tab.unregisterTab(tab); - } } // Called after the browser was destroyed. @@ -231,14 +224,9 @@ * Returns true if this Browser is in the process of restoring the previous state. * * @param True if restoring previous state. - * - * @since 87 */ public boolean isRestoringPreviousState() { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } throwIfDestroyed(); try { return mImpl.isRestoringPreviousState(); @@ -251,14 +239,9 @@ * Adds a BrowserRestoreCallback. * * @param callback The BrowserRestoreCallback. - * - * @since 87 */ public void registerBrowserRestoreCallback(@NonNull BrowserRestoreCallback callback) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } throwIfDestroyed(); mBrowserRestoreCallbacks.addObserver(callback); } @@ -267,14 +250,9 @@ * Removes a BrowserRestoreCallback. * * @param callback The BrowserRestoreCallback. - * - * @since 87 */ public void unregisterBrowserRestoreCallback(@NonNull BrowserRestoreCallback callback) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } throwIfDestroyed(); mBrowserRestoreCallbacks.removeObserver(callback); } @@ -310,16 +288,11 @@ * contexts where the URL should be visible to the user. * @param animate Whether or not any height/visibility changes that result from this call * should be animated. - * - * @since 86 */ public void setTopView(@Nullable View view, int minHeight, boolean onlyExpandControlsAtPageTop, boolean animate) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } try { mImpl.setTopViewAndScrollingBehavior( ObjectWrapper.wrap(view), minHeight, onlyExpandControlsAtPageTop, animate); @@ -332,8 +305,6 @@ * Sets the View shown at the bottom of the browser. A value of null removes the view. * * @param view The new bottom-view. - * - * @since 84 */ public void setBottomView(@Nullable View view) { ThreadCheck.ensureOnUiThread(); @@ -397,15 +368,10 @@ /** * Creates a new tab attached to this browser. This will call {@link TabListCallback#onTabAdded} * with the new tab. - * - * @since 85 */ public @NonNull Tab createTab() { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } try { ITab iTab = mImpl.createTab(); Tab tab = Tab.getTabById(iTab.getId()); @@ -483,7 +449,6 @@ /** * Returns the UrlBarController. - * @since 82 */ @NonNull public UrlBarController getUrlBarController() { @@ -535,7 +500,6 @@ for (TabListCallback callback : mTabListCallbacks) { callback.onTabRemoved(tab); } - tab.onRemovedFromBrowser(); } @Override
diff --git a/weblayer/public/java/org/chromium/weblayer/BrowserFragment.java b/weblayer/public/java/org/chromium/weblayer/BrowserFragment.java index a269a1a1..4b49431 100644 --- a/weblayer/public/java/org/chromium/weblayer/BrowserFragment.java +++ b/weblayer/public/java/org/chromium/weblayer/BrowserFragment.java
@@ -81,9 +81,6 @@ // want to trigger loading WebLayer. if (args.getBoolean(BrowserFragmentArgs.IS_INCOGNITO, false)) { String name = args.getString(BrowserFragmentArgs.PROFILE_NAME); - if (!"".equals(name) && WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException("Named incognito profile requires 87"); - } } try { mImpl = mWebLayer.connectFragment(getRemoteFragmentClient(), args);
diff --git a/weblayer/public/java/org/chromium/weblayer/BrowsingDataType.java b/weblayer/public/java/org/chromium/weblayer/BrowsingDataType.java index 7df7378..915105e8 100644 --- a/weblayer/public/java/org/chromium/weblayer/BrowsingDataType.java +++ b/weblayer/public/java/org/chromium/weblayer/BrowsingDataType.java
@@ -19,6 +19,5 @@ int COOKIES_AND_SITE_DATA = org.chromium.weblayer_private.interfaces.BrowsingDataType.COOKIES_AND_SITE_DATA; int CACHE = org.chromium.weblayer_private.interfaces.BrowsingDataType.CACHE; - // @since 86 int SITE_SETTINGS = org.chromium.weblayer_private.interfaces.BrowsingDataType.SITE_SETTINGS; }
diff --git a/weblayer/public/java/org/chromium/weblayer/CookieChangedCallback.java b/weblayer/public/java/org/chromium/weblayer/CookieChangedCallback.java index 9224097..ed96ea3 100644 --- a/weblayer/public/java/org/chromium/weblayer/CookieChangedCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/CookieChangedCallback.java
@@ -8,8 +8,6 @@ /** * Callback used to listen for cookie changes. - * - * @since 83 */ public abstract class CookieChangedCallback { public abstract void onCookieChanged(@NonNull String cookie, @CookieChangeCause int cause);
diff --git a/weblayer/public/java/org/chromium/weblayer/CookieManager.java b/weblayer/public/java/org/chromium/weblayer/CookieManager.java index cda2f900..9c71938 100644 --- a/weblayer/public/java/org/chromium/weblayer/CookieManager.java +++ b/weblayer/public/java/org/chromium/weblayer/CookieManager.java
@@ -20,8 +20,6 @@ /** * Manages cookies for a WebLayer profile. - * - * @since 83 */ public class CookieManager { private final ICookieManager mImpl;
diff --git a/weblayer/public/java/org/chromium/weblayer/Download.java b/weblayer/public/java/org/chromium/weblayer/Download.java index 4c80639..26008b7d 100644 --- a/weblayer/public/java/org/chromium/weblayer/Download.java +++ b/weblayer/public/java/org/chromium/weblayer/Download.java
@@ -16,8 +16,6 @@ /** * Contains information about a single download that's in progress. - * - * @since 81 */ public class Download extends IClientDownload.Stub { private final IDownload mDownloadImpl; @@ -130,15 +128,10 @@ /** * Returns the file name for the download that should be displayed to the user. - * - * @since 86 */ @NonNull public File getFileNameToReportToUser() { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } try { return new File(mDownloadImpl.getFileNameToReportToUser()); } catch (RemoteException e) {
diff --git a/weblayer/public/java/org/chromium/weblayer/DownloadCallback.java b/weblayer/public/java/org/chromium/weblayer/DownloadCallback.java index 846c24d..37ce555 100644 --- a/weblayer/public/java/org/chromium/weblayer/DownloadCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/DownloadCallback.java
@@ -38,8 +38,6 @@ * @param requestInitiator the initiating Uri, if present * @param callback a callback to allow or disallow the download. Must be called to avoid leaks, * and must be called on the UI thread. - * - * @since 81 */ public abstract void allowDownload(@NonNull Uri uri, @NonNull String requestMethod, @Nullable Uri requestInitiator, @NonNull ValueCallback<Boolean> callback); @@ -52,8 +50,6 @@ * destroyed. * * @param download the unique object for this download. - * - * @since 81 */ public void onDownloadStarted(@NonNull Download download) {} @@ -61,8 +57,6 @@ * The download progress has changed. * * @param download the unique object for this download. - * - * @since 81 */ public void onDownloadProgressChanged(@NonNull Download download) {} @@ -73,8 +67,6 @@ * to it afterward. * * @param download the unique object for this download. - * - * @since 81 */ public void onDownloadCompleted(@NonNull Download download) {} @@ -86,8 +78,6 @@ * to it afterward. * * @param download the unique object for this download. - * - * @since 81 */ public void onDownloadFailed(@NonNull Download download) {} }
diff --git a/weblayer/public/java/org/chromium/weblayer/ErrorPage.java b/weblayer/public/java/org/chromium/weblayer/ErrorPage.java index b8c7ab8..9de7d452 100644 --- a/weblayer/public/java/org/chromium/weblayer/ErrorPage.java +++ b/weblayer/public/java/org/chromium/weblayer/ErrorPage.java
@@ -8,8 +8,6 @@ /** * ErrorPage contains the html to show when an error is encountered. - * - * @since 86 */ public class ErrorPage { public final String htmlContent;
diff --git a/weblayer/public/java/org/chromium/weblayer/ErrorPageCallback.java b/weblayer/public/java/org/chromium/weblayer/ErrorPageCallback.java index fb386127..d11556d 100644 --- a/weblayer/public/java/org/chromium/weblayer/ErrorPageCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/ErrorPageCallback.java
@@ -26,8 +26,6 @@ * @param navigation The navigation that encountered the error. * * @return The error page. - * - * @since 86 */ public @Nullable ErrorPage getErrorPage(@NonNull Navigation navigation) { return null;
diff --git a/weblayer/public/java/org/chromium/weblayer/FaviconCallback.java b/weblayer/public/java/org/chromium/weblayer/FaviconCallback.java index 01172bf..c063b62 100644 --- a/weblayer/public/java/org/chromium/weblayer/FaviconCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/FaviconCallback.java
@@ -10,8 +10,6 @@ /** * Informed of changes to the favicon of the current navigation. - * - * @since 86 */ public abstract class FaviconCallback { /**
diff --git a/weblayer/public/java/org/chromium/weblayer/FaviconFetcher.java b/weblayer/public/java/org/chromium/weblayer/FaviconFetcher.java index 7fcd8e16..b99e3697 100644 --- a/weblayer/public/java/org/chromium/weblayer/FaviconFetcher.java +++ b/weblayer/public/java/org/chromium/weblayer/FaviconFetcher.java
@@ -17,8 +17,6 @@ /** * {@link FaviconFetcher} is responsible for downloading a favicon for the current navigation. * {@link FaviconFetcher} maintains an on disk cache of favicons downloading favicons as necessary. - * - * @since 86 */ public class FaviconFetcher { private final FaviconCallback mCallback;
diff --git a/weblayer/public/java/org/chromium/weblayer/FindInPageCallback.java b/weblayer/public/java/org/chromium/weblayer/FindInPageCallback.java index 786952fb..33cbd7a 100644 --- a/weblayer/public/java/org/chromium/weblayer/FindInPageCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/FindInPageCallback.java
@@ -6,8 +6,6 @@ /** * Informed of find in page results. - * - * @since 81 */ public abstract class FindInPageCallback { /**
diff --git a/weblayer/public/java/org/chromium/weblayer/FindInPageController.java b/weblayer/public/java/org/chromium/weblayer/FindInPageController.java index 9cdea51..98c9c64 100644 --- a/weblayer/public/java/org/chromium/weblayer/FindInPageController.java +++ b/weblayer/public/java/org/chromium/weblayer/FindInPageController.java
@@ -19,8 +19,6 @@ * * There is one FindInPageController per {@link Tab}, and only the active tab may have an active * find session. - * - * @since 81 */ public class FindInPageController { private final ITab mTab;
diff --git a/weblayer/public/java/org/chromium/weblayer/GoogleAccountsCallback.java b/weblayer/public/java/org/chromium/weblayer/GoogleAccountsCallback.java index 92db5a9..e9a82f9 100644 --- a/weblayer/public/java/org/chromium/weblayer/GoogleAccountsCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/GoogleAccountsCallback.java
@@ -8,8 +8,6 @@ /** * Used to intercept interaction with GAIA accounts. - * - * @since 86 */ public abstract class GoogleAccountsCallback { /**
diff --git a/weblayer/public/java/org/chromium/weblayer/GoogleAccountsParams.java b/weblayer/public/java/org/chromium/weblayer/GoogleAccountsParams.java index 838f406..82db953 100644 --- a/weblayer/public/java/org/chromium/weblayer/GoogleAccountsParams.java +++ b/weblayer/public/java/org/chromium/weblayer/GoogleAccountsParams.java
@@ -10,8 +10,6 @@ /** * Params passed to {@link GoogleAccountsCallback#onGoogleAccountsRequest}. - * - * @since 86 */ public class GoogleAccountsParams { /**
diff --git a/weblayer/public/java/org/chromium/weblayer/ImageDecoderService.java b/weblayer/public/java/org/chromium/weblayer/ImageDecoderService.java index cdd8579..5ac2ec8 100644 --- a/weblayer/public/java/org/chromium/weblayer/ImageDecoderService.java +++ b/weblayer/public/java/org/chromium/weblayer/ImageDecoderService.java
@@ -13,7 +13,6 @@ /** * A service used internally by WebLayer for decoding images on the local device. - * @since 87 */ public class ImageDecoderService extends Service { private IBinder mImageDecoder;
diff --git a/weblayer/public/java/org/chromium/weblayer/MediaCaptureCallback.java b/weblayer/public/java/org/chromium/weblayer/MediaCaptureCallback.java index d6612d91..101f490 100644 --- a/weblayer/public/java/org/chromium/weblayer/MediaCaptureCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/MediaCaptureCallback.java
@@ -9,8 +9,6 @@ /** * Used along with {@link MediaCaptureController} to control and observe Media Capture and Streams * usage. - * - * @since 84 */ public abstract class MediaCaptureCallback { /**
diff --git a/weblayer/public/java/org/chromium/weblayer/MediaCaptureController.java b/weblayer/public/java/org/chromium/weblayer/MediaCaptureController.java index dcd6094..0afc45c 100644 --- a/weblayer/public/java/org/chromium/weblayer/MediaCaptureController.java +++ b/weblayer/public/java/org/chromium/weblayer/MediaCaptureController.java
@@ -21,8 +21,6 @@ * * The Web API is used by sites to record video and audio from the user's device, e.g. for voice * recognition or video conferencing. There is one MediaCaptureController per {@link Tab}. - * - * @since 84 */ public class MediaCaptureController { private final ITab mTab;
diff --git a/weblayer/public/java/org/chromium/weblayer/MediaRouteDialogFragment.java b/weblayer/public/java/org/chromium/weblayer/MediaRouteDialogFragment.java index fb75ae6..5e6dd5bd 100644 --- a/weblayer/public/java/org/chromium/weblayer/MediaRouteDialogFragment.java +++ b/weblayer/public/java/org/chromium/weblayer/MediaRouteDialogFragment.java
@@ -13,8 +13,6 @@ * * This class hosts dialog fragments for casting, such as a {@link MediaRouteChooserDialogFragment} * or a {@link MediaRouteControllerDialogFragment}. - * - * @since 87 */ public class MediaRouteDialogFragment extends RemoteFragment { private static final String FRAGMENT_TAG = "WebLayerMediaRouteDialogFragment";
diff --git a/weblayer/public/java/org/chromium/weblayer/MediaSessionService.java b/weblayer/public/java/org/chromium/weblayer/MediaSessionService.java index e1a6003..eccb465 100644 --- a/weblayer/public/java/org/chromium/weblayer/MediaSessionService.java +++ b/weblayer/public/java/org/chromium/weblayer/MediaSessionService.java
@@ -20,7 +20,6 @@ * This class is a thin wrapper that forwards lifecycle events to the WebLayer implementation, which * in turn manages a system notification and {@link MediaSession}. This service will be in the * foreground when the MediaSession is active. - * @since 85 */ public class MediaSessionService extends MediaPlaybackBaseService { // A helper to automatically pause the media session when a user removes headphones.
diff --git a/weblayer/public/java/org/chromium/weblayer/NavigateParams.java b/weblayer/public/java/org/chromium/weblayer/NavigateParams.java index 74be97ce..3d6a71f 100644 --- a/weblayer/public/java/org/chromium/weblayer/NavigateParams.java +++ b/weblayer/public/java/org/chromium/weblayer/NavigateParams.java
@@ -10,12 +10,9 @@ /** * Parameters for {@link NavigationController#navigate}. - * - * @since 83 */ public class NavigateParams { - private org.chromium.weblayer_private.interfaces.NavigateParams mInterfaceParams = - new org.chromium.weblayer_private.interfaces.NavigateParams(); + private boolean mShouldReplaceCurrentEntry; private boolean mIntentProcessingDisabled; private boolean mNetworkErrorAutoReloadDisabled; private boolean mAutoPlayEnabled; @@ -48,7 +45,7 @@ */ @NonNull public Builder setShouldReplaceCurrentEntry(boolean replace) { - mParams.mInterfaceParams.mShouldReplaceCurrentEntry = replace; + mParams.mShouldReplaceCurrentEntry = replace; return this; } @@ -58,15 +55,9 @@ * create and launch an Intent. The exact heuristics of when Intent matching is performed * depends upon a wide range of state (such as the uri being navigated to, navigation * stack...). - * - * @since 86 */ @NonNull public Builder disableIntentProcessing() { - if (WebLayer.shouldPerformVersionChecks() - && WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } mParams.mIntentProcessingDisabled = true; return this; } @@ -74,30 +65,18 @@ /** * Disables auto-reload for this navigation if the network is down and comes back later. * Auto-reload is enabled by default. - * - * @since 86 */ @NonNull public Builder disableNetworkErrorAutoReload() { - if (WebLayer.shouldPerformVersionChecks() - && WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } mParams.mNetworkErrorAutoReloadDisabled = true; return this; } /** * Enable auto-play for videos in this navigation. Auto-play is disabled by default. - * - * @since 86 */ @NonNull public Builder enableAutoPlay() { - if (WebLayer.shouldPerformVersionChecks() - && WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } mParams.mAutoPlayEnabled = true; return this; } @@ -116,44 +95,27 @@ * information to show the security padlock or certificate data. As such an * exception is thrown if this is set when a View from UrlBarController is * attached to a window. - * - * @since 87 */ @NonNull public Builder setResponse(@NonNull WebResourceResponse response) { - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } mParams.mResponse = response; return this; } } - org.chromium.weblayer_private.interfaces.NavigateParams toInterfaceParams() { - return mInterfaceParams; - } - /** * Returns true if the current navigation will be replaced, false otherwise. - * - * @since 83 */ public boolean getShouldReplaceCurrentEntry() { - return mInterfaceParams.mShouldReplaceCurrentEntry; + return mShouldReplaceCurrentEntry; } /** * Returns true if intent processing is disabled. * * @return Whether intent processing is disabled. - * - * @since 86 */ public boolean isIntentProcessingDisabled() { - if (WebLayer.shouldPerformVersionChecks() - && WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } return mIntentProcessingDisabled; } @@ -161,14 +123,8 @@ * Returns true if auto reload for network errors is disabled. * * @return Whether auto reload for network errors is disabled. - * - * @since 86 */ public boolean isNetworkErrorAutoReloadDisabled() { - if (WebLayer.shouldPerformVersionChecks() - && WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } return mNetworkErrorAutoReloadDisabled; } @@ -176,14 +132,8 @@ * Returns true if auto play for videos is enabled. * * @return Whether auto play for videos is enabled. - * - * @since 86 */ public boolean isAutoPlayEnabled() { - if (WebLayer.shouldPerformVersionChecks() - && WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } return mAutoPlayEnabled; } @@ -191,8 +141,6 @@ * Returns a response of the html to use. * * @return WebResourceResponse of html to use. - * - * @since 87 */ WebResourceResponse getResponse() { return mResponse;
diff --git a/weblayer/public/java/org/chromium/weblayer/Navigation.java b/weblayer/public/java/org/chromium/weblayer/Navigation.java index 5203433c..61e078f 100644 --- a/weblayer/public/java/org/chromium/weblayer/Navigation.java +++ b/weblayer/public/java/org/chromium/weblayer/Navigation.java
@@ -132,8 +132,6 @@ * status is determined for a navigation when processing final (post redirect) HTTP response * headers. This means the only time the embedder can know if it's a download is in * NavigationCallback.onNavigationFailed. - * - * @since 84 */ public boolean isDownload() { ThreadCheck.ensureOnUiThread(); @@ -216,8 +214,6 @@ /** * Whether this navigation was stopped before it could complete because * NavigationController.stop() was called. - * - * @since 84 */ public boolean wasStopCalled() { ThreadCheck.ensureOnUiThread(); @@ -248,8 +244,6 @@ * * @throws IllegalArgumentException If supplied invalid values. * @throws IllegalStateException If not called during start or a redirect. - * - * @since 83 */ public void setRequestHeader(@NonNull String name, @NonNull String value) { ThreadCheck.ensureOnUiThread(); @@ -275,8 +269,6 @@ * @throws IllegalArgumentException If supplied an invalid value. * @throws IllegalStateException If not called during start or if {@link * Tab.setDesktopUserAgent} was called with a value of true. - * - * @since 84 */ public void setUserAgentString(@NonNull String value) { ThreadCheck.ensureOnUiThread(); @@ -299,14 +291,9 @@ * window.history.forward() or window.history.back(). * * @return Whether the navigation was initiated by the page. - * - * @since 86 */ public boolean isPageInitiated() { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } try { return mNavigationImpl.isPageInitiated(); } catch (RemoteException e) { @@ -319,14 +306,9 @@ * * embedder-specified through NavigationController::Reload * * page-initiated reloads, e.g. location.reload() * * reloads when the network interface is reconnected - * - * @since 86 */ public boolean isReload() { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } try { return mNavigationImpl.isReload(); } catch (RemoteException e) {
diff --git a/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java b/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java index 2208dc7c..96e0bea 100644 --- a/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/NavigationCallback.java
@@ -147,7 +147,6 @@ * Called after each navigation to indicate that the old page is no longer * being rendered. Note this is not ordered with respect to onFirstContentfulPaint. * @param newNavigationUri Uri of the new navigation. - * @since 85 */ public void onOldPageNoLongerRendered(@NonNull Uri newNavigationUri) {} }
diff --git a/weblayer/public/java/org/chromium/weblayer/NavigationController.java b/weblayer/public/java/org/chromium/weblayer/NavigationController.java index 0e815d1..5b35aee 100644 --- a/weblayer/public/java/org/chromium/weblayer/NavigationController.java +++ b/weblayer/public/java/org/chromium/weblayer/NavigationController.java
@@ -55,40 +55,23 @@ * * @throws IllegalStateException if params.getResponse() is not null but a URLBarController * View is attached to a Window. - * - * @since 83 */ public void navigate(@NonNull Uri uri, @Nullable NavigateParams params) { ThreadCheck.ensureOnUiThread(); try { - int version = WebLayer.getSupportedMajorVersionInternal(); - if (params == null || version < 86) { - mNavigationController.navigate( - uri.toString(), params == null ? null : params.toInterfaceParams()); - } else { - if (version == 86) { - if (params.getResponse() != null) { - throw new UnsupportedOperationException(); - } - mNavigationController.navigate2(uri.toString(), - params == null ? false : params.getShouldReplaceCurrentEntry(), - params == null ? false : params.isIntentProcessingDisabled(), - params == null ? false : params.isNetworkErrorAutoReloadDisabled(), - params == null ? false : params.isAutoPlayEnabled()); - } else { - INavigateParams iparams = mNavigationController.createNavigateParams(); - if (params.getShouldReplaceCurrentEntry()) iparams.replaceCurrentEntry(); - if (params.isIntentProcessingDisabled()) iparams.disableIntentProcessing(); - if (params.isNetworkErrorAutoReloadDisabled()) { - iparams.disableNetworkErrorAutoReload(); - } - if (params.isAutoPlayEnabled()) iparams.enableAutoPlay(); - if (params.getResponse() != null) { - iparams.setResponse(ObjectWrapper.wrap(params.getResponse())); - } - mNavigationController.navigate3(uri.toString(), iparams); + INavigateParams iparams = mNavigationController.createNavigateParams(); + if (params != null) { + if (params.getShouldReplaceCurrentEntry()) iparams.replaceCurrentEntry(); + if (params.isIntentProcessingDisabled()) iparams.disableIntentProcessing(); + if (params.isNetworkErrorAutoReloadDisabled()) { + iparams.disableNetworkErrorAutoReload(); + } + if (params.isAutoPlayEnabled()) iparams.enableAutoPlay(); + if (params.getResponse() != null) { + iparams.setResponse(ObjectWrapper.wrap(params.getResponse())); } } + mNavigationController.navigate3(uri.toString(), iparams); } catch (RemoteException e) { throw new APICallException(e); } @@ -168,8 +151,6 @@ * @throws IndexOutOfBoundsException If index is not between 0 and {@link * getNavigationListCurrentIndex}. * @throws IndexOutOfBoundsException - * - * @since 81 */ public void goToIndex(int index) throws IndexOutOfBoundsException { ThreadCheck.ensureOnUiThread(); @@ -256,7 +237,6 @@ * * @throws IndexOutOfBoundsException If index is not between 0 and {@link * getNavigationListCurrentIndex}. - * @since 81 */ @NonNull public String getNavigationEntryTitle(int index) throws IndexOutOfBoundsException { @@ -276,13 +256,9 @@ * * @throws IndexOutOfBoundsException If index is not between 0 and {@link * getNavigationListCurrentIndex}. - * @since 85 */ public boolean isNavigationEntrySkippable(int index) throws IndexOutOfBoundsException { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } checkNavigationIndex(index); try { return mNavigationController.isNavigationEntrySkippable(index);
diff --git a/weblayer/public/java/org/chromium/weblayer/PrerenderController.java b/weblayer/public/java/org/chromium/weblayer/PrerenderController.java index 80e0bbe8..d9b4f0a 100644 --- a/weblayer/public/java/org/chromium/weblayer/PrerenderController.java +++ b/weblayer/public/java/org/chromium/weblayer/PrerenderController.java
@@ -20,8 +20,6 @@ * is implemented using NoStatePrefetch and fetches resources needed for a url in advance, but does * not execute Javascript or render any part of the page in advance. For more information on * NoStatePrefetch, see https://developers.google.com/web/updates/2018/07/nostate-prefetch. - * - * @since 87 */ public class PrerenderController { private final IPrerenderController mImpl;
diff --git a/weblayer/public/java/org/chromium/weblayer/Profile.java b/weblayer/public/java/org/chromium/weblayer/Profile.java index 3f2176d70..2e3d295b 100644 --- a/weblayer/public/java/org/chromium/weblayer/Profile.java +++ b/weblayer/public/java/org/chromium/weblayer/Profile.java
@@ -47,14 +47,10 @@ throw new APICallException(e); } boolean isIncognito; - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - isIncognito = "".equals(name); - } else { - try { - isIncognito = impl.isIncognito(); - } catch (RemoteException e) { - throw new APICallException(e); - } + try { + isIncognito = impl.isIncognito(); + } catch (RemoteException e) { + throw new APICallException(e); } Profile profile; if (isIncognito) { @@ -102,11 +98,7 @@ mImpl = impl; mIsIncognito = isIncognito; mCookieManager = CookieManager.create(impl); - if (WebLayer.getSupportedMajorVersionInternal() >= 87) { - mPrerenderController = PrerenderController.create(impl); - } else { - mPrerenderController = null; - } + mPrerenderController = PrerenderController.create(impl); if (isIncognito) { sIncognitoProfiles.put(name, this); @@ -114,12 +106,10 @@ sProfiles.put(name, this); } - if (WebLayer.getSupportedMajorVersionInternal() >= 87) { - try { - mImpl.setClient(new ProfileClientImpl()); - } catch (RemoteException e) { - throw new APICallException(e); - } + try { + mImpl.setClient(new ProfileClientImpl()); + } catch (RemoteException e) { + throw new APICallException(e); } } @@ -127,8 +117,6 @@ * Returns the name of the profile. While added in 87, this can be used with any version. * * @return The name of the profile. - * - * @since 87 */ @NonNull public String getName() { @@ -140,8 +128,6 @@ * version. * * @return True if the profile is incognito. - * - * @since 87 */ public boolean isIncognito() { return mIsIncognito; @@ -193,8 +179,6 @@ * * @param completionCallback Callback that is notified when destruction and deletion of data is * complete. - * - * @since 82 */ public void destroyAndDeleteDataFromDisk(@Nullable Runnable completionCallback) { ThreadCheck.ensureOnUiThread(); @@ -227,14 +211,9 @@ * * @throws IllegalStateException If the Profile has already been destroyed. You can check for * that by looking for the profile in {@link #getAllProfiles()}. - * - * @since 87 */ public void destroyAndDeleteDataFromDiskSoon(@Nullable Runnable completionCallback) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } throwIfDestroyed(); try { mImpl.destroyAndDeleteDataFromDiskSoon(ObjectWrapper.wrap(completionCallback)); @@ -274,8 +253,6 @@ * download directory. * * @param directory the directory to place downloads in. - * - * @since 81 */ public void setDownloadDirectory(@NonNull File directory) { ThreadCheck.ensureOnUiThread(); @@ -290,8 +267,6 @@ * Allows embedders to control how downloads function. * * @param callback the callback interface implemented by the embedder. - * - * @since 83 */ public void setDownloadCallback(@Nullable DownloadCallback callback) { ThreadCheck.ensureOnUiThread(); @@ -310,8 +285,6 @@ /** * Gets the cookie manager for this profile. - * - * @since 83 */ @NonNull public CookieManager getCookieManager() { @@ -322,15 +295,9 @@ /** * Gets the prerender controller for this profile. - * - * @since 87 */ @NonNull public PrerenderController getPrerenderController() { - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } - ThreadCheck.ensureOnUiThread(); return mPrerenderController; } @@ -341,8 +308,6 @@ * * @param type See {@link SettingType}. * @param value The value to set for the setting. - * - * @since 84 */ public void setBooleanSetting(@SettingType int type, boolean value) { ThreadCheck.ensureOnUiThread(); @@ -356,8 +321,6 @@ /** * Returns the current value for the given setting type, see {@link SettingType} for more * details and the possible options. - * - * @since 84 */ public boolean getBooleanSetting(@SettingType int type) { ThreadCheck.ensureOnUiThread(); @@ -375,14 +338,9 @@ * @param callback The callback that is supplied the set of ids. * * @throws IllegalStateException If called on an in memory profile. - * - * @since 85 */ public void getBrowserPersistenceIds(@NonNull Callback<Set<String>> callback) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } if (mName.isEmpty()) { throw new IllegalStateException( "getBrowserPersistenceIds() is not applicable to in-memory profiles"); @@ -405,15 +363,10 @@ * * @throws IllegalStateException If called on an in memory profile. * @throws IllegalArgumentException if {@link ids} contains an empty/null string. - * - * @since 85 */ public void removeBrowserPersistenceStorage( @NonNull Set<String> ids, @NonNull Callback<Boolean> callback) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } if (mName.isEmpty()) { throw new IllegalStateException( "removetBrowserPersistenceStorage() is not applicable to in-memory profiles"); @@ -434,15 +387,9 @@ * safe to call this multiple times or when it is not certain that the spare renderer will be * used, although calling this too eagerly may reduce performance as unnecessary processes are * created. - * - * @since 85 */ public void prepareForPossibleCrossOriginNavigation() { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } - try { mImpl.prepareForPossibleCrossOriginNavigation(); } catch (RemoteException e) { @@ -456,14 +403,9 @@ * @param uri The uri to get the favicon for. * @param callback The callback that is notified of the bitmap. The bitmap passed to the * callback will be null if one is not available. - * - * @since 86 */ public void getCachedFaviconForPageUri(@NonNull Uri uri, @NonNull Callback<Bitmap> callback) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } try { mImpl.getCachedFaviconForPageUri( uri.toString(), ObjectWrapper.wrap((ValueCallback<Bitmap>) callback::onResult)); @@ -474,14 +416,9 @@ /** * See {@link UserIdentityCallback}. - * - * @since 87 */ public void setUserIdentityCallback(@Nullable UserIdentityCallback callback) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } try { mImpl.setUserIdentityCallbackClient( callback == null ? null : new UserIdentityCallbackClientImpl(callback));
diff --git a/weblayer/public/java/org/chromium/weblayer/ScrollOffsetCallback.java b/weblayer/public/java/org/chromium/weblayer/ScrollOffsetCallback.java index f661b0f..c537424c 100644 --- a/weblayer/public/java/org/chromium/weblayer/ScrollOffsetCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/ScrollOffsetCallback.java
@@ -14,8 +14,6 @@ * Because of WebLayer's multi-process architecture, this function can not be used to reliably * synchronize the painting of other Views with WebLayer's Views. It's entirely possible one will * render before or after the other. - * - * @since 87 */ public abstract class ScrollOffsetCallback { /**
diff --git a/weblayer/public/java/org/chromium/weblayer/SettingType.java b/weblayer/public/java/org/chromium/weblayer/SettingType.java index ea5900c6..0278c9f7 100644 --- a/weblayer/public/java/org/chromium/weblayer/SettingType.java +++ b/weblayer/public/java/org/chromium/weblayer/SettingType.java
@@ -20,15 +20,11 @@ /** * Allows the embedder to set whether it wants to disable/enable the Safe Browsing functionality * (which checks that the loaded URLs are safe). Safe Browsing is enabled by default. - * - * @since 84 */ int BASIC_SAFE_BROWSING_ENABLED = org.chromium.weblayer_private.interfaces.SettingType.BASIC_SAFE_BROWSING_ENABLED; /** * Allows the embedder to enable URL-Keyed Metrics. Disabled by default. - * - * @since 85 */ int UKM_ENABLED = org.chromium.weblayer_private.interfaces.SettingType.UKM_ENABLED; @@ -44,8 +40,6 @@ * * Note: this setting applies when Safe Browsing is enabled (i.e. BASIC_SAFE_BROWSING_ENABLED * is true). - * - * @since 85 */ int EXTENDED_REPORTING_SAFE_BROWSING_ENABLED = org.chromium.weblayer_private.interfaces.SettingType @@ -57,16 +51,12 @@ * * Note: this setting applies when Safe Browsing is enabled (i.e. BASIC_SAFE_BROWSING_ENABLED * is true). - * - * @since 85 */ int REAL_TIME_SAFE_BROWSING_ENABLED = org.chromium.weblayer_private.interfaces.SettingType.REAL_TIME_SAFE_BROWSING_ENABLED; /** * Allows the embedder to enable/disable NoStatePrefetch. Enabled by default. - * - * @since 86 */ int NETWORK_PREDICTION_ENABLED = org.chromium.weblayer_private.interfaces.SettingType.NETWORK_PREDICTION_ENABLED;
diff --git a/weblayer/public/java/org/chromium/weblayer/SiteSettingsActivity.java b/weblayer/public/java/org/chromium/weblayer/SiteSettingsActivity.java index bc78613..482c338 100644 --- a/weblayer/public/java/org/chromium/weblayer/SiteSettingsActivity.java +++ b/weblayer/public/java/org/chromium/weblayer/SiteSettingsActivity.java
@@ -24,7 +24,6 @@ /** * @deprecated Use SettingsActivity#createIntentForSiteSettingsCategoryList instead - * @since 87 */ @Deprecated public static Intent createIntentForCategoryList(
diff --git a/weblayer/public/java/org/chromium/weblayer/Tab.java b/weblayer/public/java/org/chromium/weblayer/Tab.java index b6bc28a7..605e8bd 100644 --- a/weblayer/public/java/org/chromium/weblayer/Tab.java +++ b/weblayer/public/java/org/chromium/weblayer/Tab.java
@@ -55,7 +55,6 @@ private final MediaCaptureController mMediaCaptureController; private final ObserverList<TabCallback> mCallbacks; private Browser mBrowser; - private Profile.DownloadCallbackClientImpl mDownloadCallbackClient; private FullscreenCallbackClientImpl mFullscreenCallbackClient; private NewTabCallback mNewTabCallback; private final ObserverList<ScrollOffsetCallback> mScrollOffsetCallbacks; @@ -63,10 +62,6 @@ // Id from the remote side. private final int mId; - // See comments in onTabDestroyed() for details. - // TODO(sky): this is necessary for < 87. Remove in 90. - private boolean mDestroyOnRemove; - // Constructor for test mocking. protected Tab() { mImpl = null; @@ -147,15 +142,10 @@ * active in its browser or its Fragment is not started. When a tab in this state loses its * renderer process to a crash (or due to system memory reclamation), it will automatically * reload next the time it becomes possibly visible. - * - * @since 87 */ public boolean willAutomaticallyReloadAfterCrash() { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } try { return mImpl.willAutomaticallyReloadAfterCrash(); } catch (RemoteException e) { @@ -170,25 +160,6 @@ return mBrowser; } - /** - * Deprecated. Use Profile.setDownloadCallback instead. - */ - public void setDownloadCallback(@Nullable DownloadCallback callback) { - ThreadCheck.ensureOnUiThread(); - throwIfDestroyed(); - try { - if (callback != null) { - mDownloadCallbackClient = new Profile.DownloadCallbackClientImpl(callback); - mImpl.setDownloadCallbackClient(mDownloadCallbackClient); - } else { - mDownloadCallbackClient = null; - mImpl.setDownloadCallbackClient(null); - } - } catch (RemoteException e) { - throw new APICallException(e); - } - } - public void setErrorPageCallback(@Nullable ErrorPageCallback callback) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); @@ -230,15 +201,10 @@ * page dynamically updates the favicon. * * @param callback The callback to notify of changes. - * - * @since 86 */ public @NonNull FaviconFetcher createFaviconFetcher(@NonNull FaviconCallback callback) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } return new FaviconFetcher(mImpl, callback); } @@ -249,14 +215,10 @@ * - Passing an empty string causes behavior to revert to default. * - Even with the target language specified, the translate UI will not trigger for pages in the * user's locale. - * @since 86 */ public void setTranslateTargetLanguage(@NonNull String targetLanguage) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } try { mImpl.setTranslateTargetLanguage(targetLanguage); } catch (RemoteException e) { @@ -309,8 +271,6 @@ * be asynchronous (but immediate) and will be notified in the same way. * * To close the tab synchronously without running beforeunload, use {@link Browser#destroyTab}. - * - * @since 82 */ public void dispatchBeforeUnloadAndClose() { ThreadCheck.ensureOnUiThread(); @@ -331,8 +291,6 @@ * such kind of UI would tend to be active at a time. * * @return true if some piece of UI was dismissed, or false if nothing happened. - * - * @since 82 */ public boolean dismissTransientUi() { ThreadCheck.ensureOnUiThread(); @@ -402,15 +360,10 @@ * for more details. * * @param callback The ScrollOffsetCallback to notify - * - * @since 87 */ public void registerScrollOffsetCallback(@NonNull ScrollOffsetCallback callback) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } if (mScrollOffsetCallbacks.isEmpty()) { try { mImpl.setScrollOffsetsEnabled(true); @@ -424,9 +377,6 @@ public void unregisterScrollOffsetCallback(@NonNull ScrollOffsetCallback callback) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } mScrollOffsetCallbacks.removeObserver(callback); if (mScrollOffsetCallbacks.isEmpty()) { try { @@ -452,7 +402,6 @@ * allow reentrancy. * @param scale Scale applied to the Bitmap. * @param resultCallback Called when operation is complete. - * @since 84 */ public void captureScreenShot(float scale, @NonNull CaptureScreenShotCallback callback) { ThreadCheck.ensureOnUiThread(); @@ -476,7 +425,6 @@ * Returns a unique id that persists across restarts. * * @return the unique id. - * @since 82 */ @NonNull public String getGuid() { @@ -497,15 +445,10 @@ * is taken, so any changes to the passed in object after this call will not be reflected. * * @throws IllegalArgumentException if the serialzed size of the data exceeds 4K. - * - * @since 85 */ public void setData(@NonNull Map<String, String> data) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } try { if (!mImpl.setData(data)) { throw new IllegalArgumentException("Data given to Tab.setData() was too large."); @@ -519,15 +462,11 @@ * Get arbitrary data set on the tab with setData(). * * @return the data or an empty map if no data was set. - * @since 85 */ @NonNull public Map<String, String> getData() { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } try { return (Map<String, String>) mImpl.getData(); } catch (RemoteException e) { @@ -539,15 +478,10 @@ * Sets a callback to intercept interaction with GAIA accounts. If this callback is set, any * link that would result in a change to a user's GAIA account state will trigger a call to * {@link GoogleAccountsCallback#onGoogleAccountsRequest}. - * - * @since 86 */ public void setGoogleAccountsCallback(@Nullable GoogleAccountsCallback callback) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - throw new UnsupportedOperationException(); - } try { mImpl.setGoogleAccountsCallbackClient( callback == null ? null : new GoogleAccountsCallbackClientImpl(callback)); @@ -693,16 +627,11 @@ * @param allowedOrigins The set of allowed origins. * * @throws IllegalArgumentException if jsObjectName or allowedOrigins is invalid. - * - * @since 85 */ public void registerWebMessageCallback(@NonNull WebMessageCallback callback, @NonNull String jsObjectName, @NonNull List<String> allowedOrigins) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } try { mImpl.registerWebMessageCallback( jsObjectName, allowedOrigins, new WebMessageCallbackClientImpl(callback)); @@ -716,14 +645,10 @@ * This impacts future navigations (not any already loaded navigations). * * @param jsObjectName Name of the JavaScript object. - * @since 85 */ public void unregisterWebMessageCallback(@NonNull String jsObjectName) { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } try { mImpl.unregisterWebMessageCallback(jsObjectName); } catch (RemoteException e) { @@ -733,15 +658,10 @@ /** * Returns true if the content displayed in this tab can be translated. - * - * @since 85 */ public boolean canTranslate() { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } try { return mImpl.canTranslate(); } catch (RemoteException e) { @@ -751,15 +671,10 @@ /** * Shows the UI which allows the user to translate the content displayed in this tab. - * - * @since 85 */ public void showTranslateUi() { ThreadCheck.ensureOnUiThread(); throwIfDestroyed(); - if (WebLayer.getSupportedMajorVersionInternal() < 85) { - throw new UnsupportedOperationException(); - } try { mImpl.showTranslateUi(); } catch (RemoteException e) { @@ -853,18 +768,6 @@ } } - // Called by Browser when removed. - void onRemovedFromBrowser() { - if (mDestroyOnRemove) { - // If this is destroyed as part of destroying the browser, then the tab has already been - // unregistered. - if (getTabById(mId) == this) unregisterTab(this); - mDestroyOnRemove = false; - mImpl = null; - mDestroyStack = new RuntimeException("onRemovedFromBrowser"); - } - } - private static final class WebMessageCallbackClientImpl extends IWebMessageCallbackClient.Stub { private final WebMessageCallback mCallback; // Maps from id of IWebMessageReplyProxy to WebMessageReplyProxy. This is done to avoid AIDL @@ -925,24 +828,11 @@ @Override public void onTabDestroyed() { - // Prior to 87 this was potentially called *before* onTabRemoved(). Post 87 this is - // called after onTabRemoved(). onTabRemoved() needs the Tab to be registered, so - // unregisterTab() should only be called in >= 87 (in < 87 it is called from - // Browser.prepareForDestroy()). - if (WebLayer.getSupportedMajorVersionInternal() >= 87) { - unregisterTab(Tab.this); - // Ensure that the app will fail fast if the embedder mistakenly tries to call back - // into the implementation via this Tab. - mImpl = null; - mDestroyStack = new RuntimeException("onTabDestroyed"); - } else { - // This Tab should not have been destroyed yet. - assert mImpl != null; - mDestroyOnRemove = true; - // If the tab isn't registered, it means the Browser fragment was destroyed, in - // which case there is no call to onTabRemoved(). - if (getTabById(mId) == null) onRemovedFromBrowser(); - } + unregisterTab(Tab.this); + // Ensure that the app will fail fast if the embedder mistakenly tries to call back + // into the implementation via this Tab. + mImpl = null; + mDestroyStack = new RuntimeException("onTabDestroyed"); } @Override
diff --git a/weblayer/public/java/org/chromium/weblayer/TabCallback.java b/weblayer/public/java/org/chromium/weblayer/TabCallback.java index 5b1ecf42..724d289 100644 --- a/weblayer/public/java/org/chromium/weblayer/TabCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/TabCallback.java
@@ -27,7 +27,6 @@ /** * Triggered when a context menu should be displayed. - * Added in M82. */ public void showContextMenu(@NonNull ContextMenuParams params) {} @@ -36,8 +35,6 @@ * due to the dismissal of a modal overlay (dialog/bubble/popup). * * @param isTabModalShowing true when a dialog is blocking interaction with the web contents. - * - * @since 82 */ public void onTabModalStateChanged(boolean isTabModalShowing) {} @@ -45,7 +42,6 @@ * Called when the title of this tab changes. Note before the page sets a title, the title may * be a portion of the Uri. * @param title New title of this tab. - * @since 83 */ public void onTitleUpdated(@NonNull String title) {} @@ -61,7 +57,6 @@ * This is mostly useful for filling in gaps around the web page during resize, but it will * not necessarily match the full background of the page. * @param color The new ARGB color of the page background. - * @since 85 */ public void onBackgroundColorChanged(int color) {} @@ -74,7 +69,6 @@ * @param currentScrollRatio value in [0, 1] indicating the current scroll ratio. For example * a web page that is 200 pixels, has a viewport of height 50 pixels * and a scroll offset of 50 pixels will have a ratio of 0.5. - * @since 85 */ public void onScrollNotification( @ScrollNotificationType int notificationType, float currentScrollRatio) {}
diff --git a/weblayer/public/java/org/chromium/weblayer/UrlBarController.java b/weblayer/public/java/org/chromium/weblayer/UrlBarController.java index 6ca2cbd..3628758 100644 --- a/weblayer/public/java/org/chromium/weblayer/UrlBarController.java +++ b/weblayer/public/java/org/chromium/weblayer/UrlBarController.java
@@ -31,16 +31,11 @@ /** * Creates a URL bar view based on the options provided. * @param options The options provided to tweak the URL bar display. - * @since 82 */ @NonNull public View createUrlBarView(@NonNull UrlBarOptions options) { ThreadCheck.ensureOnUiThread(); try { - if (WebLayer.getSupportedMajorVersionInternal() < 86) { - return ObjectWrapper.unwrap( - mImpl.deprecatedCreateUrlBarView(options.getBundle()), View.class); - } return ObjectWrapper.unwrap( mImpl.createUrlBarView(options.getBundle(), ObjectWrapper.wrap(options.getTextClickListener()),
diff --git a/weblayer/public/java/org/chromium/weblayer/UserIdentityCallback.java b/weblayer/public/java/org/chromium/weblayer/UserIdentityCallback.java index 5f09342..615386d1 100644 --- a/weblayer/public/java/org/chromium/weblayer/UserIdentityCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/UserIdentityCallback.java
@@ -14,8 +14,6 @@ * * If this callback is implemented and set on {@link Profile}, the information is used to better * organize contact details in the navigator.contacts UI. - * - * @since 87 */ public abstract class UserIdentityCallback { /** @@ -41,7 +39,6 @@ * @param avatarLoadedCallback to be called with the avatar when it is available (synchronously * or asynchronously). Until such time that it's called, WebLayer will fall back to a * monogram based on {@link getFullName()}, e.g. encircled "JD" for "Jill Doe". - * @since 87 */ public void getAvatar(int desiredSize, @NonNull ValueCallback<Bitmap> avatarLoadedCallback) {} }
diff --git a/weblayer/public/java/org/chromium/weblayer/WebLayer.java b/weblayer/public/java/org/chromium/weblayer/WebLayer.java index 62e78d6..f74eab47 100644 --- a/weblayer/public/java/org/chromium/weblayer/WebLayer.java +++ b/weblayer/public/java/org/chromium/weblayer/WebLayer.java
@@ -295,6 +295,9 @@ available = mFactory.isClientSupported(); majorVersion = mFactory.getImplementationMajorVersion(); version = mFactory.getImplementationVersion(); + if (available) { + available = majorVersion >= WebLayerVersionConstants.MIN_VERSION; + } // See comment in WebLayerFactoryImpl.isClientSupported() for details on this. if (available && WebLayerClientVersionConstants.PRODUCT_MAJOR_VERSION > majorVersion) { @@ -431,15 +434,10 @@ * Get or create the incognito profile with the name {@link profileName}. * * @param profileName The name of the profile. Null is mapped to an empty string. - * - * @since 87 */ @NonNull public Profile getIncognitoProfile(@Nullable String profileName) { ThreadCheck.ensureOnUiThread(); - if (WebLayer.getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } IProfile iprofile; try { iprofile = mImpl.getIncognitoProfile(sanitizeProfileName(profileName)); @@ -453,7 +451,6 @@ * Return a list of Profile names currently on disk. This does not include incognito * profiles. This will not include profiles that are being deleted from disk. * WebLayer must be initialized before calling this. - * @since 82 */ public void enumerateAllProfileNames(@NonNull Callback<String[]> callback) { ThreadCheck.ensureOnUiThread(); @@ -469,8 +466,6 @@ * Returns the user agent string used by WebLayer. * * @return The user-agent string. - * - * @since 84. */ public String getUserAgentString() { ThreadCheck.ensureOnUiThread(); @@ -527,8 +522,6 @@ * a directory name in the file system. * @param persistenceId If non-null and not empty uniquely identifies the Browser for saving * state. - * - * @since 81 */ @NonNull public static Fragment createBrowserFragment( @@ -548,8 +541,6 @@ * @throws UnsupportedOperationException If {@link params} is incognito and name is not empty * and <= 87. In order for this function not to trigger loading of WebLayer the * exception is thrown later on. - * - * @since 87 */ @NonNull public static Fragment createBrowserFragmentWithIncognitoProfile( @@ -582,8 +573,6 @@ * This method may be called multiple times to update experient IDs if they change. * * @param experimentIds An array of integer active experiment IDs relevant to WebLayer. - * - * @since 84 */ public void registerExternalExperimentIDs(@NonNull int[] experimentIds) { ThreadCheck.ensureOnUiThread(); @@ -641,9 +630,6 @@ */ /* package */ IMediaRouteDialogFragment connectMediaRouteDialogFragment( IRemoteFragmentClient remoteFragmentClient) { - if (getSupportedMajorVersionInternal() < 87) { - throw new UnsupportedOperationException(); - } try { return mImpl.createMediaRouteDialogFragmentImpl(remoteFragmentClient); } catch (RemoteException e) {
diff --git a/weblayer/public/java/org/chromium/weblayer/WebMessage.java b/weblayer/public/java/org/chromium/weblayer/WebMessage.java index 7fd27bd2..9cc3855 100644 --- a/weblayer/public/java/org/chromium/weblayer/WebMessage.java +++ b/weblayer/public/java/org/chromium/weblayer/WebMessage.java
@@ -8,8 +8,6 @@ /** * Used when sending and receiving messages to a page. - * - * @since 85 */ public class WebMessage { private final String mContents;
diff --git a/weblayer/public/java/org/chromium/weblayer/WebMessageCallback.java b/weblayer/public/java/org/chromium/weblayer/WebMessageCallback.java index bf35f5a4..2520721b 100644 --- a/weblayer/public/java/org/chromium/weblayer/WebMessageCallback.java +++ b/weblayer/public/java/org/chromium/weblayer/WebMessageCallback.java
@@ -9,8 +9,6 @@ /** * Receives messages from a JavaScript object that was created by calling {@link * Tab#registerWebMessageCallback(). - * - * @since 85 */ public abstract class WebMessageCallback { /**
diff --git a/weblayer/public/java/org/chromium/weblayer/WebMessageReplyProxy.java b/weblayer/public/java/org/chromium/weblayer/WebMessageReplyProxy.java index de9df58d..1b83ff8 100644 --- a/weblayer/public/java/org/chromium/weblayer/WebMessageReplyProxy.java +++ b/weblayer/public/java/org/chromium/weblayer/WebMessageReplyProxy.java
@@ -14,8 +14,6 @@ /** * Used to post a message to a page. WebMessageReplyProxy is created when a page posts a message to * the JavaScript object that was created by way of {@link Tab#registerWebMessageCallback}. - * - * @since 85 */ public class WebMessageReplyProxy { private final IWebMessageReplyProxy mIReplyProxy;
diff --git a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java index 1db38db..9f848b8 100644 --- a/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java +++ b/weblayer/shell/android/shell_apk/src/org/chromium/weblayer/shell/InstrumentationActivity.java
@@ -284,14 +284,9 @@ getIntent().getBooleanExtra(EXTRA_ONLY_EXPAND_CONTROLS_AT_TOP, false); final int minTopViewHeight = getIntent().getIntExtra(EXTRA_TOP_VIEW_MIN_HEIGHT, -1); - if (onlyExpandControlsAtTop || minTopViewHeight != -1) { - // This was added in 86. - mBrowser.setTopView(mTopContentsContainer, Math.max(0, minTopViewHeight), - onlyExpandControlsAtTop, - /* animate */ false); - } else { - mBrowser.setTopView(mTopContentsContainer); - } + mBrowser.setTopView(mTopContentsContainer, Math.max(0, minTopViewHeight), + onlyExpandControlsAtTop, + /* animate */ false); mRendererCrashListener = new TabCallback() { @Override