diff --git a/DEPS b/DEPS index a08e612b..efab3c42 100644 --- a/DEPS +++ b/DEPS
@@ -40,11 +40,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '31550dbc9804dafb18a71c968deb513cc8857cf3', + 'skia_revision': '6c3c1d621cb2bb3d9ed6087c8d5daaf9e2dc24b0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '973d0ea8a1dc71bcf43ffb85757f02232d66d040', + 'v8_revision': '2e442a5c2261d20a60f06a38a33331337185b9f8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '3919ea65c283bd0480b5c7fca196acc4d571fad4', + 'catapult_revision': 'a3798635175e53f40f7548875b4eb9cec5baf055', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/base/trace_event/memory_allocator_dump_guid.h b/base/trace_event/memory_allocator_dump_guid.h index b6472c6..2a420a2 100644 --- a/base/trace_event/memory_allocator_dump_guid.h +++ b/base/trace_event/memory_allocator_dump_guid.h
@@ -39,6 +39,10 @@ return !(*this == other); } + bool operator<(const MemoryAllocatorDumpGuid& other) const { + return guid_ < other.guid_; + } + private: uint64_t guid_;
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc index d81999c..cb8d5fa7 100644 --- a/base/trace_event/process_memory_dump.cc +++ b/base/trace_event/process_memory_dump.cc
@@ -301,8 +301,7 @@ other->allocator_dumps_.clear(); // Move all the edges. - allocator_dumps_edges_.insert(allocator_dumps_edges_.end(), - other->allocator_dumps_edges_.begin(), + allocator_dumps_edges_.insert(other->allocator_dumps_edges_.begin(), other->allocator_dumps_edges_.end()); other->allocator_dumps_edges_.clear(); @@ -341,7 +340,8 @@ } value->BeginArray("allocators_graph"); - for (const MemoryAllocatorDumpEdge& edge : allocator_dumps_edges_) { + for (const auto& it : allocator_dumps_edges_) { + const MemoryAllocatorDumpEdge& edge = it.second; value->BeginDictionary(); value->SetString("source", edge.source.ToString()); value->SetString("target", edge.target.ToString()); @@ -355,8 +355,10 @@ void ProcessMemoryDump::AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, const MemoryAllocatorDumpGuid& target, int importance) { - allocator_dumps_edges_.push_back( - {source, target, importance, kEdgeTypeOwnership}); + DCHECK(allocator_dumps_edges_.count(source) == 0 || + allocator_dumps_edges_[source].overridable); + allocator_dumps_edges_[source] = { + source, target, importance, kEdgeTypeOwnership, false /* overridable */}; } void ProcessMemoryDump::AddOwnershipEdge( @@ -365,6 +367,21 @@ AddOwnershipEdge(source, target, 0 /* importance */); } +void ProcessMemoryDump::AddOverridableOwnershipEdge( + const MemoryAllocatorDumpGuid& source, + const MemoryAllocatorDumpGuid& target, + int importance) { + if (allocator_dumps_edges_.count(source) == 0) { + allocator_dumps_edges_[source] = { + source, target, importance, kEdgeTypeOwnership, true /* overridable */}; + } else { + // An edge between the source and target already exits. So, do nothing here + // since the new overridable edge is implicitly overridden by a strong edge + // which was created earlier. + DCHECK(!allocator_dumps_edges_[source].overridable); + } +} + void ProcessMemoryDump::AddSuballocation(const MemoryAllocatorDumpGuid& source, const std::string& target_node_name) { // Do not create new dumps for suballocations in background mode.
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h index b16930f..ec82c10 100644 --- a/base/trace_event/process_memory_dump.h +++ b/base/trace_event/process_memory_dump.h
@@ -7,6 +7,7 @@ #include <stddef.h> +#include <map> #include <unordered_map> #include <vector> @@ -43,6 +44,7 @@ MemoryAllocatorDumpGuid target; int importance; const char* type; + bool overridable; }; // Maps allocator dumps absolute names (allocator_name/heap/subheap) to @@ -53,6 +55,10 @@ using HeapDumpsMap = std::unordered_map<std::string, std::unique_ptr<TracedValue>>; + // Stores allocator dump edges indexed by source allocator dump GUID. + using AllocatorDumpEdgesMap = + std::map<MemoryAllocatorDumpGuid, MemoryAllocatorDumpEdge>; + #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) // Returns the number of bytes in a kernel memory page. Some platforms may // have a different value for kernel page sizes from user page sizes. It is @@ -137,7 +143,14 @@ void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, const MemoryAllocatorDumpGuid& target); - const std::vector<MemoryAllocatorDumpEdge>& allocator_dumps_edges() const { + // Adds edges that can be overriden by a later or earlier call to + // AddOwnershipEdge() with the same source and target with a different + // |importance| value. + void AddOverridableOwnershipEdge(const MemoryAllocatorDumpGuid& source, + const MemoryAllocatorDumpGuid& target, + int importance); + + const AllocatorDumpEdgesMap& allocator_dumps_edges_for_testing() const { return allocator_dumps_edges_; } @@ -204,7 +217,7 @@ heap_profiler_serialization_state_; // Keeps track of relationships between MemoryAllocatorDump(s). - std::vector<MemoryAllocatorDumpEdge> allocator_dumps_edges_; + AllocatorDumpEdgesMap allocator_dumps_edges_; // Level of detail of the current dump. const MemoryDumpArgs dump_args_;
diff --git a/base/trace_event/process_memory_dump_unittest.cc b/base/trace_event/process_memory_dump_unittest.cc index 70f897c..4bddb61 100644 --- a/base/trace_event/process_memory_dump_unittest.cc +++ b/base/trace_event/process_memory_dump_unittest.cc
@@ -54,7 +54,7 @@ pmd1->Clear(); ASSERT_TRUE(pmd1->allocator_dumps().empty()); - ASSERT_TRUE(pmd1->allocator_dumps_edges().empty()); + ASSERT_TRUE(pmd1->allocator_dumps_edges_for_testing().empty()); ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad1")); ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad2")); ASSERT_FALSE(pmd1->has_process_totals()); @@ -126,7 +126,7 @@ // Make sure that pmd2 is empty but still usable after it has been emptied. ASSERT_TRUE(pmd2->allocator_dumps().empty()); - ASSERT_TRUE(pmd2->allocator_dumps_edges().empty()); + ASSERT_TRUE(pmd2->allocator_dumps_edges_for_testing().empty()); ASSERT_TRUE(pmd2->heap_dumps().empty()); pmd2->CreateAllocatorDump("pmd2/this_mad_stays_with_pmd2"); ASSERT_EQ(1u, pmd2->allocator_dumps().size()); @@ -147,7 +147,7 @@ ASSERT_EQ(1u, pmd1->allocator_dumps().count("pmd1/mad2")); ASSERT_EQ(1u, pmd1->allocator_dumps().count("pmd2/mad1")); ASSERT_EQ(1u, pmd1->allocator_dumps().count("pmd1/mad2")); - ASSERT_EQ(2u, pmd1->allocator_dumps_edges().size()); + ASSERT_EQ(2u, pmd1->allocator_dumps_edges_for_testing().size()); ASSERT_EQ(shared_mad1, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1)); ASSERT_EQ(shared_mad2, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2)); ASSERT_TRUE(MemoryAllocatorDump::Flags::WEAK & shared_mad2->flags()); @@ -164,6 +164,72 @@ pmd1.reset(); } +TEST(ProcessMemoryDumpTest, OverrideOwnershipEdge) { + std::unique_ptr<ProcessMemoryDump> pmd( + new ProcessMemoryDump(nullptr, kDetailedDumpArgs)); + + auto* shm_dump1 = pmd->CreateAllocatorDump("shared_mem/seg1"); + auto* shm_dump2 = pmd->CreateAllocatorDump("shared_mem/seg2"); + auto* shm_dump3 = pmd->CreateAllocatorDump("shared_mem/seg3"); + auto* shm_dump4 = pmd->CreateAllocatorDump("shared_mem/seg4"); + + // Create one allocation with an auto-assigned guid and mark it as a + // suballocation of "fakealloc/allocated_objects". + auto* child1_dump = pmd->CreateAllocatorDump("shared_mem/child/seg1"); + pmd->AddOverridableOwnershipEdge(child1_dump->guid(), shm_dump1->guid(), + 0 /* importance */); + auto* child2_dump = pmd->CreateAllocatorDump("shared_mem/child/seg2"); + pmd->AddOwnershipEdge(child2_dump->guid(), shm_dump2->guid(), + 3 /* importance */); + MemoryAllocatorDumpGuid shared_mad_guid(1); + pmd->CreateSharedGlobalAllocatorDump(shared_mad_guid); + pmd->AddOverridableOwnershipEdge(shm_dump3->guid(), shared_mad_guid, + 0 /* importance */); + auto* child4_dump = pmd->CreateAllocatorDump("shared_mem/child/seg4"); + pmd->AddOverridableOwnershipEdge(child4_dump->guid(), shm_dump4->guid(), + 4 /* importance */); + + const ProcessMemoryDump::AllocatorDumpEdgesMap& edges = + pmd->allocator_dumps_edges_for_testing(); + EXPECT_EQ(4u, edges.size()); + EXPECT_EQ(shm_dump1->guid(), edges.find(child1_dump->guid())->second.target); + EXPECT_EQ(0, edges.find(child1_dump->guid())->second.importance); + EXPECT_TRUE(edges.find(child1_dump->guid())->second.overridable); + EXPECT_EQ(shm_dump2->guid(), edges.find(child2_dump->guid())->second.target); + EXPECT_EQ(3, edges.find(child2_dump->guid())->second.importance); + EXPECT_FALSE(edges.find(child2_dump->guid())->second.overridable); + EXPECT_EQ(shared_mad_guid, edges.find(shm_dump3->guid())->second.target); + EXPECT_EQ(0, edges.find(shm_dump3->guid())->second.importance); + EXPECT_TRUE(edges.find(shm_dump3->guid())->second.overridable); + EXPECT_EQ(shm_dump4->guid(), edges.find(child4_dump->guid())->second.target); + EXPECT_EQ(4, edges.find(child4_dump->guid())->second.importance); + EXPECT_TRUE(edges.find(child4_dump->guid())->second.overridable); + + // These should override old edges: + pmd->AddOwnershipEdge(child1_dump->guid(), shm_dump1->guid(), + 1 /* importance */); + pmd->AddOwnershipEdge(shm_dump3->guid(), shared_mad_guid, 2 /* importance */); + // This should not change the old edges. + pmd->AddOverridableOwnershipEdge(child2_dump->guid(), shm_dump2->guid(), + 0 /* importance */); + pmd->AddOwnershipEdge(child4_dump->guid(), shm_dump4->guid(), + 0 /* importance */); + + EXPECT_EQ(4u, edges.size()); + EXPECT_EQ(shm_dump1->guid(), edges.find(child1_dump->guid())->second.target); + EXPECT_EQ(1, edges.find(child1_dump->guid())->second.importance); + EXPECT_FALSE(edges.find(child1_dump->guid())->second.overridable); + EXPECT_EQ(shm_dump2->guid(), edges.find(child2_dump->guid())->second.target); + EXPECT_EQ(3, edges.find(child2_dump->guid())->second.importance); + EXPECT_FALSE(edges.find(child2_dump->guid())->second.overridable); + EXPECT_EQ(shared_mad_guid, edges.find(shm_dump3->guid())->second.target); + EXPECT_EQ(2, edges.find(shm_dump3->guid())->second.importance); + EXPECT_FALSE(edges.find(shm_dump3->guid())->second.overridable); + EXPECT_EQ(shm_dump4->guid(), edges.find(child4_dump->guid())->second.target); + EXPECT_EQ(0, edges.find(child4_dump->guid())->second.importance); + EXPECT_FALSE(edges.find(child4_dump->guid())->second.overridable); +} + TEST(ProcessMemoryDumpTest, Suballocations) { std::unique_ptr<ProcessMemoryDump> pmd( new ProcessMemoryDump(nullptr, kDetailedDumpArgs)); @@ -193,11 +259,11 @@ // Finally check that AddSuballocation() has created also the // edges between the pictures and the anonymous allocator child dumps. bool found_edge[2]{false, false}; - for (const auto& e : pmd->allocator_dumps_edges()) { - found_edge[0] |= (e.source == pic1_dump->guid() && - e.target == anon_node_1_it->second->guid()); - found_edge[1] |= (e.source == pic2_dump->guid() && - e.target == anon_node_2_it->second->guid()); + for (const auto& e : pmd->allocator_dumps_edges_for_testing()) { + found_edge[0] |= (e.first == pic1_dump->guid() && + e.second.target == anon_node_1_it->second->guid()); + found_edge[1] |= (e.first == pic2_dump->guid() && + e.second.target == anon_node_2_it->second->guid()); } ASSERT_TRUE(found_edge[0]); ASSERT_TRUE(found_edge[1]);
diff --git a/build/check_gn_headers.py b/build/check_gn_headers.py index c5095e61..2c3a51a1 100755 --- a/build/check_gn_headers.py +++ b/build/check_gn_headers.py
@@ -19,12 +19,16 @@ import tempfile from multiprocessing import Process, Queue +SRC_DIR = os.path.abspath( + os.path.join(os.path.abspath(os.path.dirname(__file__)), os.path.pardir)) +DEPOT_TOOLS_DIR = os.path.join(SRC_DIR, 'third_party', 'depot_tools') + def GetHeadersFromNinja(out_dir, q): """Return all the header files from ninja_deps""" def NinjaSource(): - cmd = ['ninja', '-C', out_dir, '-t', 'deps'] + cmd = [os.path.join(DEPOT_TOOLS_DIR, 'ninja'), '-C', out_dir, '-t', 'deps'] # A negative bufsize means to use the system default, which usually # means fully buffered. popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=-1) @@ -82,7 +86,8 @@ shutil.copy2(os.path.join(out_dir, 'args.gn'), os.path.join(tmp, 'args.gn')) # Do "gn gen" in a temp dir to prevent dirtying |out_dir|. - subprocess.check_call(['gn', 'gen', tmp, '--ide=json', '-q']) + subprocess.check_call([ + os.path.join(DEPOT_TOOLS_DIR, 'gn'), 'gen', tmp, '--ide=json', '-q']) gn_json = json.load(open(os.path.join(tmp, 'project.json'))) ans = ParseGNProjectJSON(gn_json, out_dir, tmp) except Exception as e: @@ -118,9 +123,10 @@ """Return all the folders controlled by DEPS file""" prefixes, err = set(), None try: - gclient_out = subprocess.check_output( - ['gclient', 'recurse', '--no-progress', '-j1', - 'python', '-c', 'import os;print os.environ["GCLIENT_DEP_PATH"]']) + gclient_out = subprocess.check_output([ + os.path.join(DEPOT_TOOLS_DIR, 'gclient'), + 'recurse', '--no-progress', '-j1', + 'python', '-c', 'import os;print os.environ["GCLIENT_DEP_PATH"]']) for i in gclient_out.split('\n'): if i.startswith('src/'): i = i[4:] @@ -131,7 +137,7 @@ def IsBuildClean(out_dir): - cmd = ['ninja', '-C', out_dir, '-n'] + cmd = [os.path.join(DEPOT_TOOLS_DIR, 'ninja'), '-C', out_dir, '-n'] out = subprocess.check_output(cmd) return 'no work to do.' in out
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index cf617028..993571c 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1606,10 +1606,6 @@ deps = [ "//chrome/test/data:webui_test_resources", ] - if (!is_android && !is_ios) { - sources += [ "$root_gen_dir/chrome/options_test_resources.pak" ] - deps += [ "//chrome/browser/resources:options_test_resources" ] - } } group("strings") {
diff --git a/chrome/VERSION b/chrome/VERSION index 5459bd9..d346d67 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=61 MINOR=0 -BUILD=3123 +BUILD=3124 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTask.java index 9f894c8..3d1741b3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTask.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTask.java
@@ -35,8 +35,12 @@ */ @JNINamespace("offline_pages::prefetch") public class PrefetchBackgroundTask implements BackgroundTask { + public static final long DEFAULT_START_DELAY_SECONDS = 15 * 60; + private static final String TAG = "OPPrefetchBGTask"; + private static BackgroundTaskScheduler sSchedulerInstance; + private long mNativeTask = 0; private TaskFinishedCallback mTaskFinishedCallback = null; @@ -50,6 +54,13 @@ mProfile = profile; } + static BackgroundTaskScheduler getScheduler() { + if (sSchedulerInstance != null) { + return sSchedulerInstance; + } + return BackgroundTaskSchedulerFactory.getScheduler(); + } + /** * Schedules the default 'NWake' task for the prefetching service. * @@ -57,13 +68,13 @@ * TODO(dewittj): Handle skipping work if the battery percentage is too low. */ @CalledByNative - public static void scheduleTask() { - BackgroundTaskScheduler scheduler = BackgroundTaskSchedulerFactory.getScheduler(); + public static void scheduleTask(int additionalDelaySeconds) { TaskInfo taskInfo = TaskInfo.createOneOffTask(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID, PrefetchBackgroundTask.class, // Minimum time to wait - TimeUnit.MINUTES.toMillis(15), + TimeUnit.SECONDS.toMillis( + DEFAULT_START_DELAY_SECONDS + additionalDelaySeconds), // Maximum time to wait. After this interval the event will fire // regardless of whether the conditions are right. TimeUnit.DAYS.toMillis(7)) @@ -71,7 +82,7 @@ .setIsPersisted(true) .setUpdateCurrent(true) .build(); - scheduler.schedule(ContextUtils.getApplicationContext(), taskInfo); + getScheduler().schedule(ContextUtils.getApplicationContext(), taskInfo); } /** @@ -79,8 +90,7 @@ */ @CalledByNative public static void cancelTask() { - BackgroundTaskScheduler scheduler = BackgroundTaskSchedulerFactory.getScheduler(); - scheduler.cancel( + getScheduler().cancel( ContextUtils.getApplicationContext(), TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID); } @@ -161,7 +171,27 @@ } @VisibleForTesting + static void setSchedulerForTesting(BackgroundTaskScheduler scheduler) { + sSchedulerInstance = scheduler; + } + + @VisibleForTesting + void setTaskReschedulingForTesting(boolean reschedule, boolean backoff) { + if (mNativeTask == 0) return; + nativeSetTaskReschedulingForTesting(mNativeTask, reschedule, backoff); + } + + @VisibleForTesting + void signalTaskFinishedForTesting() { + if (mNativeTask == 0) return; + nativeSignalTaskFinishedForTesting(mNativeTask); + } + + @VisibleForTesting native boolean nativeStartPrefetchTask(Profile profile); @VisibleForTesting native boolean nativeOnStopTask(long nativePrefetchBackgroundTask); + native void nativeSetTaskReschedulingForTesting( + long nativePrefetchBackgroundTask, boolean reschedule, boolean backoff); + native void nativeSignalTaskFinishedForTesting(long nativePrefetchBackgroundTask); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java index 24a005e..12efeff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoPopup.java
@@ -90,11 +90,12 @@ */ public class PageInfoPopup implements OnClickListener { @Retention(RetentionPolicy.SOURCE) - @IntDef({OPENED_FROM_MENU, OPENED_FROM_TOOLBAR}) + @IntDef({OPENED_FROM_MENU, OPENED_FROM_TOOLBAR, OPENED_FROM_VR}) private @interface OpenedFromSource {} public static final int OPENED_FROM_MENU = 1; public static final int OPENED_FROM_TOOLBAR = 2; + public static final int OPENED_FROM_VR = 3; /** * An entry in the settings dropdown for a given permission. There are two options for each @@ -997,6 +998,8 @@ RecordUserAction.record("MobileWebsiteSettingsOpenedFromMenu"); } else if (source == OPENED_FROM_TOOLBAR) { RecordUserAction.record("MobileWebsiteSettingsOpenedFromToolbar"); + } else if (source == OPENED_FROM_VR) { + RecordUserAction.record("MobileWebsiteSettingsOpenedFromVR"); } else { assert false : "Invalid source passed"; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java index b0121f7..af5620d9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -51,6 +51,7 @@ import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.infobar.InfoBarIdentifier; import org.chromium.chrome.browser.infobar.SimpleConfirmInfoBarBuilder; +import org.chromium.chrome.browser.page_info.PageInfoPopup; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.util.IntentUtils; @@ -140,6 +141,9 @@ private Boolean mInVrAtChromeLaunch; private boolean mShowingDaydreamDoff; private boolean mDoffOptional; + // Whether we should show the PageInfo UI. This is shown when we force exit the user + // out of VR when they attempt to view the PageInfo. + private boolean mShouldShowPageInfo; private boolean mExitingCct; private boolean mPaused; private int mRestoreSystemUiVisibilityFlag = -1; @@ -486,6 +490,7 @@ case ActivityState.RESUMED: if (mInVr && activity != mActivity) { if (mShowingDaydreamDoff) { + mShouldShowPageInfo = false; onExitVrResult(true); } else { // We should never reach this state currently, but just in case... @@ -627,6 +632,7 @@ } mVrClassesWrapper.setVrModeEnabled(mActivity, true); mInVr = true; + mShouldShowPageInfo = false; // Lock orientation to landscape after enter VR. mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); @@ -899,8 +905,12 @@ // If Doff is not optional and user backed out, keep trying to exit. if (!mDoffOptional && !success && showDoff(false /* optional */)) return; + mShowingDaydreamDoff = false; if (success) { + if (mShouldShowPageInfo) { + sInstance.showPageInfoPopup(); + } shutdownVr(true /* disableVrMode */, false /* canReenter */, !mExitingCct /* stayingInChrome */); if (mExitingCct) ((CustomTabActivity) mActivity).finishAndClose(false); @@ -988,14 +998,23 @@ if (disableVrMode) mVrClassesWrapper.setVrModeEnabled(mActivity, false); promptForFeedbackIfNeeded(stayingInChrome); + // We don't want to show the PageInfo prompt if we return to Chrome + // after shutting down for reasons other than a successful DOFF (e.g. + // clicking the controller home button and returning to Chrome). + mShouldShowPageInfo = false; } - /* package */ void showDoffAndExitVr() { + /* package */ void showDoffAndExitVr(boolean optional) { if (mShowingDaydreamDoff) return; - if (showDoff(false /* optional */)) return; + if (showDoff(optional)) return; shutdownVr(true /* disableVrMode */, false /* canReenter */, true /* stayingInChrome */); } + /* package */ void onUnhandledPageInfo() { + mShouldShowPageInfo = true; + showDoffAndExitVr(true); + } + /* package */ void exitCct() { if (mShowingDaydreamDoff) return; assert mActivity instanceof CustomTabActivity; @@ -1010,6 +1029,15 @@ } } + private void showPageInfoPopup() { + assert mShouldShowPageInfo; + // Note: we don't set mShouldShowPageInfo to false here because we don't + // want to show the feedback prompt when the user exits VR to view PageInfo. So this gets + // reset in shutdownVr. + PageInfoPopup.show( + mActivity, mActivity.getActivityTab(), null, PageInfoPopup.OPENED_FROM_VR); + } + private static void startFeedback(Tab tab) { // TODO(ymalik): This call will connect to the Google Services api which can be slow. Can we // connect to it beforehand when we know that we'll be prompting for feedback? @@ -1051,12 +1079,14 @@ // 1) The user hasn't explicitly opted-out of it in the past // 2) The user has performed VR browsing // 3) The user is exiting VR and going back into 2D Chrome - // 4) Every n'th visit (where n = mFeedbackFrequency) + // 4) We're not exiting to complete an unsupported VR action in 2D (e.g. viewing PageInfo) + // 5) Every n'th visit (where n = mFeedbackFrequency) if (!activitySupportsExitFeedback(mActivity)) return; if (!stayingInChrome) return; if (VrFeedbackStatus.getFeedbackOptOut()) return; if (!mVrBrowserUsed) return; + if (mShouldShowPageInfo) return; int exitCount = VrFeedbackStatus.getUserExitedAndEntered2DCount(); VrFeedbackStatus.setUserExitedAndEntered2DCount((exitCount + 1) % mFeedbackFrequency);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java index 8bc205a..8824e21 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellImpl.java
@@ -357,7 +357,14 @@ // Exits VR, telling the user to remove their headset, and returning to Chromium. @CalledByNative public void forceExitVr() { - mDelegate.showDoffAndExitVr(); + mDelegate.showDoffAndExitVr(false); + } + + // Called because showing PageInfo isn't supported in VR. This happens when the user clicks on + // the security icon in the URL bar. + @CalledByNative + public void onUnhandledPageInfo() { + mDelegate.onUnhandledPageInfo(); } // Exits CCT, returning to the app that opened it.
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 0a8c250..d83835d 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1633,7 +1633,7 @@ Chrome needs permission to access your camera and microphone for this site. </message> <message name="IDS_INFOBAR_MISSING_LOCATION_PERMISSION_TEXT" desc="Text shown in an infobar when a website has requested access to the location capabilities, but Chrome is missing the Android location permission."> - Chrome needs access to to your location to share your location with this site. + Chrome needs access to your location to share your location with this site. </message> <message name="IDS_MISSING_STORAGE_PERMISSION_DOWNLOAD_EDUCATION_TEXT" desc="Text shown educating the user that Chrome is missing the Android storage permission, which is required to download files."> Chrome needs storage access to download files.
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 4a03177..1232e38 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1484,6 +1484,7 @@ "javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java", "javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java", "javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java", + "javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java", "javatests/src/org/chromium/chrome/browser/omaha/ExponentialBackoffSchedulerTest.java", "javatests/src/org/chromium/chrome/browser/omaha/MockExponentialBackoffScheduler.java", "javatests/src/org/chromium/chrome/browser/omaha/OmahaBaseTest.java", @@ -1760,7 +1761,7 @@ "junit/src/org/chromium/chrome/browser/offlinepages/ShadowDeviceConditions.java", "junit/src/org/chromium/chrome/browser/offlinepages/TaskExtrasPackerTest.java", "junit/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridgeTest.java", - "junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java", + "junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java", "junit/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java", "junit/src/org/chromium/chrome/browser/omaha/VersionNumberTest.java", "junit/src/org/chromium/chrome/browser/omnibox/AutocompleteEditTextTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java new file mode 100644 index 0000000..297ec35 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java
@@ -0,0 +1,296 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.offlinepages.prefetch; + +import android.content.Context; +import android.support.test.filters.SmallTest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ContextUtils; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.components.background_task_scheduler.BackgroundTask.TaskFinishedCallback; +import org.chromium.components.background_task_scheduler.BackgroundTaskScheduler; +import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerDelegate; +import org.chromium.components.background_task_scheduler.TaskIds; +import org.chromium.components.background_task_scheduler.TaskInfo; +import org.chromium.components.background_task_scheduler.TaskParameters; + +import java.util.HashMap; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +/** Unit tests for {@link PrefetchBackgroundTask}. */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) +public class PrefetchBackgroundTaskTest { + @Rule + public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = + new ChromeActivityTestRule<>(ChromeActivity.class); + + private static final double BACKOFF_JITTER_FACTOR = 0.33; + private static final int SEMAPHORE_TIMEOUT_MS = 5000; + private TestBackgroundTaskScheduler mScheduler; + + private static class TestPrefetchBackgroundTask extends PrefetchBackgroundTask { + private TaskInfo mTaskInfo; + private boolean mNeedsReschedule; + private Semaphore mStopSemaphore = new Semaphore(0); + + public TestPrefetchBackgroundTask(TaskInfo taskInfo) { + super(Profile.getLastUsedProfile()); + mTaskInfo = taskInfo; + } + + public void startTask(Context context, final TaskFinishedCallback callback) { + TaskParameters.Builder builder = + TaskParameters.create(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID); + TaskParameters params = builder.build(); + onStartTask(context, params, new TaskFinishedCallback() { + @Override + public void taskFinished(boolean needsReschedule) { + mNeedsReschedule = needsReschedule; + callback.taskFinished(needsReschedule); + mStopSemaphore.release(); + } + }); + } + + public void signalTaskFinished() { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + signalTaskFinishedForTesting(); + } + }); + } + + public void stopTask() { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + TaskParameters.Builder builder = + TaskParameters.create(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID); + TaskParameters params = builder.build(); + onStopTask(ContextUtils.getApplicationContext(), params); + } + }); + } + + public void setTaskRescheduling(final boolean reschedule, final boolean backoff) { + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + setTaskReschedulingForTesting(reschedule, backoff); + } + }); + } + + public void waitForTaskFinished() throws Exception { + assertTrue(mStopSemaphore.tryAcquire(SEMAPHORE_TIMEOUT_MS, TimeUnit.MILLISECONDS)); + } + + public TaskInfo taskInfo() { + return mTaskInfo; + } + public boolean needsReschedule() { + return mNeedsReschedule; + } + } + + private static class NoopBackgroundTaskSchedulerDelegate + implements BackgroundTaskSchedulerDelegate { + @Override + public boolean schedule(Context context, TaskInfo taskInfo) { + return true; + } + + @Override + public void cancel(Context context, int taskId) {} + } + + private static class TestBackgroundTaskScheduler extends BackgroundTaskScheduler { + private HashMap<Integer, TestPrefetchBackgroundTask> mTasks = new HashMap<>(); + private Semaphore mStartSemaphore = new Semaphore(0); + private int mAddCount = 0; + private int mRemoveCount = 0; + + public TestBackgroundTaskScheduler() { + super(new NoopBackgroundTaskSchedulerDelegate()); + } + + @Override + public boolean schedule(final Context context, final TaskInfo taskInfo) { + mAddCount++; + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + TestPrefetchBackgroundTask task = new TestPrefetchBackgroundTask(taskInfo); + mTasks.put(taskInfo.getTaskId(), task); + task.startTask(context, new TaskFinishedCallback() { + @Override + public void taskFinished(boolean needsReschedule) { + removeTask(taskInfo.getTaskId()); + } + }); + mStartSemaphore.release(); + } + }); + return true; + } + + @Override + public void cancel(Context context, int taskId) { + removeTask(taskId); + } + + public void waitForTaskStarted() throws Exception { + assertTrue(mStartSemaphore.tryAcquire(SEMAPHORE_TIMEOUT_MS, TimeUnit.MILLISECONDS)); + // Reset for next task. + mStartSemaphore = new Semaphore(0); + } + + public TestPrefetchBackgroundTask getTask(int taskId) { + return mTasks.get(taskId); + } + + public void removeTask(int taskId) { + mRemoveCount++; + mTasks.remove(taskId); + } + + public int addCount() { + return mAddCount; + } + public int removeCount() { + return mRemoveCount; + } + } + + TestPrefetchBackgroundTask validateAndGetScheduledTask(int additionalDelaySeconds) { + TestPrefetchBackgroundTask scheduledTask = + mScheduler.getTask(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID); + assertNotNull(scheduledTask); + TaskInfo scheduledTaskInfo = scheduledTask.taskInfo(); + assertEquals(true, scheduledTaskInfo.isPersisted()); + assertEquals(TaskInfo.NETWORK_TYPE_UNMETERED, scheduledTaskInfo.getRequiredNetworkType()); + + long defaultTaskStartTimeMs = + TimeUnit.SECONDS.toMillis(PrefetchBackgroundTask.DEFAULT_START_DELAY_SECONDS); + long currentTaskStartTimeMs = scheduledTaskInfo.getOneOffInfo().getWindowStartTimeMs(); + if (additionalDelaySeconds == 0) { + assertEquals(defaultTaskStartTimeMs, currentTaskStartTimeMs); + } else { + long maxTaskStartTimeMs = + defaultTaskStartTimeMs + TimeUnit.SECONDS.toMillis(additionalDelaySeconds); + assertTrue(currentTaskStartTimeMs <= maxTaskStartTimeMs); + assertTrue(currentTaskStartTimeMs >= maxTaskStartTimeMs * (1 - BACKOFF_JITTER_FACTOR)); + } + + return scheduledTask; + } + + @Before + public void setUp() throws Exception { + mActivityTestRule.startMainActivityOnBlankPage(); + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + mScheduler = new TestBackgroundTaskScheduler(); + PrefetchBackgroundTask.setSchedulerForTesting(mScheduler); + } + }); + } + + @Test + @SmallTest + public void testSchedule() throws Exception { + PrefetchBackgroundTask.scheduleTask(0); + mScheduler.waitForTaskStarted(); + TestPrefetchBackgroundTask task = validateAndGetScheduledTask(0); + task.signalTaskFinished(); + task.waitForTaskFinished(); + assertFalse(task.needsReschedule()); + } + + @Test + @SmallTest + public void testScheduleWithAdditionalDelay() throws Exception { + final int additionalDelaySeconds = 15; + PrefetchBackgroundTask.scheduleTask(additionalDelaySeconds); + mScheduler.waitForTaskStarted(); + TestPrefetchBackgroundTask task = validateAndGetScheduledTask(additionalDelaySeconds); + task.signalTaskFinished(); + task.waitForTaskFinished(); + assertFalse(task.needsReschedule()); + } + + @Test + @SmallTest + public void testReschedule() throws Exception { + PrefetchBackgroundTask.scheduleTask(0); + mScheduler.waitForTaskStarted(); + TestPrefetchBackgroundTask task = validateAndGetScheduledTask(0); + + // Requests a reschedule without backoff. + task.setTaskRescheduling(/*reschedule*/ true, /*backoff*/ false); + task.signalTaskFinished(); + task.waitForTaskFinished(); + assertTrue(task.needsReschedule()); + mScheduler.waitForTaskStarted(); + // No additional delay due to no backoff asked. + task = validateAndGetScheduledTask(0); + + // Requests a reschedule with backoff. + task.setTaskRescheduling(/*reschedule*/ true, /*backoff*/ true); + task.signalTaskFinished(); + task.waitForTaskFinished(); + assertTrue(task.needsReschedule()); + mScheduler.waitForTaskStarted(); + // Adding initial delay due to backoff. + task = validateAndGetScheduledTask(30); + + // Requests another reschedule with backoff. + task.setTaskRescheduling(/*reschedule*/ true, /*backoff*/ true); + task.signalTaskFinished(); + task.waitForTaskFinished(); + assertTrue(task.needsReschedule()); + mScheduler.waitForTaskStarted(); + // Delay doubled due to exponential backoff. + task = validateAndGetScheduledTask(60); + + // Simulate killing the task by the system. + task.stopTask(); + task.waitForTaskFinished(); + assertTrue(task.needsReschedule()); + mScheduler.waitForTaskStarted(); + // Additional delay is removed if it is killed by the system. + task = validateAndGetScheduledTask(0); + + // Finishes the task without rescheduling. + task.setTaskRescheduling(/*reschedule*/ false, /*backoff*/ false); + task.signalTaskFinished(); + task.waitForTaskFinished(); + assertFalse(task.needsReschedule()); + + assertEquals(5, mScheduler.addCount()); + assertEquals(5, mScheduler.removeCount()); + } +} \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java similarity index 87% rename from chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java rename to chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java index 14523810..3c84028 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskUnitTest.java
@@ -40,13 +40,14 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.concurrent.TimeUnit; /** Unit tests for {@link PrefetchBackgroundTask}. */ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE, - shadows = {PrefetchBackgroundTaskTest.ShadowBackgroundTaskScheduler.class, + shadows = {PrefetchBackgroundTaskUnitTest.ShadowBackgroundTaskScheduler.class, ShadowMultiDex.class}) -public class PrefetchBackgroundTaskTest { +public class PrefetchBackgroundTaskUnitTest { /** * Shadow of BackgroundTaskScheduler system service. */ @@ -103,10 +104,14 @@ @Test public void scheduleTask() { - PrefetchBackgroundTask.scheduleTask(); + final int additionalDelaySeconds = 15; + PrefetchBackgroundTask.scheduleTask(additionalDelaySeconds); TaskInfo scheduledTask = mShadowTaskScheduler.getTaskInfo(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID); assertNotNull(scheduledTask); + assertEquals(TimeUnit.SECONDS.toMillis(PrefetchBackgroundTask.DEFAULT_START_DELAY_SECONDS + + additionalDelaySeconds), + scheduledTask.getOneOffInfo().getWindowStartTimeMs()); assertEquals(true, scheduledTask.isPersisted()); assertEquals(TaskInfo.NETWORK_TYPE_UNMETERED, scheduledTask.getRequiredNetworkType()); } @@ -117,9 +122,11 @@ mShadowTaskScheduler.getTaskInfo(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID); assertNull(scheduledTask); - PrefetchBackgroundTask.scheduleTask(); + PrefetchBackgroundTask.scheduleTask(0); scheduledTask = mShadowTaskScheduler.getTaskInfo(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID); assertNotNull(scheduledTask); + assertEquals(TimeUnit.SECONDS.toMillis(PrefetchBackgroundTask.DEFAULT_START_DELAY_SECONDS), + scheduledTask.getOneOffInfo().getWindowStartTimeMs()); PrefetchBackgroundTask.cancelTask(); scheduledTask = mShadowTaskScheduler.getTaskInfo(TaskIds.OFFLINE_PAGES_PREFETCH_JOB_ID);
diff --git a/chrome/app/bookmarks_strings.grdp b/chrome/app/bookmarks_strings.grdp index 22d0be7..528b254 100644 --- a/chrome/app/bookmarks_strings.grdp +++ b/chrome/app/bookmarks_strings.grdp
@@ -419,6 +419,19 @@ <message name="IDS_MD_BOOKMARK_MANAGER_TITLE" desc="Title of the bookmark manager window."> Bookmarks </message> + <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_FOLDER_SORTED" desc="Label displayed in toast popup message when a folder's children are sorted."> + Folder sorted + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_ITEM_DELETED" desc="Label displayed in toast popup message when an item is deleted."> + '<ph name="DELETED_ITEM_NAME">$1</ph>' has been deleted + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_ITEMS_DELETED" desc="Label displayed in toast popup message when several items are deleted."> + {COUNT, plural, + other {# bookmarks deleted}} + </message> + <message name="IDS_MD_BOOKMARK_MANAGER_TOAST_URL_COPIED" desc="Label displayed in toast popup message when a URL is copied."> + URL copied + </message> <!-- End of material design Bookmarks Manager strings. --> <!-- Begin of Bookmarks Menu (in the Main Menu) strings. -->
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd index b304bf8..a2b2b26 100644 --- a/chrome/app/chromium_strings.grd +++ b/chrome/app/chromium_strings.grd
@@ -1218,7 +1218,7 @@ Chromium needs permission to access your camera and microphone for this site. </message> <message name="IDS_INFOBAR_MISSING_LOCATION_PERMISSION_TEXT" desc="Text shown in an infobar when a website has requested access to the location capabilities, but Chrome is missing the Android location permission."> - Chromium needs access to to your location to share your location with this site. + Chromium needs access to your location to share your location with this site. </message> <message name="IDS_MISSING_STORAGE_PERMISSION_DOWNLOAD_EDUCATION_TEXT" desc="Text shown educating the user that Chrome is missing the Android storage permission, which is required to download files."> Chromium needs storage access to download files.
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 94382382..49acb1b 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -12160,6 +12160,12 @@ <message name="IDS_VR_SHELL_NEW_INCOGNITO_TAB_BUTTON" desc="Text on the VR scene new incognito tab button"> New Incognito Tab </message> + <message name="IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION" desc="Text on the exit prompt that shows up when the user clicks on URL bar security icon in VR"> + Site information is not available in VR + </message> + <message name="IDS_VR_SHELL_EXIT_PROMPT_EXIT_VR_BUTTON" desc="Text on the exit button of the exit prompt that shows up when the user clicks on URL bar security icon in VR"> + EXIT VR + </message> </if> <!-- Safe Browsing Subresource Filter UI strings. -->
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd index ed18a2a..b3c93a2 100644 --- a/chrome/app/google_chrome_strings.grd +++ b/chrome/app/google_chrome_strings.grd
@@ -1228,7 +1228,7 @@ Chrome needs permission to access your camera and microphone for this site. </message> <message name="IDS_INFOBAR_MISSING_LOCATION_PERMISSION_TEXT" desc="Text shown in an infobar when a website has requested access to the location capabilities, but Chrome is missing the Android location permission."> - Chrome needs access to to your location to share your location with this site. + Chrome needs access to your location to share your location with this site. </message> <message name="IDS_MISSING_STORAGE_PERMISSION_DOWNLOAD_EDUCATION_TEXT" desc="Text shown educating the user that Chrome is missing the Android storage permission, which is required to download files."> Chrome needs storage access to download files.
diff --git a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc index 6e28422..6fe9189 100644 --- a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc +++ b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.cc
@@ -4,18 +4,34 @@ #include "chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h" +#include "base/time/time.h" #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_android.h" +#include "chrome/common/pref_names.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/browser_context.h" #include "jni/PrefetchBackgroundTask_jni.h" +#include "net/base/backoff_entry_serializer.h" using base::android::JavaParamRef; using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; namespace offline_pages { + +const net::BackoffEntry::Policy kBackoffPolicy = { + 0, // Number of initial errors to ignore without backoff. + 30 * 1000, // Initial delay for backoff in ms: 30 seconds. + 2, // Factor to multiply for exponential backoff. + 0.33, // Fuzzing percentage. + 24 * 3600 * 1000, // Maximum time to delay requests in ms: 1 day. + -1, // Don't discard entry even if unused. + false // Don't use initial delay unless the last was an error. +}; + namespace prefetch { // JNI call to start request processing in scheduled mode. @@ -31,16 +47,22 @@ return false; prefetch_service->GetPrefetchDispatcher()->BeginBackgroundTask( - base::MakeUnique<PrefetchBackgroundTask>(env, jcaller, prefetch_service)); - return true; + base::MakeUnique<PrefetchBackgroundTask>(env, jcaller, prefetch_service, + profile)); + return false; // true; } } // namespace prefetch +void RegisterPrefetchBackgroundTaskPrefs(PrefRegistrySimple* registry) { + registry->RegisterListPref(prefs::kOfflinePrefetchBackoff); +} + // static -void PrefetchBackgroundTask::Schedule() { +void PrefetchBackgroundTask::Schedule(int additional_delay_seconds) { JNIEnv* env = base::android::AttachCurrentThread(); - return prefetch::Java_PrefetchBackgroundTask_scheduleTask(env); + return prefetch::Java_PrefetchBackgroundTask_scheduleTask( + env, additional_delay_seconds); } // static @@ -52,29 +74,80 @@ PrefetchBackgroundTask::PrefetchBackgroundTask( JNIEnv* env, const JavaParamRef<jobject>& java_prefetch_background_task, - PrefetchService* service) + PrefetchService* service, + Profile* profile) : java_prefetch_background_task_(java_prefetch_background_task), - service_(service) { + service_(service), + profile_(profile) { // Give the Java side a pointer to the new background task object. prefetch::Java_PrefetchBackgroundTask_setNativeTask( env, java_prefetch_background_task_, reinterpret_cast<jlong>(this)); + + SetupBackOff(); } PrefetchBackgroundTask::~PrefetchBackgroundTask() { JNIEnv* env = base::android::AttachCurrentThread(); prefetch::Java_PrefetchBackgroundTask_doneProcessing( env, java_prefetch_background_task_.obj(), needs_reschedule_); + + if (needs_reschedule_) { + // If the task is killed due to the system, it should be rescheduled without + // backoff even when it is in effect because we want to rerun the task asap. + Schedule(task_killed_by_system_ ? 0 : GetAdditionalBackoffSeconds()); + } +} + +void PrefetchBackgroundTask::SetupBackOff() { + const base::ListValue* value = + profile_->GetPrefs()->GetList(prefs::kOfflinePrefetchBackoff); + if (value) { + backoff_ = net::BackoffEntrySerializer::DeserializeFromValue( + *value, &kBackoffPolicy, nullptr, base::Time::Now()); + } + + if (!backoff_) + backoff_ = base::MakeUnique<net::BackoffEntry>(&kBackoffPolicy); } bool PrefetchBackgroundTask::OnStopTask(JNIEnv* env, const JavaParamRef<jobject>& jcaller) { - DCHECK(jcaller.obj() == java_prefetch_background_task_.obj()); - service_->GetPrefetchDispatcher()->StopBackgroundTask(this); - return needs_reschedule_; + task_killed_by_system_ = true; + needs_reschedule_ = true; + service_->GetPrefetchDispatcher()->StopBackgroundTask(); + return false; } -void PrefetchBackgroundTask::SetNeedsReschedule(bool reschedule) { +void PrefetchBackgroundTask::SetTaskReschedulingForTesting( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jboolean reschedule, + jboolean backoff) { + SetNeedsReschedule(static_cast<bool>(reschedule), static_cast<bool>(backoff)); +} + +void PrefetchBackgroundTask::SignalTaskFinishedForTesting( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller) { + service_->GetPrefetchDispatcher()->RequestFinishBackgroundTaskForTest(); +} + +void PrefetchBackgroundTask::SetNeedsReschedule(bool reschedule, bool backoff) { needs_reschedule_ = reschedule; + + if (reschedule && backoff) + backoff_->InformOfRequest(false); + else + backoff_->Reset(); + + std::unique_ptr<base::Value> value = + net::BackoffEntrySerializer::SerializeToValue(*backoff_, + base::Time::Now()); + profile_->GetPrefs()->Set(prefs::kOfflinePrefetchBackoff, *value); +} + +int PrefetchBackgroundTask::GetAdditionalBackoffSeconds() const { + return static_cast<int>(backoff_->GetTimeUntilRelease().InSeconds()); } bool RegisterPrefetchBackgroundTask(JNIEnv* env) {
diff --git a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h index b1b74cd..06e4978 100644 --- a/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h +++ b/chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h
@@ -7,6 +7,11 @@ #include "base/android/jni_android.h" #include "components/offline_pages/core/prefetch/prefetch_dispatcher.h" +#include "components/offline_pages/core/prefetch/prefetch_service.h" +#include "net/base/backoff_entry.h" + +class PrefRegistrySimple; +class Profile; namespace offline_pages { class PrefetchService; @@ -19,12 +24,13 @@ PrefetchBackgroundTask( JNIEnv* env, const base::android::JavaParamRef<jobject>& j_prefetch_background_task, - PrefetchService* service); + PrefetchService* service, + Profile* profile); ~PrefetchBackgroundTask() override; // API for interacting with BackgroundTaskScheduler from native. // Schedules the default 'NWake' prefetching task. - static void Schedule(); + static void Schedule(int additional_delay_seconds); // Cancels the default 'NWake' prefetching task. static void Cancel(); @@ -32,24 +38,42 @@ // Java hooks. bool OnStopTask(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); + void SetTaskReschedulingForTesting( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller, + jboolean reschedule, + jboolean backoff); + void SignalTaskFinishedForTesting( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jcaller); // When this task completes, we tell the system whether the task should be - // rescheduled with the same parameters as last time. - void SetNeedsReschedule(bool reschedule) override; + // rescheduled with or without backoff. + void SetNeedsReschedule(bool reschedule, bool backoff) override; bool needs_reschedule() { return needs_reschedule_; } private: - bool needs_reschedule_ = true; + void SetupBackOff(); + int GetAdditionalBackoffSeconds() const; + + bool task_killed_by_system_ = false; + bool needs_reschedule_ = false; // A pointer to the controlling |PrefetchBackgroundTask|. base::android::ScopedJavaGlobalRef<jobject> java_prefetch_background_task_; // The PrefetchService owns |this|, so a raw pointer is OK. PrefetchService* service_; + + Profile* profile_; + + std::unique_ptr<net::BackoffEntry> backoff_; }; bool RegisterPrefetchBackgroundTask(JNIEnv* env); +void RegisterPrefetchBackgroundTaskPrefs(PrefRegistrySimple* registry); + } // namespace offline_pages #endif // CHROME_BROWSER_ANDROID_OFFLINE_PAGES_PREFETCH_PREFETCH_BACKGROUND_TASK_H_
diff --git a/chrome/browser/android/vr_shell/BUILD.gn b/chrome/browser/android/vr_shell/BUILD.gn index 4dedfb9..c886e77a 100644 --- a/chrome/browser/android/vr_shell/BUILD.gn +++ b/chrome/browser/android/vr_shell/BUILD.gn
@@ -33,6 +33,8 @@ "textures/button_texture.h", "textures/close_button_texture.cc", "textures/close_button_texture.h", + "textures/exit_prompt_texture.cc", + "textures/exit_prompt_texture.h", "textures/exit_warning_texture.cc", "textures/exit_warning_texture.h", "textures/insecure_content_permanent_texture.cc", @@ -54,6 +56,8 @@ "ui_elements/audio_capture_indicator.h", "ui_elements/button.cc", "ui_elements/button.h", + "ui_elements/exit_prompt.cc", + "ui_elements/exit_prompt.h", "ui_elements/exit_warning.cc", "ui_elements/exit_warning.h", "ui_elements/loading_indicator.cc", @@ -198,6 +202,7 @@ "test/paths.h", "textures/close_button_texture_unittest.cc", "textures/url_bar_texture_unittest.cc", + "ui_elements/exit_prompt_unittest.cc", "ui_elements/ui_element_unittest.cc", "ui_scene_manager_unittest.cc", "ui_scene_unittest.cc", @@ -211,6 +216,7 @@ "//skia", "//testing/gmock", "//testing/gtest", + "//ui/gfx:test_support", "//ui/gfx/geometry", "//ui/gl", ]
diff --git a/chrome/browser/android/vr_shell/color_scheme.cc b/chrome/browser/android/vr_shell/color_scheme.cc index 56ec5db3..9478a7c 100644 --- a/chrome/browser/android/vr_shell/color_scheme.cc +++ b/chrome/browser/android/vr_shell/color_scheme.cc
@@ -47,6 +47,13 @@ normal_scheme.system_indicator_foreground = normal_scheme.permanent_warning_foreground; normal_scheme.separator = 0xFF9E9E9E; + normal_scheme.prompt_foreground = 0xCC000000; + normal_scheme.prompt_primary_button_background = 0xBFFFFFFF; + normal_scheme.prompt_secondary_button_background = 0x66FFFFFF; + normal_scheme.prompt_primary_button_forground = 0xA6000000; + normal_scheme.prompt_secondary_button_foreground = 0xA6000000; + normal_scheme.prompt_button_background_down = 0xE6FFFFFF; + normal_scheme.prompt_button_background_hover = 0xFFFFFFFF; normal_scheme.secure = gfx::kGoogleGreen700; normal_scheme.insecure = gfx::kGoogleRed700; normal_scheme.warning = 0xFF5A5A5A; @@ -85,6 +92,13 @@ incognito_scheme.warning = incognito_scheme.secure; incognito_scheme.url_emphasized = incognito_scheme.secure; incognito_scheme.url_deemphasized = 0xFF878787; + incognito_scheme.prompt_foreground = 0xCCFFFFFF; + incognito_scheme.prompt_primary_button_background = 0xD9FFFFFF; + incognito_scheme.prompt_secondary_button_background = 0x80FFFFFF; + incognito_scheme.prompt_primary_button_forground = 0xD9000000; + incognito_scheme.prompt_secondary_button_foreground = 0xD9000000; + incognito_scheme.prompt_button_background_hover = 0xFF8C8C8C; + incognito_scheme.prompt_button_background_down = 0xE6FFFFFF; incognito_scheme.disabled = 0x33E6E6E6; initialized = true;
diff --git a/chrome/browser/android/vr_shell/color_scheme.h b/chrome/browser/android/vr_shell/color_scheme.h index 8457c81..1db6df5 100644 --- a/chrome/browser/android/vr_shell/color_scheme.h +++ b/chrome/browser/android/vr_shell/color_scheme.h
@@ -50,6 +50,15 @@ SkColor system_indicator_background; SkColor system_indicator_foreground; + // The colors used for text and buttons on prompts. + SkColor prompt_foreground; + SkColor prompt_primary_button_background; + SkColor prompt_secondary_button_background; + SkColor prompt_primary_button_forground; + SkColor prompt_secondary_button_foreground; + SkColor prompt_button_background_hover; + SkColor prompt_button_background_down; + // If you have a segmented element, its separators should use this color. SkColor separator;
diff --git a/chrome/browser/android/vr_shell/textures/exit_prompt_texture.cc b/chrome/browser/android/vr_shell/textures/exit_prompt_texture.cc new file mode 100644 index 0000000..52d59558 --- /dev/null +++ b/chrome/browser/android/vr_shell/textures/exit_prompt_texture.cc
@@ -0,0 +1,174 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/vr_shell/textures/exit_prompt_texture.h" + +#include "cc/paint/skia_paint_canvas.h" +#include "chrome/browser/android/vr_shell/color_scheme.h" +#include "chrome/grit/generated_resources.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/font_list.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/vector2d.h" +#include "ui/gfx/render_text.h" + +namespace vr_shell { + +namespace { + +constexpr float kWidth = 0.672; +constexpr float kHeight = 0.2; +constexpr float kButtonWidth = 0.162; +constexpr float kButtonHeight = 0.066; +constexpr float kPromptTextButtonSeperatorHeight = 0.04; +constexpr float kButtonsSeperatorWidth = 0.01; +constexpr float kButtonRadiusFactor = 0.006; +constexpr float kFontSizePromptText = 0.027; +constexpr float kFontSizePromptButtonText = 0.024; + +} // namespace + +ExitPromptTexture::ExitPromptTexture() = default; + +ExitPromptTexture::~ExitPromptTexture() = default; + +void ExitPromptTexture::Draw(SkCanvas* sk_canvas, + const gfx::Size& texture_size) { + size_.set_width(texture_size.width()); + size_.set_height(texture_size.height()); + + cc::SkiaPaintCanvas paint_canvas(sk_canvas); + gfx::Canvas gfx_canvas(&paint_canvas, 1.0f); + gfx::Canvas* canvas = &gfx_canvas; + + // Prompt text area. + auto text = l10n_util::GetStringUTF16(IDS_VR_SHELL_EXIT_PROMPT_DESCRIPTION); + gfx::FontList fonts; + GetFontList(ToPixels(kFontSizePromptText), text, &fonts); + gfx::Rect prompt_text_size(size_.width(), 0); + std::vector<std::unique_ptr<gfx::RenderText>> lines = PrepareDrawStringRect( + text, fonts, color_scheme().prompt_foreground, &prompt_text_size, + kTextAlignmentCenter, kWrappingBehaviorWrap); + for (auto& render_text : lines) + render_text->Draw(canvas); + + SkPaint paint; + gfx::Rect button_text_size(ToPixels(kButtonWidth), 0); + float radius = size_.width() * kButtonRadiusFactor; + GetFontList(ToPixels(kFontSizePromptButtonText), text, &fonts); + + // Secondary button area. + text = l10n_util::GetStringUTF16(IDS_VR_SHELL_EXIT_PROMPT_EXIT_VR_BUTTON); + lines = PrepareDrawStringRect( + text, fonts, color_scheme().prompt_secondary_button_foreground, + &button_text_size, kTextAlignmentCenter, kWrappingBehaviorWrap); + secondary_button_rect_.SetRect( + ToPixels(kWidth / 2 - kButtonsSeperatorWidth - kButtonWidth), + prompt_text_size.height() + ToPixels(kPromptTextButtonSeperatorHeight), + ToPixels(kButtonWidth), ToPixels(kButtonHeight)); + paint.setColor(GetSecondaryButtonColor()); + canvas->Save(); + canvas->Translate( + gfx::Vector2d(secondary_button_rect_.x(), secondary_button_rect_.y())); + sk_canvas->drawRoundRect( + SkRect::MakeXYWH(0, 0, ToPixels(kButtonWidth), ToPixels(kButtonHeight)), + radius, radius, paint); + canvas->Translate(gfx::Vector2d( + 0, ToPixels(kButtonHeight) / 2 - button_text_size.height() / 2)); + for (auto& render_text : lines) + render_text->Draw(canvas); + canvas->Restore(); + + // Primary button area. + text = l10n_util::GetStringUTF16(IDS_OK); + button_text_size.set_size(gfx::Size(ToPixels(kButtonWidth), 0)); + lines = PrepareDrawStringRect( + text, fonts, color_scheme().prompt_primary_button_forground, + &button_text_size, kTextAlignmentCenter, kWrappingBehaviorWrap); + primary_button_rect_.SetRect( + ToPixels(kWidth / 2 + kButtonsSeperatorWidth), + prompt_text_size.height() + ToPixels(kPromptTextButtonSeperatorHeight), + ToPixels(kButtonWidth), ToPixels(kButtonHeight)); + paint.setColor(GetPrimaryButtonColor()); + canvas->Save(); + canvas->Translate( + gfx::Vector2d(primary_button_rect_.x(), primary_button_rect_.y())); + sk_canvas->drawRoundRect( + SkRect::MakeXYWH(0, 0, ToPixels(kButtonWidth), ToPixels(kButtonHeight)), + radius, radius, paint); + canvas->Translate(gfx::Vector2d( + 0, ToPixels(kButtonHeight) / 2 - button_text_size.height() / 2)); + for (auto& render_text : lines) + render_text->Draw(canvas); + canvas->Restore(); +} + +float ExitPromptTexture::ToPixels(float meters) const { + return meters * size_.width() / kWidth; +} + +gfx::PointF ExitPromptTexture::PercentToPixels( + const gfx::PointF& percent) const { + return gfx::PointF(percent.x() * size_.width(), percent.y() * size_.height()); +} + +SkColor ExitPromptTexture::GetPrimaryButtonColor() const { + if (primary_pressed_) + return color_scheme().prompt_button_background_down; + if (primary_hovered_) + return color_scheme().prompt_button_background_hover; + return color_scheme().prompt_primary_button_background; +} + +SkColor ExitPromptTexture::GetSecondaryButtonColor() const { + if (secondary_pressed_) + return color_scheme().prompt_button_background_down; + if (secondary_hovered_) + return color_scheme().prompt_button_background_hover; + return color_scheme().prompt_secondary_button_background; +} + +bool ExitPromptTexture::HitsPrimaryButton(const gfx::PointF& position) const { + return primary_button_rect_.Contains(PercentToPixels(position)); +} + +bool ExitPromptTexture::HitsSecondaryButton(const gfx::PointF& position) const { + return secondary_button_rect_.Contains(PercentToPixels(position)); +} + +void ExitPromptTexture::SetPrimaryButtonHovered(bool hovered) { + if (primary_hovered_ != hovered) + set_dirty(); + primary_hovered_ = hovered; +} + +void ExitPromptTexture::SetPrimaryButtonPressed(bool pressed) { + if (primary_pressed_ != pressed) + set_dirty(); + primary_pressed_ = pressed; +} + +void ExitPromptTexture::SetSecondaryButtonHovered(bool hovered) { + if (secondary_hovered_ != hovered) + set_dirty(); + secondary_hovered_ = hovered; +} + +void ExitPromptTexture::SetSecondaryButtonPressed(bool pressed) { + if (secondary_pressed_ != pressed) + set_dirty(); + secondary_pressed_ = pressed; +} + +gfx::Size ExitPromptTexture::GetPreferredTextureSize(int maximum_width) const { + return gfx::Size(maximum_width, maximum_width * kHeight / kWidth); +} + +gfx::SizeF ExitPromptTexture::GetDrawnSize() const { + return size_; +} + +} // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/textures/exit_prompt_texture.h b/chrome/browser/android/vr_shell/textures/exit_prompt_texture.h new file mode 100644 index 0000000..8a64040 --- /dev/null +++ b/chrome/browser/android/vr_shell/textures/exit_prompt_texture.h
@@ -0,0 +1,55 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_VR_SHELL_TEXTURES_EXIT_PROMPT_TEXTURE_H_ +#define CHROME_BROWSER_ANDROID_VR_SHELL_TEXTURES_EXIT_PROMPT_TEXTURE_H_ + +#include "base/macros.h" +#include "chrome/browser/android/vr_shell/textures/ui_texture.h" +#include "ui/gfx/geometry/rect_f.h" + +namespace gfx { +class PointF; +} // namespace gfx + +namespace vr_shell { + +class ExitPromptTexture : public UiTexture { + public: + ExitPromptTexture(); + ~ExitPromptTexture() override; + gfx::Size GetPreferredTextureSize(int width) const override; + gfx::SizeF GetDrawnSize() const override; + + void SetPrimaryButtonHovered(bool hovered); + void SetPrimaryButtonPressed(bool pressed); + void SetSecondaryButtonHovered(bool hovered); + void SetSecondaryButtonPressed(bool pressed); + + virtual bool HitsSecondaryButton(const gfx::PointF& position) const; + virtual bool HitsPrimaryButton(const gfx::PointF& position) const; + + private: + void Draw(SkCanvas* sk_canvas, const gfx::Size& texture_size) override; + + SkColor GetPrimaryButtonColor() const; + SkColor GetSecondaryButtonColor() const; + float ToPixels(float meters) const; + gfx::PointF PercentToPixels(const gfx::PointF& percent) const; + + gfx::RectF secondary_button_rect_; + gfx::RectF primary_button_rect_; + gfx::SizeF size_; + + bool primary_hovered_ = false; + bool primary_pressed_ = false; + bool secondary_hovered_ = false; + bool secondary_pressed_ = false; + + DISALLOW_COPY_AND_ASSIGN(ExitPromptTexture); +}; + +} // namespace vr_shell + +#endif // CHROME_BROWSER_ANDROID_VR_SHELL_TEXTURES_EXIT_PROMPT_TEXTURE_H_
diff --git a/chrome/browser/android/vr_shell/textures/url_bar_texture.cc b/chrome/browser/android/vr_shell/textures/url_bar_texture.cc index 91a06654..698f4a7ef 100644 --- a/chrome/browser/android/vr_shell/textures/url_bar_texture.cc +++ b/chrome/browser/android/vr_shell/textures/url_bar_texture.cc
@@ -142,6 +142,19 @@ return rect.Contains(meters) && !HitsTransparentRegion(meters, false); } +gfx::PointF UrlBarTexture::SecurityIconPositionMeters() const { + float x = kBackButtonWidth + kSeparatorWidth + kSecurityFieldWidth / 2 - + kSecurityIconHeight / 2; + float y = kHeight / 2 - kSecurityIconHeight / 2; + return gfx::PointF(x, y); +} + +bool UrlBarTexture::HitsSecurityIcon(const gfx::PointF& position) const { + gfx::RectF rect(SecurityIconPositionMeters(), + gfx::SizeF(kSecurityIconHeight, kSecurityIconHeight)); + return rect.Contains(percentToMeters(position)); +} + bool UrlBarTexture::HitsTransparentRegion(const gfx::PointF& meters, bool left) const { const float radius = kHeight / 2.0f; @@ -222,10 +235,8 @@ // Site security state icon. if (!gurl_.is_empty()) { canvas->save(); - canvas->translate( - kBackButtonWidth + kSeparatorWidth + kSecurityFieldWidth / 2, - kHeight / 2); - canvas->translate(-kSecurityIconHeight / 2, -kSecurityIconHeight / 2); + gfx::PointF icon_position = SecurityIconPositionMeters(); + canvas->translate(icon_position.x(), icon_position.y()); const gfx::VectorIcon& icon = getSecurityIcon(security_level_); icon_default_height = GetDefaultSizeOfVectorIcon(icon); icon_scale = kSecurityIconHeight / icon_default_height;
diff --git a/chrome/browser/android/vr_shell/textures/url_bar_texture.h b/chrome/browser/android/vr_shell/textures/url_bar_texture.h index a077e733..e4e6626 100644 --- a/chrome/browser/android/vr_shell/textures/url_bar_texture.h +++ b/chrome/browser/android/vr_shell/textures/url_bar_texture.h
@@ -44,6 +44,7 @@ bool HitsBackButton(const gfx::PointF& position) const; bool HitsUrlBar(const gfx::PointF& position) const; + bool HitsSecurityIcon(const gfx::PointF& position) const; void SetHovered(bool hovered); void SetPressed(bool pressed); @@ -61,6 +62,7 @@ bool HitsTransparentRegion(const gfx::PointF& meters, bool left) const; void RenderUrl(const gfx::Size& texture_size, const gfx::Rect& bounds); void OnSetMode() override; + gfx::PointF SecurityIconPositionMeters() const; gfx::SizeF size_; bool hovered_ = false;
diff --git a/chrome/browser/android/vr_shell/ui_elements/exit_prompt.cc b/chrome/browser/android/vr_shell/ui_elements/exit_prompt.cc new file mode 100644 index 0000000..909fd59 --- /dev/null +++ b/chrome/browser/android/vr_shell/ui_elements/exit_prompt.cc
@@ -0,0 +1,75 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/vr_shell/ui_elements/exit_prompt.h" + +#include "base/memory/ptr_util.h" +#include "chrome/browser/android/vr_shell/textures/exit_prompt_texture.h" + +namespace vr_shell { + +ExitPrompt::ExitPrompt(int preferred_width, + const base::Callback<void()>& primary_button_callback, + const base::Callback<void()>& secondary_buttton_callback) + : TexturedElement(preferred_width), + texture_(base::MakeUnique<ExitPromptTexture>()), + primary_button_callback_(primary_button_callback), + secondary_buttton_callback_(secondary_buttton_callback) {} + +ExitPrompt::~ExitPrompt() = default; + +void ExitPrompt::SetTextureForTesting(ExitPromptTexture* texture) { + texture_.reset(texture); +} + +void ExitPrompt::OnHoverEnter(const gfx::PointF& position) { + OnStateUpdated(position); +} + +void ExitPrompt::OnHoverLeave() { + OnStateUpdated(gfx::PointF(std::numeric_limits<float>::max(), + std::numeric_limits<float>::max())); +} + +void ExitPrompt::OnMove(const gfx::PointF& position) { + OnStateUpdated(position); +} + +void ExitPrompt::OnButtonDown(const gfx::PointF& position) { + if (texture_->HitsPrimaryButton(position)) + primary_down_ = true; + else if (texture_->HitsSecondaryButton(position)) + secondary_down_ = true; + OnStateUpdated(position); +} + +void ExitPrompt::OnButtonUp(const gfx::PointF& position) { + if (primary_down_ && texture_->HitsPrimaryButton(position)) + primary_button_callback_.Run(); + else if (secondary_down_ && texture_->HitsSecondaryButton(position)) + secondary_buttton_callback_.Run(); + + primary_down_ = false; + secondary_down_ = false; + + OnStateUpdated(position); +} + +void ExitPrompt::OnStateUpdated(const gfx::PointF& position) { + const bool primary_hovered = texture_->HitsPrimaryButton(position); + const bool secondary_hovered = texture_->HitsSecondaryButton(position); + + texture_->SetPrimaryButtonHovered(primary_hovered); + texture_->SetPrimaryButtonPressed(primary_hovered ? primary_down_ : false); + texture_->SetSecondaryButtonHovered(secondary_hovered); + texture_->SetSecondaryButtonPressed(secondary_hovered ? secondary_down_ + : false); + UpdateTexture(); +} + +UiTexture* ExitPrompt::GetTexture() const { + return texture_.get(); +} + +} // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_elements/exit_prompt.h b/chrome/browser/android/vr_shell/ui_elements/exit_prompt.h new file mode 100644 index 0000000..51d44da7 --- /dev/null +++ b/chrome/browser/android/vr_shell/ui_elements/exit_prompt.h
@@ -0,0 +1,51 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_VR_SHELL_UI_ELEMENTS_EXIT_PROMPT_H_ +#define CHROME_BROWSER_ANDROID_VR_SHELL_UI_ELEMENTS_EXIT_PROMPT_H_ + +#include <memory> + +#include "base/callback.h" +#include "base/macros.h" +#include "chrome/browser/android/vr_shell/ui_elements/textured_element.h" + +namespace vr_shell { + +class ExitPromptTexture; + +class ExitPrompt : public TexturedElement { + public: + ExitPrompt(int preferred_width, + const base::Callback<void()>& primary_button_callback, + const base::Callback<void()>& secondary_buttton_callback); + ~ExitPrompt() override; + + void SetTextureForTesting(ExitPromptTexture* texture); + + void OnHoverEnter(const gfx::PointF& position) override; + void OnHoverLeave() override; + void OnMove(const gfx::PointF& position) override; + void OnButtonDown(const gfx::PointF& position) override; + void OnButtonUp(const gfx::PointF& position) override; + + private: + UiTexture* GetTexture() const override; + + void OnStateUpdated(const gfx::PointF& position); + + bool primary_down_ = false; + bool secondary_down_ = false; + + std::unique_ptr<ExitPromptTexture> texture_; + + base::Callback<void()> primary_button_callback_; + base::Callback<void()> secondary_buttton_callback_; + + DISALLOW_COPY_AND_ASSIGN(ExitPrompt); +}; + +} // namespace vr_shell + +#endif // CHROME_BROWSER_ANDROID_VR_SHELL_UI_ELEMENTS_EXIT_PROMPT_H_
diff --git a/chrome/browser/android/vr_shell/ui_elements/exit_prompt_unittest.cc b/chrome/browser/android/vr_shell/ui_elements/exit_prompt_unittest.cc new file mode 100644 index 0000000..8d651168 --- /dev/null +++ b/chrome/browser/android/vr_shell/ui_elements/exit_prompt_unittest.cc
@@ -0,0 +1,102 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/vr_shell/ui_elements/exit_prompt.h" + +#include "base/bind.h" +#include "base/macros.h" +#include "base/memory/ptr_util.h" +#include "chrome/browser/android/vr_shell/textures/exit_prompt_texture.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/test/gfx_util.h" + +using ::testing::Return; + +namespace vr_shell { + +namespace { + +class MockExitPromptTexture : public ExitPromptTexture { + public: + MockExitPromptTexture() : ExitPromptTexture() {} + ~MockExitPromptTexture() override {} + + MOCK_CONST_METHOD1(HitsPrimaryButton, bool(const gfx::PointF&)); + MOCK_CONST_METHOD1(HitsSecondaryButton, bool(const gfx::PointF&)); + + MOCK_CONST_METHOD1(GetPreferredTextureSize, gfx::Size(int)); + MOCK_CONST_METHOD0(GetDrawnSize, gfx::SizeF()); + MOCK_METHOD2(Draw, void(SkCanvas*, const gfx::Size&)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockExitPromptTexture); +}; + +} // namespace + +class TestExitPrompt : public ExitPrompt { + public: + TestExitPrompt(); + ~TestExitPrompt() override {} + + bool primary_button_pressed() const { return primary_button_pressed_; } + bool secondary_button_pressed() const { return secondary_button_pressed_; } + + private: + void OnPrimaryButtonPressed() { primary_button_pressed_ = true; } + void OnSecondaryButtonPressed() { secondary_button_pressed_ = true; } + + bool primary_button_pressed_ = false; + bool secondary_button_pressed_ = false; +}; + +TestExitPrompt::TestExitPrompt() + : ExitPrompt(512, + base::Bind(&TestExitPrompt::OnPrimaryButtonPressed, + base::Unretained(this)), + base::Bind(&TestExitPrompt::OnSecondaryButtonPressed, + base::Unretained(this))) {} + +TEST(ExitPromptTest, PrimaryButtonCallbackCalled) { + TestExitPrompt prompt; + MockExitPromptTexture* texture = new MockExitPromptTexture(); + // Called twice from OnButtonDown and twice from OnButtonUp. + EXPECT_CALL(*texture, HitsPrimaryButton(gfx::PointF())) + .Times(4) + .WillRepeatedly(Return(true)); + // Called once from OnButtonDown and once from OnButtonUp (via OnStatUpdated). + EXPECT_CALL(*texture, HitsSecondaryButton(gfx::PointF())) + .Times(2) + .WillRepeatedly(Return(false)); + prompt.SetTextureForTesting(std::move(texture)); + + prompt.OnButtonDown(gfx::PointF()); + prompt.OnButtonUp(gfx::PointF()); + + EXPECT_TRUE(prompt.primary_button_pressed()); + EXPECT_FALSE(prompt.secondary_button_pressed()); +} + +TEST(ExitPromptTest, SecondaryButtonCallbackCalled) { + TestExitPrompt prompt; + MockExitPromptTexture* texture = new MockExitPromptTexture(); + // Called twice from OnButtonDown and once from OnButtonUp. + EXPECT_CALL(*texture, HitsPrimaryButton(gfx::PointF())) + .Times(3) + .WillRepeatedly(Return(false)); + // Called twice from OnButtonDown and twice from OnButtonUp. + EXPECT_CALL(*texture, HitsSecondaryButton(gfx::PointF())) + .Times(4) + .WillRepeatedly(Return(true)); + prompt.SetTextureForTesting(std::move(texture)); + + prompt.OnButtonDown(gfx::PointF()); + prompt.OnButtonUp(gfx::PointF()); + + EXPECT_FALSE(prompt.primary_button_pressed()); + EXPECT_TRUE(prompt.secondary_button_pressed()); +} + +} // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h b/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h index d32d8280..e43db65 100644 --- a/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h +++ b/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h
@@ -25,6 +25,7 @@ kCloseButton, kScreenDimmer, kExitWarning, + kExitPrompt, }; } // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_elements/url_bar.cc b/chrome/browser/android/vr_shell/ui_elements/url_bar.cc index 34ab3538..87fe7867 100644 --- a/chrome/browser/android/vr_shell/ui_elements/url_bar.cc +++ b/chrome/browser/android/vr_shell/ui_elements/url_bar.cc
@@ -20,9 +20,13 @@ } // namespace UrlBar::UrlBar(int preferred_width, + const base::Callback<void()>& back_button_callback, + const base::Callback<void()>& security_icon_callback, const base::Callback<void(UiUnsupportedMode)>& failure_callback) : TexturedElement(preferred_width), - texture_(base::MakeUnique<UrlBarTexture>(failure_callback)) {} + texture_(base::MakeUnique<UrlBarTexture>(failure_callback)), + back_button_callback_(back_button_callback), + security_icon_callback_(security_icon_callback) {} UrlBar::~UrlBar() = default; @@ -51,6 +55,8 @@ void UrlBar::OnButtonDown(const gfx::PointF& position) { if (texture_->HitsBackButton(position)) down_ = true; + else if (texture_->HitsSecurityIcon(position)) + security_icon_down_ = true; OnStateUpdated(position); } @@ -59,6 +65,9 @@ OnStateUpdated(position); if (can_go_back_ && texture_->HitsBackButton(position)) back_button_callback_.Run(); + else if (security_icon_down_ && texture_->HitsSecurityIcon(position)) + security_icon_callback_.Run(); + security_icon_down_ = false; } bool UrlBar::HitTest(const gfx::PointF& position) const { @@ -92,10 +101,6 @@ texture_->SetSecurityLevel(level); } -void UrlBar::SetBackButtonCallback(const base::Callback<void()>& callback) { - back_button_callback_ = callback; -} - void UrlBar::OnStateUpdated(const gfx::PointF& position) { const bool hovered = texture_->HitsBackButton(position); const bool pressed = hovered ? down_ : false;
diff --git a/chrome/browser/android/vr_shell/ui_elements/url_bar.h b/chrome/browser/android/vr_shell/ui_elements/url_bar.h index 5c28acb8..77ee9784 100644 --- a/chrome/browser/android/vr_shell/ui_elements/url_bar.h +++ b/chrome/browser/android/vr_shell/ui_elements/url_bar.h
@@ -22,6 +22,8 @@ class UrlBar : public TexturedElement { public: UrlBar(int preferred_width, + const base::Callback<void()>& back_button_callback, + const base::Callback<void()>& security_icon_callback, const base::Callback<void(UiUnsupportedMode)>& failure_callback); ~UrlBar() override; @@ -38,7 +40,6 @@ void SetHistoryButtonsEnabled(bool can_go_back); void SetURL(const GURL& gurl); void SetSecurityLevel(security_state::SecurityLevel level); - void SetBackButtonCallback(const base::Callback<void()>& callback); private: void UpdateTexture() override; @@ -47,9 +48,11 @@ std::unique_ptr<UrlBarTexture> texture_; base::Callback<void()> back_button_callback_; + base::Callback<void()> security_icon_callback_; bool enabled_ = false; bool can_go_back_ = false; bool down_ = false; + bool security_icon_down_ = false; base::TimeTicks last_begin_frame_time_; base::TimeTicks last_update_time_;
diff --git a/chrome/browser/android/vr_shell/ui_scene.cc b/chrome/browser/android/vr_shell/ui_scene.cc index 40ce66c4..f3caf40 100644 --- a/chrome/browser/android/vr_shell/ui_scene.cc +++ b/chrome/browser/android/vr_shell/ui_scene.cc
@@ -212,6 +212,10 @@ is_exiting_ = true; } +void UiScene::set_is_prompting_to_exit(bool prompting) { + is_prompting_to_exit_ = prompting; +} + const std::vector<std::unique_ptr<UiElement>>& UiScene::GetUiElements() const { return ui_elements_; }
diff --git a/chrome/browser/android/vr_shell/ui_scene.h b/chrome/browser/android/vr_shell/ui_scene.h index 3b6f508..df949d2c 100644 --- a/chrome/browser/android/vr_shell/ui_scene.h +++ b/chrome/browser/android/vr_shell/ui_scene.h
@@ -80,6 +80,8 @@ bool is_exiting() const { return is_exiting_; } void set_is_exiting(); + bool is_prompting_to_exit() { return is_prompting_to_exit_; } + void set_is_prompting_to_exit(bool prompting); void OnGLInitialized(); @@ -95,6 +97,7 @@ bool webvr_rendering_enabled_ = true; bool gl_initialized_ = false; bool is_exiting_ = false; + bool is_prompting_to_exit_ = false; DISALLOW_COPY_AND_ASSIGN(UiScene); };
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.cc b/chrome/browser/android/vr_shell/ui_scene_manager.cc index 619a61f29..f3f9026b 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager.cc +++ b/chrome/browser/android/vr_shell/ui_scene_manager.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/android/vr_shell/ui_browser_interface.h" #include "chrome/browser/android/vr_shell/ui_elements/audio_capture_indicator.h" #include "chrome/browser/android/vr_shell/ui_elements/button.h" +#include "chrome/browser/android/vr_shell/ui_elements/exit_prompt.h" #include "chrome/browser/android/vr_shell/ui_elements/exit_warning.h" #include "chrome/browser/android/vr_shell/ui_elements/loading_indicator.h" #include "chrome/browser/android/vr_shell/ui_elements/permanent_security_warning.h" @@ -51,6 +52,10 @@ static constexpr float kFullscreenWidth = 1.138 * kFullscreenDistance; static constexpr float kFullscreenVerticalOffset = -0.1 * kFullscreenDistance; +static constexpr float kExitPromptWidth = 0.672 * kContentDistance; +static constexpr float kExitPromptHeight = 0.2 * kContentDistance; +static constexpr float kExitPromptVerticalOffset = -0.09 * kContentDistance; + static constexpr float kUrlBarDistance = 2.4; static constexpr float kUrlBarWidth = 0.672 * kUrlBarDistance; static constexpr float kUrlBarHeight = 0.088 * kUrlBarDistance; @@ -224,9 +229,26 @@ element->set_size({kBackplaneSize, kBackplaneSize, 1.0}); element->set_translation({0.0, 0.0, -kTextureOffset}); element->set_parent_id(main_content_->id()); + main_content_backplane_ = element.get(); content_elements_.push_back(element.get()); scene_->AddUiElement(std::move(element)); + element = base::MakeUnique<ExitPrompt>( + 512, + base::Bind(&UiSceneManager::OnExitPromptPrimaryButtonClicked, + base::Unretained(this)), + base::Bind(&UiSceneManager::OnExitPromptSecondaryButtonClicked, + base::Unretained(this))); + element->set_debug_id(kExitPrompt); + element->set_id(AllocateId()); + element->set_fill(vr_shell::Fill::NONE); + element->set_size({kExitPromptWidth, kExitPromptHeight, 1}); + element->set_translation({0.0, kExitPromptVerticalOffset, kTextureOffset}); + element->set_parent_id(main_content_->id()); + element->set_visible(false); + exit_prompt_ = element.get(); + scene_->AddUiElement(std::move(element)); + // Limit reticle distance to a sphere based on content distance. scene_->SetBackgroundDistance(main_content_->translation().z() * -kBackgroundDistanceMultiplier); @@ -246,7 +268,7 @@ element->set_draw_phase(0); element->set_gridline_count(kFloorGridlineCount); floor_ = element.get(); - content_elements_.push_back(element.get()); + background_elements_.push_back(element.get()); scene_->AddUiElement(std::move(element)); // Ceiling. @@ -259,7 +281,7 @@ element->set_fill(vr_shell::Fill::OPAQUE_GRADIENT); element->set_draw_phase(0); ceiling_ = element.get(); - content_elements_.push_back(element.get()); + background_elements_.push_back(element.get()); scene_->AddUiElement(std::move(element)); UpdateBackgroundColor(); @@ -269,14 +291,15 @@ // TODO(cjgrant): Incorporate final size and position. auto url_bar = base::MakeUnique<UrlBar>( 512, + base::Bind(&UiSceneManager::OnBackButtonClicked, base::Unretained(this)), + base::Bind(&UiSceneManager::OnSecurityIconClicked, + base::Unretained(this)), base::Bind(&UiSceneManager::OnUnsupportedMode, base::Unretained(this))); url_bar->set_debug_id(kUrlBar); url_bar->set_id(AllocateId()); url_bar->set_translation({0, kUrlBarVerticalOffset, -kUrlBarDistance}); url_bar->set_rotation({1.0, 0.0, 0.0, kUrlBarRotationRad}); url_bar->set_size({kUrlBarWidth, kUrlBarHeight, 1}); - url_bar->SetBackButtonCallback( - base::Bind(&UiSceneManager::OnBackButtonClicked, base::Unretained(this))); url_bar_ = url_bar.get(); control_elements_.push_back(url_bar.get()); scene_->AddUiElement(std::move(url_bar)); @@ -326,12 +349,13 @@ void UiSceneManager::ConfigureScene() { exit_warning_->SetEnabled(scene_->is_exiting()); + exit_prompt_->SetEnabled(scene_->is_prompting_to_exit()); screen_dimmer_->SetEnabled(scene_->is_exiting()); // Controls (URL bar, loading progress, etc). bool controls_visible = !web_vr_mode_ && !fullscreen_; for (UiElement* element : control_elements_) { - element->SetEnabled(controls_visible); + element->SetEnabled(controls_visible && !scene_->is_prompting_to_exit()); } // Close button is a special control element that needs to be hidden when in @@ -339,7 +363,10 @@ close_button_->SetEnabled(!web_vr_mode_ && (fullscreen_ || in_cct_)); // Content elements. - for (UiElement* element : content_elements_) { + main_content_->SetEnabled(!web_vr_mode_ && !scene_->is_prompting_to_exit()); + main_content_backplane_->SetEnabled(!web_vr_mode_); + // Background elements. + for (UiElement* element : background_elements_) { element->SetEnabled(!web_vr_mode_); } @@ -448,6 +475,24 @@ browser_->NavigateBack(); } +void UiSceneManager::OnSecurityIconClicked() { + if (scene_->is_prompting_to_exit()) + return; + scene_->set_is_prompting_to_exit(true); + ConfigureScene(); +} + +void UiSceneManager::OnExitPromptPrimaryButtonClicked() { + if (!scene_->is_prompting_to_exit()) + return; + scene_->set_is_prompting_to_exit(false); + ConfigureScene(); +} + +void UiSceneManager::OnExitPromptSecondaryButtonClicked() { + OnUnsupportedMode(UiUnsupportedMode::kUnhandledPageInfo); +} + void UiSceneManager::SetURL(const GURL& gurl) { url_bar_->SetURL(gurl); }
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.h b/chrome/browser/android/vr_shell/ui_scene_manager.h index f6abe57..c870835b 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager.h +++ b/chrome/browser/android/vr_shell/ui_scene_manager.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_ANDROID_VR_SHELL_UI_SCENE_MANAGER_H_ #define CHROME_BROWSER_ANDROID_VR_SHELL_UI_SCENE_MANAGER_H_ +#include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" @@ -52,6 +53,8 @@ void OnAppButtonGesturePerformed(UiInterface::Direction direction); private: + FRIEND_TEST_ALL_PREFIXES(UiSceneManagerTest, UiUpdatesExitPrompt); + void CreateScreenDimmer(); void CreateSecurityWarnings(); void CreateSystemIndicators(); @@ -59,13 +62,15 @@ void CreateBackground(); void CreateUrlBar(); void CreateCloseButton(); - void CreateExitWarning(); void ConfigureScene(); void ConfigureSecurityWarnings(); void UpdateBackgroundColor(); void OnSecurityWarningTimer(); void OnBackButtonClicked(); + void OnSecurityIconClicked(); + void OnExitPromptPrimaryButtonClicked(); + void OnExitPromptSecondaryButtonClicked(); void OnCloseButtonClicked(); void OnUnsupportedMode(UiUnsupportedMode mode); int AllocateId(); @@ -78,8 +83,10 @@ // UI element pointers (not owned by the scene manager). UiElement* permanent_security_warning_ = nullptr; UiElement* transient_security_warning_ = nullptr; + UiElement* exit_prompt_ = nullptr; UiElement* exit_warning_ = nullptr; UiElement* main_content_ = nullptr; + UiElement* main_content_backplane_ = nullptr; UiElement* audio_capture_indicator_ = nullptr; UiElement* video_capture_indicator_ = nullptr; UiElement* screen_capture_indicator_ = nullptr; @@ -95,7 +102,6 @@ bool secure_origin_ = false; bool fullscreen_ = false; bool incognito_ = false; - bool is_exiting_ = false; bool audio_capturing_ = false; bool video_capturing_ = false; bool screen_capturing_ = false; @@ -103,6 +109,7 @@ int next_available_id_ = 1; std::vector<UiElement*> content_elements_; + std::vector<UiElement*> background_elements_; std::vector<UiElement*> control_elements_; base::OneShotTimer security_warning_timer_;
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc index f5745451..5744214 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc +++ b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc
@@ -14,8 +14,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -using testing::InSequence; - namespace vr_shell { namespace { @@ -35,6 +33,9 @@ DISALLOW_COPY_AND_ASSIGN(MockBrowserInterface); }; +std::set<UiElementDebugId> kElementsVisibleInBrowsing = { + kContentQuad, kBackplane, kCeiling, kFloor, kUrlBar, kLoadingIndicator}; + } // namespace class UiSceneManagerTest : public testing::Test { @@ -195,14 +196,8 @@ } TEST_F(UiSceneManagerTest, UiUpdatesForFullscreenChanges) { - std::set<UiElementDebugId> visible_in_browsing = { - UiElementDebugId::kContentQuad, UiElementDebugId::kBackplane, - UiElementDebugId::kCeiling, UiElementDebugId::kFloor, - UiElementDebugId::kUrlBar, UiElementDebugId::kLoadingIndicator}; std::set<UiElementDebugId> visible_in_fullscreen = { - UiElementDebugId::kContentQuad, UiElementDebugId::kCloseButton, - UiElementDebugId::kBackplane, UiElementDebugId::kCeiling, - UiElementDebugId::kFloor}; + kContentQuad, kCloseButton, kBackplane, kCeiling, kFloor}; MakeManager(kNotInCct, kNotInWebVr); @@ -211,8 +206,9 @@ for (const auto& element : scene_->GetUiElements()) { SCOPED_TRACE(element->debug_id()); - bool should_be_visible = visible_in_browsing.find(element->debug_id()) != - visible_in_browsing.end(); + bool should_be_visible = + kElementsVisibleInBrowsing.find(element->debug_id()) != + kElementsVisibleInBrowsing.end(); EXPECT_EQ(should_be_visible, element->visible()); } @@ -239,8 +235,9 @@ // Everything should return to original state after leaving fullscreen. for (const auto& element : scene_->GetUiElements()) { SCOPED_TRACE(element->debug_id()); - bool should_be_visible = visible_in_browsing.find(element->debug_id()) != - visible_in_browsing.end(); + bool should_be_visible = + kElementsVisibleInBrowsing.find(element->debug_id()) != + kElementsVisibleInBrowsing.end(); EXPECT_EQ(should_be_visible, element->visible()); } { @@ -249,6 +246,42 @@ } } +TEST_F(UiSceneManagerTest, UiUpdatesExitPrompt) { + std::set<UiElementDebugId> visible_when_prompting = {kExitPrompt, kBackplane, + kCeiling, kFloor}; + MakeManager(kNotInCct, kNotInWebVr); + + manager_->SetWebVrSecureOrigin(true); + + // Initial state. + for (const auto& element : scene_->GetUiElements()) { + SCOPED_TRACE(element->debug_id()); + bool should_be_visible = + kElementsVisibleInBrowsing.find(element->debug_id()) != + kElementsVisibleInBrowsing.end(); + EXPECT_EQ(should_be_visible, element->visible()); + } + + // Exit prompt visible state. + manager_->OnSecurityIconClicked(); + for (const auto& element : scene_->GetUiElements()) { + SCOPED_TRACE(element->debug_id()); + bool should_be_visible = visible_when_prompting.find(element->debug_id()) != + visible_when_prompting.end(); + EXPECT_EQ(should_be_visible, element->visible()); + } + + // Back to initial state. + manager_->OnExitPromptPrimaryButtonClicked(); + for (const auto& element : scene_->GetUiElements()) { + SCOPED_TRACE(element->debug_id()); + bool should_be_visible = + kElementsVisibleInBrowsing.find(element->debug_id()) != + kElementsVisibleInBrowsing.end(); + EXPECT_EQ(should_be_visible, element->visible()); + } +} + TEST_F(UiSceneManagerTest, UiUpdatesForWebVR) { MakeManager(kNotInCct, kInWebVr);
diff --git a/chrome/browser/android/vr_shell/ui_unsupported_mode.h b/chrome/browser/android/vr_shell/ui_unsupported_mode.h index 4811b0b..731af52 100644 --- a/chrome/browser/android/vr_shell/ui_unsupported_mode.h +++ b/chrome/browser/android/vr_shell/ui_unsupported_mode.h
@@ -13,6 +13,7 @@ enum class UiUnsupportedMode : int { kUnhandledCodePoint = 0, kCouldNotElideURL, + kUnhandledPageInfo, // This must be last. kCount,
diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc index 1e154e2..9fce75e 100644 --- a/chrome/browser/android/vr_shell/vr_shell.cc +++ b/chrome/browser/android/vr_shell/vr_shell.cc
@@ -585,6 +585,13 @@ } void VrShell::ExitVrDueToUnsupportedMode(UiUnsupportedMode mode) { + if (mode == UiUnsupportedMode::kUnhandledPageInfo) { + UMA_HISTOGRAM_ENUMERATION("VR.Shell.EncounteredUnsupportedMode", mode, + UiUnsupportedMode::kCount); + JNIEnv* env = base::android::AttachCurrentThread(); + Java_VrShellImpl_onUnhandledPageInfo(env, j_vr_shell_.obj()); + return; + } ui_->SetIsExiting(); main_thread_task_runner_->PostDelayedTask( FROM_HERE,
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index 9a708c27..3601b81 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc
@@ -12,7 +12,6 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_dialogs.h" @@ -23,10 +22,6 @@ #include "content/public/common/content_features.h" #include "extensions/features/features.h" -#if defined(OS_ANDROID) -#include "chrome/browser/android/chrome_feature_list.h" -#endif - bool FixupBrowserAboutURL(GURL* url, content::BrowserContext* browser_context) { // Ensure that any cleanup done by FixupURL happens before the rewriting @@ -54,6 +49,14 @@ std::string host(url->host()); std::string path; + // Handle chrome://settings. + if (host == chrome::kChromeUISettingsHost) + return true; // Prevent further rewriting - this is a valid URL. + + // Do not handle chrome://help. + if (host == chrome::kChromeUIHelpHost) + return false; // Handled in the HandleWebUI handler. + // Replace about with chrome-urls. if (host == chrome::kChromeUIAboutHost) host = chrome::kChromeUIChromeURLsHost; @@ -90,12 +93,6 @@ } else if (host == chrome::kChromeUIHistoryHost) { // Redirect chrome://history. path = url->path(); - } else if (host == chrome::kChromeUISettingsHost) { - // Redirect chrome://settings. - return true; // Prevent further rewriting - this is a valid URL. - } else if (host == chrome::kChromeUIHelpHost) { - // Redirect chrome://help, unless MD settings is enabled. - return false; // Handled in the HandleWebUI handler. } GURL::Replacements replacements; @@ -117,7 +114,8 @@ base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&chrome::AttemptRestart)); return true; - } else if (base::LowerCaseEqualsASCII(spec, chrome::kChromeUIQuitURL)) { + } + if (base::LowerCaseEqualsASCII(spec, chrome::kChromeUIQuitURL)) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&chrome::AttemptExit)); return true;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index a96cff4..3c449b8c 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -294,6 +294,8 @@ <include name="IDR_MD_BOOKMARKS_STORE_CLIENT_JS" file="resources\md_bookmarks\store_client.js" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_STORE_HTML" file="resources\md_bookmarks\store.html" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_STORE_JS" file="resources\md_bookmarks\store.js" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_TOAST_MANAGER_HTML" file="resources\md_bookmarks\toast_manager.html" type="BINDATA" /> + <include name="IDR_MD_BOOKMARKS_TOAST_MANAGER_JS" file="resources\md_bookmarks\toast_manager.js" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_TOOLBAR_HTML" file="resources\md_bookmarks\toolbar.html" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_TOOLBAR_JS" file="resources\md_bookmarks\toolbar.js" type="BINDATA" /> <include name="IDR_MD_BOOKMARKS_UTIL_HTML" file="resources\md_bookmarks\util.html" type="BINDATA" />
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 8156041e..dea9827c 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1792,7 +1792,6 @@ "../ui/webui/chromeos/login/l10n_util_unittest.cc", "../ui/webui/chromeos/login/oobe_display_chooser_unittest.cc", "../ui/webui/chromeos/login/signin_userlist_unittest.cc", - "../ui/webui/options/chromeos/cros_language_options_handler_unittest.cc", "../ui/webui/settings/chromeos/easy_unlock_settings_handler_unittest.cc", "//components/drive/change_list_loader_unittest.cc", "//components/drive/change_list_processor_unittest.cc",
diff --git a/chrome/browser/chromeos/arc/tracing/DEPS b/chrome/browser/chromeos/arc/tracing/DEPS deleted file mode 100644 index e94e96a..0000000 --- a/chrome/browser/chromeos/arc/tracing/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+content/browser/tracing/arc_tracing_agent.h" -]
diff --git a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h index b9a18e8..0c301c37 100644 --- a/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h +++ b/chrome/browser/chromeos/arc/tracing/arc_tracing_bridge.h
@@ -15,7 +15,7 @@ #include "components/arc/arc_service.h" #include "components/arc/common/tracing.mojom.h" #include "components/arc/instance_holder.h" -#include "content/browser/tracing/arc_tracing_agent.h" +#include "content/public/browser/arc_tracing_agent.h" namespace arc {
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index d481adf..3ae29ff 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -86,6 +86,7 @@ #include "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h" #include "components/ntp_snippets/user_classifier.h" #include "components/ntp_tiles/most_visited_sites.h" +#include "components/offline_pages/features/features.h" #include "components/omnibox/browser/zero_suggest_provider.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_manager.h" @@ -143,6 +144,10 @@ #include "extensions/browser/extension_prefs.h" #endif // BUILDFLAG(ENABLE_EXTENSIONS) +#if BUILDFLAG(ENABLE_OFFLINE_PAGES) +#include "chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h" +#endif + #if BUILDFLAG(ENABLE_PLUGINS) #include "chrome/browser/plugins/plugins_resource_service.h" #endif @@ -678,6 +683,10 @@ #endif registry->RegisterDictionaryPref(kDistroDict); + +#if BUILDFLAG(ENABLE_OFFLINE_PAGES) + offline_pages::RegisterPrefetchBackgroundTaskPrefs(registry); +#endif } void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index b4fb9ad7..16864c45 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -116,16 +116,6 @@ output_dir = "$root_gen_dir/chrome" } - grit("options_test_resources") { - source = "options_test_resources.grd" - defines = chrome_grit_defines - outputs = [ - "grit/options_test_resources.h", - "options_test_resources.pak", - ] - output_dir = "$root_gen_dir/chrome" - } - grit("settings_resources") { if (use_vulcanize) { source = "settings/settings_resources_vulcanized.grd"
diff --git a/chrome/browser/resources/md_bookmarks/app.html b/chrome/browser/resources/md_bookmarks/app.html index ce4aae3..9cc1c358 100644 --- a/chrome/browser/resources/md_bookmarks/app.html +++ b/chrome/browser/resources/md_bookmarks/app.html
@@ -9,6 +9,7 @@ <link rel="import" href="chrome://bookmarks/router.html"> <link rel="import" href="chrome://bookmarks/shared_vars.html"> <link rel="import" href="chrome://bookmarks/store.html"> +<link rel="import" href="chrome://bookmarks/toast_manager.html"> <link rel="import" href="chrome://bookmarks/toolbar.html"> <link rel="import" href="chrome://bookmarks/folder_node.html"> <link rel="import" href="chrome://bookmarks/util.html"> @@ -76,6 +77,7 @@ </div> <bookmarks-router></bookmarks-router> <bookmarks-command-manager></bookmarks-command-manager> + <bookmarks-toast-manager duration="5000"></bookmarks-toast-manager> </template> <script src="chrome://bookmarks/app.js"></script> </dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/command_manager.js b/chrome/browser/resources/md_bookmarks/command_manager.js index be258a32..8960d0a 100644 --- a/chrome/browser/resources/md_bookmarks/command_manager.js +++ b/chrome/browser/resources/md_bookmarks/command_manager.js
@@ -44,6 +44,12 @@ this.boundOnOpenItemMenu_ = this.onOpenItemMenu_.bind(this); document.addEventListener('open-item-menu', this.boundOnOpenItemMenu_); + /** @private {function()} */ + this.boundOnCommandUndo_ = function() { + this.handle(Command.UNDO, new Set()); + }.bind(this); + document.addEventListener('command-undo', this.boundOnCommandUndo_); + /** @private {function(!Event)} */ this.boundOnKeydown_ = this.onKeydown_.bind(this); document.addEventListener('keydown', this.boundOnKeydown_); @@ -66,6 +72,7 @@ detached: function() { CommandManager.instance_ = null; document.removeEventListener('open-item-menu', this.boundOnOpenItemMenu_); + document.removeEventListener('command-undo', this.boundOnCommandUndo_); document.removeEventListener('keydown', this.boundOnKeydown_); }, @@ -179,17 +186,31 @@ case Command.COPY: var idList = Array.from(itemIds); chrome.bookmarkManagerPrivate.copy(idList, function() { - // TODO(jiaxi): Add toast later. + bookmarks.ToastManager.getInstance().show( + loadTimeData.getString('toastUrlCopied'), false); }); break; case Command.DELETE: - chrome.bookmarkManagerPrivate.removeTrees( - Array.from(this.minimizeDeletionSet_(itemIds)), function() { - // TODO(jiaxi): Add toast later. - }); + var idList = Array.from(this.minimizeDeletionSet_(itemIds)); + var labelPromise; + if (idList.length == 1) { + // TODO(calamity): fold this separate label into + // 'toastItemsDeleted'. + labelPromise = Promise.resolve(loadTimeData.getStringF( + 'toastItemDeleted', this.getState().nodes[idList[0]].title)); + } else { + labelPromise = cr.sendWithPromise( + 'getPluralString', 'toastItemsDeleted', idList.length); + } + chrome.bookmarkManagerPrivate.removeTrees(idList, function() { + labelPromise.then(function(label) { + bookmarks.ToastManager.getInstance().show(label, true); + }); + }.bind(this)); break; case Command.UNDO: chrome.bookmarkManagerPrivate.undo(); + bookmarks.ToastManager.getInstance().hide(); break; case Command.REDO: chrome.bookmarkManagerPrivate.redo();
diff --git a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp index f88af25..a1200ea 100644 --- a/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp +++ b/chrome/browser/resources/md_bookmarks/compiled_resources2.gyp
@@ -47,6 +47,7 @@ '<(EXTERNS_GYP):bookmark_manager_private', 'edit_dialog', 'store_client', + 'toast_manager' ], 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], }, @@ -146,6 +147,15 @@ 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'] }, { + 'target_name': 'toast_manager', + 'dependencies': [ + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', + '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-button/compiled_resources2.gyp:paper-button-extracted', + ], + 'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'], + }, + { 'target_name': 'toolbar', 'dependencies': [ '<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
diff --git a/chrome/browser/resources/md_bookmarks/list.js b/chrome/browser/resources/md_bookmarks/list.js index cb0bdb9..0505d47 100644 --- a/chrome/browser/resources/md_bookmarks/list.js +++ b/chrome/browser/resources/md_bookmarks/list.js
@@ -32,7 +32,16 @@ }, /** @private */ - searchTerm_: String, + searchTerm_: { + type: String, + observer: 'onDisplayedListSourceChange_', + }, + + /** @private */ + selectedFolder_: { + type: String, + observer: 'onDisplayedListSourceChange_', + }, }, listeners: { @@ -49,6 +58,9 @@ this.watch('searchTerm_', function(state) { return state.search.term; }); + this.watch('selectedFolder_', function(state) { + return state.selectedFolder; + }); this.updateFromStore(); this.$.bookmarksCard.addEventListener( @@ -91,6 +103,11 @@ }, /** @private */ + onDisplayedListSourceChange_: function() { + this.scrollTop = 0; + }, + + /** @private */ emptyListMessage_: function() { var emptyListMessage = this.searchTerm_ ? 'noSearchResults' : 'emptyList'; return loadTimeData.getString(emptyListMessage); @@ -130,6 +147,7 @@ var focusMoved = false; var focusedIndex = this.getIndexForItemElement_(/** @type {HTMLElement} */ (e.target)); + var oldFocusedIndex = focusedIndex; if (e.key == 'ArrowUp') { focusedIndex--; focusMoved = true; @@ -166,6 +184,12 @@ this.dispatch( bookmarks.actions.updateAnchor(this.displayedIds_[focusedIndex])); } else { + // If shift-selecting with no anchor, use the old focus index. + if (e.shiftKey && this.getState().selection.anchor == null) { + this.dispatch(bookmarks.actions.updateAnchor( + this.displayedIds_[oldFocusedIndex])); + } + // If the focus moved from something other than a Ctrl + move event, // update the selection. var config = {
diff --git a/chrome/browser/resources/md_bookmarks/toast_manager.html b/chrome/browser/resources/md_bookmarks/toast_manager.html new file mode 100644 index 0000000..bc3a643 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/toast_manager.html
@@ -0,0 +1,60 @@ +<link rel="import" href="chrome://resources/html/polymer.html"> + +<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> +<link rel="import" href="chrome://bookmarks/shared_style.html"> + +<dom-module id="bookmarks-toast-manager"> + <template> + <style include="shared-style"> + #content { + flex: 1; + margin-right: 32px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + paper-button { + color: var(--google-blue-300); + font-weight: 500; + height: 32px; + margin: 0; + min-width: 52px; + padding: 8px; + } + + #toast { + align-items: center; + background-color: #323232; + border-radius: 4px; + bottom: 0; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.28); + box-sizing: border-box; + color: #fff; + display: flex; + margin: 24px; + max-width: 568px; + min-height: 52px; + min-width: 288px; + opacity: 0; + padding: 0 24px; + position: fixed; + transform: translateY(100px); + transition: transform 300ms, opacity 300ms; + white-space: nowrap; + } + + :host([open_]) #toast { + opacity: 1; + transform: translateY(0); + } + </style> + <div id="toast" aria-live="polite"> + <div id="content"></div> + <paper-button id="button" hidden$="[[!showUndo_]]" on-tap="onUndoTap_"> + $i18n{undo} + </paper-button> + </div> + </template> + <script src="chrome://bookmarks/toast_manager.js"></script> +</dom-module>
diff --git a/chrome/browser/resources/md_bookmarks/toast_manager.js b/chrome/browser/resources/md_bookmarks/toast_manager.js new file mode 100644 index 0000000..dabd5885 --- /dev/null +++ b/chrome/browser/resources/md_bookmarks/toast_manager.js
@@ -0,0 +1,95 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Element which shows toasts. + */ +cr.define('bookmarks', function() { + + var ToastManager = Polymer({ + is: 'bookmarks-toast-manager', + + properties: { + duration: { + type: Number, + value: 0, + }, + + /** @private */ + open_: { + type: Boolean, + reflectToAttribute: true, + }, + + /** @private */ + showUndo_: Boolean, + }, + + /** @private {function(number)} */ + clearTimeout_: window.clearTimeout.bind(window), + + /** @private {function((Function|null|string), number)} */ + setTimeout_: window.setTimeout.bind(window), + + /** @private {number|null} */ + hideTimeout_: null, + + /** @override */ + attached: function() { + assert(ToastManager.instance_ == null); + ToastManager.instance_ = this; + }, + + /** @override */ + detached: function() { + ToastManager.instance_ = null; + }, + + /** + * @param {string} label The label to display inside the toast. + * @param {boolean} showUndo Whether the undo button should be shown. + */ + show: function(label, showUndo) { + this.open_ = true; + // TODO(calamity): Support collapsing of long bookmark names in label. + this.$.content.textContent = label; + this.showUndo_ = showUndo; + + if (!this.duration) + return; + + if (this.hideTimeout_ != null) { + this.clearTimeout_(this.hideTimeout_); + this.hideTimeout_ = null; + } + + this.hideTimeout_ = this.setTimeout_(function() { + this.open_ = false; + this.hideTimeout_ = null; + }.bind(this), this.duration); + }, + + hide: function() { + this.open_ = false; + }, + + /** @private */ + onUndoTap_: function() { + // Will hide the toast. + this.fire('command-undo'); + }, + }); + + /** @private {?bookmarks.ToastManager} */ + ToastManager.instance_ = null; + + /** @return {!bookmarks.ToastManager} */ + ToastManager.getInstance = function() { + return assert(ToastManager.instance_); + }; + + return { + ToastManager: ToastManager, + }; +});
diff --git a/chrome/browser/resources/md_bookmarks/toolbar.js b/chrome/browser/resources/md_bookmarks/toolbar.js index bc48904..2ec0469 100644 --- a/chrome/browser/resources/md_bookmarks/toolbar.js +++ b/chrome/browser/resources/md_bookmarks/toolbar.js
@@ -67,6 +67,8 @@ onSortTap_: function() { chrome.bookmarkManagerPrivate.sortChildren( assert(this.getState().selectedFolder)); + bookmarks.ToastManager.getInstance().show( + loadTimeData.getString('toastFolderSorted'), true); this.closeDropdownMenu_(); },
diff --git a/chrome/browser/resources/options_test_resources.grd b/chrome/browser/resources/options_test_resources.grd deleted file mode 100644 index a9220f9f..0000000 --- a/chrome/browser/resources/options_test_resources.grd +++ /dev/null
@@ -1,19 +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/options_test_resources.h" type="rc_header"> - <emit emit_type='prepend'></emit> - </output> - <output filename="options_test_resources.pak" type="data_package" /> - </outputs> - <release seq="1"> - <structures> - <structure name="IDR_OPTIONS_DELETABLE_ITEM_LIST" - file="options/deletable_item_list.js" - type="chrome_html" /> - <structure name="IDR_OPTIONS_INLINE_EDITABLE_LIST" - file="options/inline_editable_list.js" - type="chrome_html" /> - </structures> - </release> -</grit>
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 55d9c1af..4e0b4d7 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1071,6 +1071,8 @@ "webui/options/supervised_user_learn_more_handler.h", "webui/options/sync_setup_handler.cc", "webui/options/sync_setup_handler.h", + "webui/plural_string_handler.cc", + "webui/plural_string_handler.h", "webui/policy_indicator_localized_strings_provider.cc", "webui/policy_indicator_localized_strings_provider.h", "webui/profile_helper.cc",
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h index d01dd7e1..ae556ea 100644 --- a/chrome/browser/ui/browser_window.h +++ b/chrome/browser/ui/browser_window.h
@@ -304,10 +304,9 @@ // that it's time to redraw everything. virtual void UserChangedTheme() = 0; - // Shows Page Info using the specified information. |virtual_url| - // is the virtual url of the page/frame the info applies to, |ssl| is the SSL - // information for that page/frame. If |show_history| is true, a section - // showing how many times that URL has been visited is added to the page info. + // Shows Page Info using the specified information. |virtual_url| is the + // virtual url of the page/frame the info applies to, and |security_info| + // contains the security state for that page/frame. virtual void ShowPageInfo( Profile* profile, content::WebContents* web_contents,
diff --git a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc index 76d0fec..442b54f0 100644 --- a/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc +++ b/chrome/browser/ui/webui/md_bookmarks/md_bookmarks_ui.cc
@@ -10,6 +10,7 @@ #include "base/strings/string16.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/md_bookmarks/bookmarks_message_handler.h" +#include "chrome/browser/ui/webui/plural_string_handler.h" #include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" @@ -86,6 +87,13 @@ IDS_BOOKMARK_MANAGER_SEARCH_BUTTON); AddLocalizedString(source, "saveEdit", IDS_SAVE); AddLocalizedString(source, "title", IDS_MD_BOOKMARK_MANAGER_TITLE); + AddLocalizedString(source, "toastFolderSorted", + IDS_MD_BOOKMARK_MANAGER_TOAST_FOLDER_SORTED); + AddLocalizedString(source, "toastItemDeleted", + IDS_MD_BOOKMARK_MANAGER_TOAST_ITEM_DELETED); + AddLocalizedString(source, "toastUrlCopied", + IDS_MD_BOOKMARK_MANAGER_TOAST_URL_COPIED); + AddLocalizedString(source, "undo", IDS_BOOKMARK_BAR_UNDO); // Resources. #if BUILDFLAG(USE_VULCANIZE) @@ -134,6 +142,10 @@ source->AddResourcePath("store_client.html", IDR_MD_BOOKMARKS_STORE_CLIENT_HTML); source->AddResourcePath("store_client.js", IDR_MD_BOOKMARKS_STORE_CLIENT_JS); + source->AddResourcePath("toast_manager.html", + IDR_MD_BOOKMARKS_TOAST_MANAGER_HTML); + source->AddResourcePath("toast_manager.js", + IDR_MD_BOOKMARKS_TOAST_MANAGER_JS); source->AddResourcePath("toolbar.html", IDR_MD_BOOKMARKS_TOOLBAR_HTML); source->AddResourcePath("toolbar.js", IDR_MD_BOOKMARKS_TOOLBAR_JS); source->AddResourcePath("util.html", IDR_MD_BOOKMARKS_UTIL_HTML); @@ -155,6 +167,11 @@ content::WebUIDataSource::Add(profile, CreateMdBookmarksUIHTMLSource(profile)); + auto plural_string_handler = base::MakeUnique<PluralStringHandler>(); + plural_string_handler->AddLocalizedString( + "toastItemsDeleted", IDS_MD_BOOKMARK_MANAGER_TOAST_ITEMS_DELETED); + web_ui->AddMessageHandler(std::move(plural_string_handler)); + web_ui->AddMessageHandler(base::MakeUnique<BookmarksMessageHandler>()); }
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc index 2d7be60d..ae691217 100644 --- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc +++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
@@ -236,7 +236,7 @@ const base::Value* callback_id; CHECK(args->Get(0, &callback_id)); - offline_pages::PrefetchBackgroundTask::Schedule(); + offline_pages::PrefetchBackgroundTask::Schedule(0); ResolveJavascriptCallback(*callback_id, base::Value("Scheduled.")); }
diff --git a/chrome/browser/ui/webui/options/autofill_options_browsertest.js b/chrome/browser/ui/webui/options/autofill_options_browsertest.js deleted file mode 100644 index 79109af..0000000 --- a/chrome/browser/ui/webui/options/autofill_options_browsertest.js +++ /dev/null
@@ -1,174 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * Returns the HTML element for the |field|. - * @param {string} field The field name for the element. - * @return {HTMLElement} The HTML element. - */ -function getField(field) { - return document.querySelector( - '#autofill-edit-address-overlay [field=' + field + ']'); -} - -/** - * Returns the size of the |list|. - * @param {HTMLElement} list The list to check. - * @return {number} The size of the list. - */ -function getListSize(list) { - // Remove 1 for placeholder input field. - return list.items.length - 1; -} - -/** - * TestFixture for autofill options WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function AutofillOptionsWebUITest() {} - -AutofillOptionsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to autofill options. - * @override - */ - browsePreload: 'chrome://settings-frame/autofill', -}; - -// TODO(crbug.com/617066) Flakes on Win. -GEN('#if defined(OS_WIN)'); -GEN('#define MAYBE_testOpenAutofillOptions ' + - 'DISABLED_testOpenAutofillOptions'); -GEN('#else'); -GEN('#define MAYBE_testOpenAutofillOptions testOpenAutofillOptions'); -GEN('#endif'); -// Test opening the autofill options has correct location. -TEST_F('AutofillOptionsWebUITest', 'MAYBE_testOpenAutofillOptions', - function() { - assertEquals(this.browsePreload, document.location.href); -}); - -/** - * TestFixture for autofill edit address overlay WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function AutofillEditAddressWebUITest() {} - -AutofillEditAddressWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/autofillEditAddress', -}; - -TEST_F('AutofillEditAddressWebUITest', 'testInitialFormLayout', function() { - assertEquals(this.browsePreload, document.location.href); - - var fields = ['country', 'phone', 'email', 'fullName', 'city']; - for (field in fields) { - assertEquals('', getField(fields[field]).value, 'Field: ' + fields[field]); - } - - testDone(); -}); - -TEST_F('AutofillEditAddressWebUITest', 'testLoadAddress', function() { - // http://crbug.com/434502 - // Accessibility failure was originally (and consistently) seen on Mac OS and - // Chromium OS. Disabling for all OSs because of a flake in Windows. There is - // a possibility for flake in linux too. - this.disableAccessibilityChecks(); - - assertEquals(this.browsePreload, document.location.href); - - var testAddress = { - guid: 'GUID Value', - fullName: 'Full Name 1', - companyName: 'Company Name Value', - addrLines: 'First Line Value\nSecond Line Value', - dependentLocality: 'Dependent Locality Value', - city: 'City Value', - state: 'State Value', - postalCode: 'Postal Code Value', - sortingCode: 'Sorting Code Value', - country: 'CH', - phone: '123', - email: 'a@b.c', - languageCode: 'de', - components: [[ - {field: 'postalCode', length: 'short'}, - {field: 'sortingCode', length: 'short'}, - {field: 'dependentLocality', length: 'short'}, - {field: 'city', length: 'short'}, - {field: 'state', length: 'short'}, - {field: 'addrLines', length: 'long'}, - {field: 'companyName', length: 'long'}, - {field: 'country', length: 'long'}, - {field: 'fullName', length: 'long', placeholder: 'Add name'} - ]] - }; - AutofillEditAddressOverlay.loadAddress(testAddress); - - var overlay = AutofillEditAddressOverlay.getInstance(); - assertEquals(testAddress.guid, overlay.guid_); - assertEquals(testAddress.languageCode, overlay.languageCode_); - - var inputs = ['companyName', 'dependentLocality', 'city', 'state', - 'postalCode', 'sortingCode', 'fullName', 'email', 'phone']; - for (var i in inputs) { - var field = getField(inputs[i]); - assertEquals(testAddress[inputs[i]], field.value); - assertTrue(field instanceof HTMLInputElement); - } - - var addrLines = getField('addrLines'); - assertEquals(testAddress.addrLines, addrLines.value); - assertTrue(addrLines instanceof HTMLTextAreaElement); - - var country = getField('country'); - assertEquals(testAddress.country, country.value); - assertTrue(country instanceof HTMLSelectElement); -}); - -TEST_F('AutofillEditAddressWebUITest', 'testLoadAddressComponents', function() { - assertEquals(this.browsePreload, document.location.href); - - var testInput = { - languageCode: 'fr', - components: [[{field: 'city'}], - [{field: 'state'}]] - }; - AutofillEditAddressOverlay.loadAddressComponents(testInput); - - assertEquals('fr', AutofillEditAddressOverlay.getInstance().languageCode_); - expectEquals(2, $('autofill-edit-address-fields').children.length); -}); - -TEST_F('AutofillEditAddressWebUITest', 'testFieldValuesSaved', function() { - assertEquals(this.browsePreload, document.location.href); - - AutofillEditAddressOverlay.loadAddressComponents({ - languageCode: 'en', - components: [[{field: 'city'}]] - }); - getField('city').value = 'New York'; - - AutofillEditAddressOverlay.loadAddressComponents({ - languageCode: 'en', - components: [[{field: 'state'}]] - }); - assertEquals(null, getField('city')); - - AutofillEditAddressOverlay.loadAddressComponents({ - languageCode: 'en', - components: [[{field: 'city'}]] - }); - assertEquals('New York', getField('city').value); -});
diff --git a/chrome/browser/ui/webui/options/autofill_options_handler_unittest.cc b/chrome/browser/ui/webui/options/autofill_options_handler_unittest.cc deleted file mode 100644 index a00cc4c..0000000 --- a/chrome/browser/ui/webui/options/autofill_options_handler_unittest.cc +++ /dev/null
@@ -1,62 +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 "chrome/browser/ui/webui/options/autofill_options_handler.h" - -#include "base/values.h" -#include "components/autofill/core/browser/autofill_profile.h" -#include "components/autofill/core/browser/autofill_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace options { - -TEST(AutofillOptionsHandlerTest, AddressToDictionary) { - autofill::AutofillProfile profile; - autofill::test::SetProfileInfoWithGuid(&profile, - "guid", - "First", - "Middle", - "Last", - "fml@example.com", - "Acme inc", - "123 Main", - "Apt 2", - "Laredo", - "TX", - "77300", - "US", - "832-555-1000"); - - base::DictionaryValue dictionary; - options::AutofillOptionsHandler::AutofillProfileToDictionary(profile, - &dictionary); - - std::string value; - EXPECT_TRUE(dictionary.GetString("addrLines", &value)); - EXPECT_EQ("123 Main\nApt 2", value); - EXPECT_TRUE(dictionary.GetString("city", &value)); - EXPECT_EQ("Laredo", value); - EXPECT_TRUE(dictionary.GetString("country", &value)); - EXPECT_EQ("US", value); - EXPECT_TRUE(dictionary.GetString("dependentLocality", &value)); - EXPECT_EQ("", value); - EXPECT_TRUE(dictionary.GetString("guid", &value)); - EXPECT_EQ("guid", value); - EXPECT_TRUE(dictionary.GetString("languageCode", &value)); - EXPECT_EQ("", value); - EXPECT_TRUE(dictionary.GetString("postalCode", &value)); - EXPECT_EQ("77300", value); - EXPECT_TRUE(dictionary.GetString("sortingCode", &value)); - EXPECT_EQ("", value); - EXPECT_TRUE(dictionary.GetString("state", &value)); - EXPECT_EQ("TX", value); - EXPECT_TRUE(dictionary.GetString("email", &value)); - EXPECT_EQ("fml@example.com", value); - EXPECT_TRUE(dictionary.GetString("fullName", &value)); - EXPECT_EQ("First Middle Last", value); - EXPECT_TRUE(dictionary.GetString("phone", &value)); - EXPECT_EQ("832-555-1000", value); -} - -} // namespace options
diff --git a/chrome/browser/ui/webui/options/browser_options_browsertest.js b/chrome/browser/ui/webui/options/browser_options_browsertest.js deleted file mode 100644 index b5713f6..0000000 --- a/chrome/browser/ui/webui/options/browser_options_browsertest.js +++ /dev/null
@@ -1,131 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for browser options WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function BrowserOptionsWebUITest() {} - -BrowserOptionsWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** @override */ - browsePreload: 'chrome://chrome/settings/', -}; - -// Test opening the browser options has correct location. -// Times out on Mac debug only. See http://crbug.com/121030 -GEN('#if defined(OS_MACOSX) && !defined(NDEBUG)'); -GEN('#define MAYBE_testOpenBrowserOptions ' + - 'DISABLED_testOpenBrowserOptions'); -GEN('#else'); -GEN('#define MAYBE_testOpenBrowserOptions testOpenBrowserOptions'); -GEN('#endif // defined(OS_MACOSX)'); -TEST_F('BrowserOptionsWebUITest', 'MAYBE_testOpenBrowserOptions', function() { - assertEquals(this.browsePreload, document.location.href); - expectFalse($('navigation').classList.contains('background')); -}); - -/** - * TestFixture for the uber page when the browser options page has an overlay. - * @extends {testing.Test} - * @constructor - */ -function BrowserOptionsOverlayWebUITest() {} - -BrowserOptionsOverlayWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** @override */ - browsePreload: 'chrome://chrome/settings/autofill', - - /** @override */ - isAsync: true, -}; - -TEST_F('BrowserOptionsOverlayWebUITest', 'testNavigationInBackground', - function() { - assertEquals(this.browsePreload, document.location.href); - - if ($('navigation').classList.contains('background')) { - testDone(); - return; - } - - // Wait for the message to be posted to the Uber page. - window.addEventListener('message', function(e) { - if (e.data.method == 'beginInterceptingEvents') { - window.setTimeout(function() { - assertTrue($('navigation').classList.contains('background')); - testDone(); - }); - } - }); -}); - -/** - * @extends {testing.Test} - * @constructor - */ -function BrowserOptionsFrameWebUITest() {} - -BrowserOptionsFrameWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/', - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/570721 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#sync-overview > A'); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/570723 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#profiles-list'); - }, -}; - -TEST_F('BrowserOptionsFrameWebUITest', 'testAdvancedSettingsHiddenByDefault', - function() { - assertEquals(this.browsePreload, document.location.href); - expectTrue($('advanced-settings').hidden); -}); - -/** - * @extends {testing.Test} - * @constructor - */ -function AdvancedSettingsWebUITest() {} - -AdvancedSettingsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/autofill', -}; - -// TODO(crbug.com/617066) Flakes on Win. -GEN('#if defined(OS_WIN)'); -GEN('#define MAYBE_testAdvancedSettingsShown ' + - 'DISABLED_testAdvancedSettingsShown'); -GEN('#else'); -GEN('#define MAYBE_testAdvancedSettingsShown testAdvancedSettingsShown'); -GEN('#endif'); -TEST_F('AdvancedSettingsWebUITest', 'MAYBE_testAdvancedSettingsShown', - function() { - assertEquals(this.browsePreload, document.location.href); - expectFalse($('advanced-settings').hidden); -});
diff --git a/chrome/browser/ui/webui/options/certificate_manager_browsertest.js b/chrome/browser/ui/webui/options/certificate_manager_browsertest.js deleted file mode 100644 index 0db9129..0000000 --- a/chrome/browser/ui/webui/options/certificate_manager_browsertest.js +++ /dev/null
@@ -1,405 +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. - -// Mac and Windows go to native certificate manager, and certificate manager -// isn't implemented if OpenSSL is used. -GEN('#if defined(USE_NSS_CERTS)'); - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * URL of the Certificates dialog in the Settings page. - * @const - */ -var CERTIFICATE_MANAGER_SETTINGS_PAGE_URL = - 'chrome://settings-frame/certificates'; - -// Standalone certificate manager dialog page is implemented only in Chrome OS. -GEN('#if defined(OS_CHROMEOS)'); - -/** - * URL of the standalone certificate manager dialog page. - * @const - */ -var CERTIFICATE_MANAGER_STANDALONE_PAGE_URL = 'chrome://certificate-manager/'; - -GEN('#endif // defined(OS_CHROMEOS)'); - -/** - * TestFixture for certificate manager WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function CertificateManagerWebUIBaseTest() {} - -CertificateManagerWebUIBaseTest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - preLoad: function() { - // We can't check cr.isChromeOS in the preLoad since "cr" doesn't exist yet. - // This is copied from ui/webui/resources/js/cr.js, maybe - // there's a better way to do this. - this.isChromeOS = /CrOS/.test(navigator.userAgent); - - this.makeAndRegisterMockHandler( - [ - 'editCaCertificateTrust', - 'exportPersonalCertificate', - 'importPersonalCertificate', - 'importCaCertificate', - 'exportCertificate', - 'deleteCertificate', - 'populateCertificateManager', - 'viewCertificate', - ]); - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - var ariaRoleNotScopedSelectors = [ - '#tree-item-autogen-id-0', - '#tree-item-autogen-id-1', - '#tree-item-autogen-id-2', - '#tree-item-autogen-id-3', - '#tree-item-autogen-id-4', - ]; - - // Enable when failure is resolved. - // AX_ARIA_09: http://crbug.com/570567 - this.accessibilityAuditConfig.ignoreSelectors( - 'ariaRoleNotScoped', - ariaRoleNotScopedSelectors); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/570566 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#caCertsTab-tree'); - - var focusableElementNotVisibleAndNotAriaHiddenSelectors = [ - '#personalCertsTab-tree', - '#personalCertsTab-import', - '#personalCertsTab-import-and-bind', - '#certificate-confirm', - ]; - - // Enable when failure is resolved. - // AX_FOCUS_01: http://crbug.com/570568 - this.accessibilityAuditConfig.ignoreSelectors( - 'focusableElementNotVisibleAndNotAriaHidden', - focusableElementNotVisibleAndNotAriaHiddenSelectors); - }, -}; - -/** - * TestFixture for certificate manager WebUI testing. - * @extends {CertificateManagerWebUIBaseTest} - * @constructor - */ -function CertificateManagerWebUIUnpopulatedTest() {} - -CertificateManagerWebUIUnpopulatedTest.prototype = { - __proto__: CertificateManagerWebUIBaseTest.prototype, - - /** - * Browse to the certificate manager dialog in the Settings page. - */ - browsePreload: CERTIFICATE_MANAGER_SETTINGS_PAGE_URL, - - /** @override */ - preLoad: function() { - CertificateManagerWebUIBaseTest.prototype.preLoad.call(this); - - // We expect the populateCertificateManager callback, but do not reply to - // it. This simulates what will be displayed if retrieving the cert list - // from NSS is slow. - this.mockHandler.expects(once()).populateCertificateManager(); - }, -}; - -// Test opening the certificate manager has correct location and buttons have -// correct initial states when onPopulateTree has not been called. -TEST_F('CertificateManagerWebUIUnpopulatedTest', - 'testUnpopulatedCertificateManager', function() { - assertEquals(this.browsePreload, document.location.href); - - // All buttons should be disabled to start. - expectTrue($('personalCertsTab-view').disabled); - expectTrue($('personalCertsTab-backup').disabled); - expectTrue($('personalCertsTab-delete').disabled); - expectTrue($('personalCertsTab-import').disabled); - if (this.isChromeOS) - expectTrue($('personalCertsTab-import-and-bind').disabled); - - expectTrue($('serverCertsTab-view').disabled); - expectTrue($('serverCertsTab-export').disabled); - expectTrue($('serverCertsTab-delete').disabled); - expectTrue($('serverCertsTab-import').disabled); - - expectTrue($('caCertsTab-view').disabled); - expectTrue($('caCertsTab-edit').disabled); - expectTrue($('caCertsTab-export').disabled); - expectTrue($('caCertsTab-delete').disabled); - expectTrue($('caCertsTab-import').disabled); - - expectTrue($('otherCertsTab-view').disabled); - expectTrue($('otherCertsTab-export').disabled); - expectTrue($('otherCertsTab-delete').disabled); - - Mock4JS.verifyAllMocks(); - - // If user database is not available, import buttons should be disabled. - CertificateManager.onModelReady(false /* userDbAvailable*/, - false /* tpmAvailable */); - - expectTrue($('personalCertsTab-import').disabled); - expectTrue($('serverCertsTab-import').disabled); - expectTrue($('caCertsTab-import').disabled); - - // Once we get the onModelReady call, the import buttons should be enabled, - // others should still be disabled. - CertificateManager.onModelReady(true /* userDbAvailable*/, - false /* tpmAvailable */); - - expectTrue($('personalCertsTab-view').disabled); - expectTrue($('personalCertsTab-backup').disabled); - expectTrue($('personalCertsTab-delete').disabled); - expectFalse($('personalCertsTab-import').disabled); - - expectTrue($('serverCertsTab-view').disabled); - expectTrue($('serverCertsTab-export').disabled); - expectTrue($('serverCertsTab-delete').disabled); - expectFalse($('serverCertsTab-import').disabled); - - expectTrue($('caCertsTab-view').disabled); - expectTrue($('caCertsTab-edit').disabled); - expectTrue($('caCertsTab-export').disabled); - expectTrue($('caCertsTab-delete').disabled); - expectFalse($('caCertsTab-import').disabled); - - expectTrue($('otherCertsTab-view').disabled); - expectTrue($('otherCertsTab-export').disabled); - expectTrue($('otherCertsTab-delete').disabled); - - // On ChromeOS, the import and bind button should only be enabled if TPM is - // present. - if (this.isChromeOS) { - expectTrue($('personalCertsTab-import-and-bind').disabled); - CertificateManager.onModelReady(true /* userDbAvailable*/, - true /* tpmAvailable */); - expectFalse($('personalCertsTab-import-and-bind').disabled); - } -}); - -/** - * TestFixture for certificate manager WebUI testing. - * @extends {CertificateManagerWebUIBaseTest} - * @constructor - */ -function CertificateManagerWebUITest() {} - -CertificateManagerWebUITest.prototype = { - __proto__: CertificateManagerWebUIBaseTest.prototype, - - /** @override */ - preLoad: function() { - CertificateManagerWebUIBaseTest.prototype.preLoad.call(this); - - var tpmAvailable = this.isChromeOS; - var userDbAvailable = true; - this.mockHandler.expects(once()).populateCertificateManager().will( - callFunction(function() { - CertificateManager.onModelReady(userDbAvailable, tpmAvailable); - - [['personalCertsTab-tree', - [{'id': 'o1', - 'name': 'org1', - 'subnodes': [{ 'id': 'c1', - 'name': 'cert1', - 'readonly': false, - 'untrusted': false, - 'extractable': true }], - }], - ], - ['caCertsTab-tree', - [{'id': 'o2', - 'name': 'org2', - 'subnodes': [{ 'id': 'ca_cert0', - 'name': 'ca_cert0', - 'readonly': false, - 'untrusted': false, - 'extractable': true, - 'policy': false }, - { 'id': 'ca_cert1', - 'name': 'ca_cert1', - 'readonly': false, - 'untrusted': false, - 'extractable': true, - 'policy': true }, - { 'id': 'ca_cert2', - 'name': 'ca_cert2', - 'readonly': false, - 'untrusted': false, - 'extractable': true, - 'policy': false }], - }], - ] - ].forEach(CertificateManager.onPopulateTree);})); - }, -}; - -/** - * TestFixture for testing certificate manager WebUI in the Settings page. - * @extends {CertificateManagerWebUITest} - * @constructor - */ -function CertificateManagerSettingsWebUITest() {} - -CertificateManagerSettingsWebUITest.prototype = { - __proto__: CertificateManagerWebUITest.prototype, - - /** - * Browse to the certificate manager dialog in the Settings page. - */ - browsePreload: CERTIFICATE_MANAGER_SETTINGS_PAGE_URL, -}; - -TEST_F('CertificateManagerSettingsWebUITest', - 'testViewAndDeleteCert', function() { - assertEquals(this.browsePreload, document.location.href); - - this.mockHandler.expects(once()).viewCertificate(['c1']); - - expectTrue($('personalCertsTab-view').disabled); - expectTrue($('personalCertsTab-backup').disabled); - expectTrue($('personalCertsTab-delete').disabled); - expectFalse($('personalCertsTab-import').disabled); - if (this.isChromeOS) - expectFalse($('personalCertsTab-import-and-bind').disabled); - - var personalCerts = $('personalCertsTab'); - - // Click on the first folder. - personalCerts.querySelector('div.tree-item').click(); - // Buttons should still be in same state. - expectTrue($('personalCertsTab-view').disabled); - expectTrue($('personalCertsTab-backup').disabled); - expectTrue($('personalCertsTab-delete').disabled); - expectFalse($('personalCertsTab-import').disabled); - if (this.isChromeOS) - expectFalse($('personalCertsTab-import-and-bind').disabled); - - // Click on the first cert. - personalCerts.querySelector('div.tree-item div.tree-item').click(); - // Buttons should now allow you to act on the cert. - expectFalse($('personalCertsTab-view').disabled); - expectFalse($('personalCertsTab-backup').disabled); - expectFalse($('personalCertsTab-delete').disabled); - expectFalse($('personalCertsTab-import').disabled); - if (this.isChromeOS) - expectFalse($('personalCertsTab-import-and-bind').disabled); - - // Click on the view button. - $('personalCertsTab-view').click(); - - Mock4JS.verifyAllMocks(); - - this.mockHandler.expects(once()).deleteCertificate(['c1']).will(callFunction( - function() { - CertificateManager.onPopulateTree(['personalCertsTab-tree', []]); - })); - - // Click on the delete button. - $('personalCertsTab-delete').click(); - - // Click on the cancel button to verify the confirmation overlay closes. - $('alertOverlayCancel').click(); - expectTrue($('alertOverlay').parentNode.classList.contains('transparent')); - - // Click on the delete button. - $('personalCertsTab-delete').click(); - - // Click on the ok button in the confirmation overlay. - $('alertOverlayOk').click(); - expectTrue($('alertOverlay').parentNode.classList.contains('transparent')); - - // Context sensitive buttons should be disabled. - expectTrue($('personalCertsTab-view').disabled); - expectTrue($('personalCertsTab-backup').disabled); - expectTrue($('personalCertsTab-delete').disabled); - expectFalse($('personalCertsTab-import').disabled); - if (this.isChromeOS) - expectFalse($('personalCertsTab-import-and-bind').disabled); - // Tree should be empty. - expectTrue(personalCerts.querySelector('div.tree-item') === null); -}); - -// Ensure certificate objects with the 'policy' property set have -// the cert-policy CSS class appended. -TEST_F('CertificateManagerSettingsWebUITest', - 'testPolicyInstalledCertificate', function() { - // Click on the first folder and get the certificates. - var caCertsTab = $('caCertsTab'); - caCertsTab.querySelector('div.tree-item').click(); - var certs = caCertsTab.querySelectorAll('div.tree-item div.tree-item'); - - // First cert shouldn't show the controlled setting badge, and the - // edit and delete buttons should be enabled. - var cert0 = certs[0]; - expectEquals('ca_cert0', cert0.data.name); - expectEquals(null, cert0.querySelector('.cert-policy')); - cert0.click(); - expectFalse($('caCertsTab-edit').disabled); - expectFalse($('caCertsTab-delete').disabled); - - // But the second should show the controlled setting badge, and the - // edit and delete buttons should be disabled. - var cert1 = certs[1]; - expectEquals('ca_cert1', cert1.data.name); - expectNotEquals(null, cert1.querySelector('.cert-policy')); - cert1.click(); - expectTrue($('caCertsTab-edit').disabled); - expectTrue($('caCertsTab-delete').disabled); -}); - -// Standalone certificate manager dialog page is implemented only in Chrome OS. -GEN('#if defined(OS_CHROMEOS)'); - -/** - * TestFixture for testing standalone certificate manager WebUI. - * @extends {CertificateManagerWebUITest} - * @constructor - */ -function CertificateManagerStandaloneWebUITest() {} - -CertificateManagerStandaloneWebUITest.prototype = { - __proto__: CertificateManagerWebUITest.prototype, - - /** - * Browse to the certificate manager page. - */ - browsePreload: CERTIFICATE_MANAGER_STANDALONE_PAGE_URL, -}; - -// Ensure that the standalone certificate manager page loads and displays the -// ceertificates correctly. -TEST_F('CertificateManagerStandaloneWebUITest', 'testCertsDisplaying', - function() { - assertEquals(this.browsePreload, document.location.href); - - // Click on the first folder and get the certificates. - var caCertsTab = $('caCertsTab'); - caCertsTab.querySelector('div.tree-item').click(); - var certs = caCertsTab.querySelectorAll('div.tree-item div.tree-item'); - - // There should be exactly three certificates displayed. - expectEquals(certs.length, 3); -}); - -GEN('#endif // defined(OS_CHROMEOS)'); - -GEN('#endif // defined(USE_NSS_CERTS)');
diff --git a/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.cc b/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.cc deleted file mode 100644 index 34ea81b1..0000000 --- a/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.cc +++ /dev/null
@@ -1,166 +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 <stddef.h> - -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/chromeos/login/login_manager_test.h" -#include "chrome/browser/chromeos/login/startup_utils.h" -#include "chrome/browser/chromeos/login/ui/user_adding_screen.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/ui_test_utils.h" -#include "chromeos/settings/cros_settings_names.h" -#include "components/prefs/pref_service.h" -#include "components/user_manager/user_manager.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_utils.h" - -namespace chromeos { - -namespace { - -const char* kTestUsers[] = { "test-user1@gmail.com", "test-user2@gmail.com" }; - -} // namespace - -class AccountsOptionsTest : public LoginManagerTest { - public: - AccountsOptionsTest() - : LoginManagerTest(false), - stub_settings_provider_(base::MakeUnique<StubCrosSettingsProvider>()), - stub_settings_provider_ptr_(static_cast<StubCrosSettingsProvider*>( - stub_settings_provider_.get())) { - stub_settings_provider_->Set(kDeviceOwner, base::Value(kTestUsers[0])); - for (size_t i = 0; i < arraysize(kTestUsers); ++i) { - test_users_.push_back(AccountId::FromUserEmail(kTestUsers[i])); - } - } - - ~AccountsOptionsTest() override {} - - void SetUpOnMainThread() override { - LoginManagerTest::SetUpOnMainThread(); - CrosSettings* settings = CrosSettings::Get(); - CrosSettingsProvider* device_settings_provider = - settings->GetProvider(kDeviceOwner); - device_settings_provider_ = - settings->RemoveSettingsProvider(device_settings_provider); - settings->AddSettingsProvider(std::move(stub_settings_provider_)); - - // Notify ChromeUserManager of ownership change. - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, - content::Source<AccountsOptionsTest>(this), - content::NotificationService::NoDetails()); - } - - void TearDownOnMainThread() override { - CrosSettings* settings = CrosSettings::Get(); - stub_settings_provider_ = - settings->RemoveSettingsProvider(stub_settings_provider_ptr_); - settings->AddSettingsProvider(std::move(device_settings_provider_)); - LoginManagerTest::TearDownOnMainThread(); - } - - void SetUpCommandLine(base::CommandLine* command_line) override { - LoginManagerTest::SetUpCommandLine(command_line); - } - - protected: - void CheckAccountsUI(const user_manager::User* user, bool is_owner) { - Profile* profile = ProfileHelper::Get()->GetProfileByUserUnsafe(user); - - ui_test_utils::BrowserAddedObserver observer; - Browser* browser = CreateBrowser(profile); - observer.WaitForSingleNewBrowser(); - - ui_test_utils::NavigateToURL(browser, - GURL("chrome://settings-frame/accounts")); - content::WebContents* contents = - browser->tab_strip_model()->GetActiveWebContents(); - - bool warning_visible; - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, - "var e = document.getElementById('ownerOnlyWarning');" - "var visible = e.offsetWidth > 0 && e.offsetHeight > 0;" - "window.domAutomationController.send(visible);", - &warning_visible)); - EXPECT_EQ(is_owner, !warning_visible); - - bool guest_option_enabled; - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, - "var e = document.getElementById('allowBwsiCheck');" - "window.domAutomationController.send(!e.disabled);", - &guest_option_enabled)); - EXPECT_EQ(is_owner, guest_option_enabled); - - bool supervised_users_enabled; - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, - "var e = document.getElementById('allowSupervisedCheck');" - "window.domAutomationController.send(!e.disabled);", - &supervised_users_enabled)); - ASSERT_EQ(is_owner, supervised_users_enabled); - - bool user_pods_enabled; - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, - "var e = document.getElementById('showUserNamesCheck');" - "window.domAutomationController.send(!e.disabled);", - &user_pods_enabled)); - EXPECT_EQ(is_owner, user_pods_enabled); - - bool whitelist_enabled; - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, - "var e = document.getElementById('useWhitelistCheck');" - "window.domAutomationController.send(!e.disabled);", - &whitelist_enabled)); - EXPECT_EQ(is_owner, whitelist_enabled); - } - - std::unique_ptr<CrosSettingsProvider> stub_settings_provider_; - StubCrosSettingsProvider* stub_settings_provider_ptr_; - std::unique_ptr<CrosSettingsProvider> device_settings_provider_; - std::vector<AccountId> test_users_; - - private: - DISALLOW_COPY_AND_ASSIGN(AccountsOptionsTest); -}; - -IN_PROC_BROWSER_TEST_F(AccountsOptionsTest, PRE_MultiProfilesAccountsOptions) { - RegisterUser(test_users_[0].GetUserEmail()); - RegisterUser(test_users_[1].GetUserEmail()); - StartupUtils::MarkOobeCompleted(); -} - -IN_PROC_BROWSER_TEST_F(AccountsOptionsTest, MultiProfilesAccountsOptions) { - LoginUser(test_users_[0].GetUserEmail()); - UserAddingScreen::Get()->Start(); - content::RunAllPendingInMessageLoop(); - AddUser(test_users_[1].GetUserEmail()); - - user_manager::UserManager* manager = user_manager::UserManager::Get(); - ASSERT_EQ(2u, manager->GetLoggedInUsers().size()); - - CheckAccountsUI(manager->FindUser(test_users_[0]), true /* is_owner */); - CheckAccountsUI(manager->FindUser(test_users_[1]), false /* is_owner */); -} - -} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.js b/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.js deleted file mode 100644 index 381aead..0000000 --- a/chrome/browser/ui/webui/options/chromeos/accounts_options_browsertest.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. - -GEN_INCLUDE(['../options_browsertest_base.js']); - -function AccountsOptionsWebUITest() {} - -AccountsOptionsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to accounts options. - */ - browsePreload: 'chrome://settings-frame/accounts', -}; - -function createEnterKeyboardEvent(type) { - return new KeyboardEvent(type, { - 'bubbles': true, - 'cancelable': true, - 'key': 'Enter' - }); -} - -TEST_F('AccountsOptionsWebUITest', 'testNoCloseOnEnter', function() { - assertEquals(this.browsePreload, document.location.href); - - var inputField = $('userNameEdit'); - var accountsOptionsPage = AccountsOptions.getInstance(); - - // Overlay is visible. - assertTrue(accountsOptionsPage.visible); - - // Simulate pressing the enter key in the edit field. - inputField.dispatchEvent(createEnterKeyboardEvent('keydown')); - inputField.dispatchEvent(createEnterKeyboardEvent('keypress')); - inputField.dispatchEvent(createEnterKeyboardEvent('keyup')); - - // Verify the overlay is still visible. - assertTrue(accountsOptionsPage.visible); -});
diff --git a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js deleted file mode 100644 index 38e4c9b..0000000 --- a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js +++ /dev/null
@@ -1,440 +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. - -GEN('#if defined(OS_CHROMEOS)'); - -GEN_INCLUDE(['../options_browsertest_base.js']); - -function BluetoothWebUITestAsync() {} - -BluetoothWebUITestAsync.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - isAsync: true, - - /** - * Start tests from the main-settings page. - */ - browsePreload: 'chrome://settings-frame/', - - // These entries match the fake entries in FakeBluetoothDeviceClient. - fakePairedDevice: { - address: '00:11:22:33:44:55', - connectable: true, - connected: false, - name: 'Fake Device (name)', - paired: true - }, - - fakePairedDevice2: { - address: '20:7D:74:00:00:04', - connectable: false, - connected: false, - name: 'Paired Unconnectable Device (name)', - paired: true - }, - - fakeUnpairedDevice: { - address: '28:CF:DA:00:00:00', - connectable: true, - connected: false, - name: 'Bluetooth 2.0 Mouse', - paired: false - }, - - fakeUnpairedDevice2: { - address: '00:24:BE:00:00:00', - connectable: true, - connected: false, - name: 'PIN Device', - paired: false - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - var unsupportedAriaAttributeSelectors = [ - '#bluetooth-paired-devices-list', - '#bluetooth-unpaired-devices-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/570564 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - unsupportedAriaAttributeSelectors); - }, - - /** - * Retrieves the list item associated with a Bluetooth device. - * @param {!Element} listElement Element containing a list of devices. - * @param {string} deviceName The name of the device. - * @return {Element|undefined} List item matching the device name. - */ - getElementForDevice: function(listElement, deviceName) { - var items = listElement.querySelectorAll('.bluetooth-device'); - for (var i = 0; i < items.length; i++) { - var candidate = items[i]; - var name = candidate.data.name; - if (name == deviceName) - return candidate; - } - return undefined; - }, - - /** - * Selects a bluetooth device from the list with the matching address. - * @param {!Element} listElement A list of Bluetooth devices. - * @param {string} address Device address. - */ - selectDevice: function(listElement, address) { - listElement.setSelectedDevice_(address); - cr.dispatchSimpleEvent(listElement, 'change'); - }, - - /** - * Fake input of a pincode or passkey. - * @param {!Element} element Text input field. - * @param {string} text New value for the input field. - */ - fakeInput: function(element, text) { - element.value = text; - cr.dispatchSimpleEvent(element, 'input'); - }, -}; - -TEST_F('BluetoothWebUITestAsync', 'testEnableBluetooth', function() { - assertEquals(this.browsePreload, document.location.href); - expectFalse($('enable-bluetooth').checked); - expectTrue($('bluetooth-paired-devices-list').parentNode.hidden); - - $('enable-bluetooth').click(); - - // The UI may not be updated until all callbacks have been handled, so - // send a new request that will get processed after any currently pending - // callbacks. - chrome.bluetooth.getAdapterState(function(state) { - expectTrue(state.powered); - expectFalse($('bluetooth-paired-devices-list').parentNode.hidden); - testDone(); - }.bind(this)); -}); - -// TODO(crbug.com/603499) Test is flaky. -TEST_F('BluetoothWebUITestAsync', 'DISABLED_testAddDevice', function() { - assertEquals(this.browsePreload, document.location.href); - - // Enable bluetooth. - $('enable-bluetooth').click(); - - // Wait for the UI to process any pending messages. - window.setTimeout(function() { - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - var pairedDeviceList = $('bluetooth-paired-devices-list'); - var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); - - // Verify that devices are in the correct list. - var index = pairedDeviceList.find(this.fakePairedDevice.address); - expectEquals(1, index); - index = pairedDeviceList.find(this.fakePairedDevice2.address); - expectEquals(0, index); - index = pairedDeviceList.find(this.fakeUnpairedDevice.address); - expectEquals(undefined, index); - expectTrue(!!this.getElementForDevice(pairedDeviceList, - this.fakePairedDevice.name)); - expectFalse(!!this.getElementForDevice(unpairedDeviceList, - this.fakePairedDevice.name)); - - // Test clicking on the 'Add a device' button. This should send a - // startDiscovering request. - $('bluetooth-add-device').click(); - expectFalse($('bluetooth-options').hidden); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - expectTrue(state.discovering); - expectFalse(unpairedDeviceList.parentNode.hidden); - - index = unpairedDeviceList.find(this.fakeUnpairedDevice.address); - expectEquals(0, index); - - var connectButton = $('bluetooth-add-device-apply-button'); - expectTrue(connectButton.disabled); - expectFalse($('bluetooth-add-device-cancel-button').disabled); - - // Test selecting an element and clicking on the connect button. - this.selectDevice(unpairedDeviceList, this.fakeUnpairedDevice.address); - expectFalse(connectButton.disabled); - connectButton.click(); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - // Verify that the pairing UI is shown. - expectFalse($('bluetooth-pairing').hidden); - testDone(); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }.bind(this)); -}); - -TEST_F('BluetoothWebUITestAsync', 'testDevicePairing', function() { - assertEquals(this.browsePreload, document.location.href); - - // Enable bluetooth. - $('enable-bluetooth').click(); - - // Wait for the UI to process any pending messages. - window.setTimeout(function() { - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - var pairedDeviceList = $('bluetooth-paired-devices-list'); - var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); - - $('bluetooth-add-device').click(); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - expectFalse(unpairedDeviceList.parentNode.hidden); - - // Test selecting an element and clicking on the connect button. - var index = unpairedDeviceList.find(this.fakeUnpairedDevice2.address); - expectNotEquals(undefined, index); - this.selectDevice(unpairedDeviceList, this.fakeUnpairedDevice2.address); - var connectButton = $('bluetooth-add-device-apply-button'); - expectFalse(connectButton.disabled); - connectButton.click(); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - // Verify that the pairing UI is shown. - expectFalse($('bluetooth-pairing').hidden); - expectTrue($('bluetooth-pairing-passkey-display').hidden); - expectTrue($('bluetooth-pairing-passkey-entry').hidden); - expectFalse($('bluetooth-pairing-pincode-entry').hidden); - - var pincode = '123456'; - this.fakeInput($('bluetooth-pincode'), pincode); - $('bluetooth-pair-device-connect-button').click(); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - expectTrue($('bluetooth-pairing-pincode-entry').hidden); - testDone(); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }.bind(this)); -}); - -// TODO(crbug.com/608126) Test is flaky. -TEST_F('BluetoothWebUITestAsync', 'DISABLED_testConnect', function() { - assertEquals(this.browsePreload, document.location.href); - - // Enable bluetooth. - $('enable-bluetooth').click(); - - // Wait for the UI to process any pending messages. - window.setTimeout(function() { - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - var pairedDeviceList = $('bluetooth-paired-devices-list'); - var element = this.getElementForDevice( - pairedDeviceList, this.fakePairedDevice.name); - assertTrue(!!element, this.fakePairedDevice.name); - expectFalse(!!element.getAttribute('connected')); - - var connectButton = $('bluetooth-reconnect-device'); - expectTrue(connectButton.disabled); - - // Simulate connecting to a previously paired device. - this.selectDevice(pairedDeviceList, this.fakePairedDevice.address); - expectFalse(connectButton.disabled); - connectButton.click(); - - // Call bluetooth.getAdapterState to ensure that all state has been - // updated. - chrome.bluetooth.getAdapterState(function(state) { - element = this.getElementForDevice( - pairedDeviceList, this.fakePairedDevice.name); - expectTrue(!!element.getAttribute('connected')); - var deleteButton = element.querySelector('.row-delete-button'); - expectTrue(!!deleteButton); - testDone(); - }.bind(this)); - }.bind(this)); - }.bind(this)); -}); - -TEST_F('BluetoothWebUITestAsync', 'testDisconnect', function() { - assertEquals(this.browsePreload, document.location.href); - - // Enable bluetooth. - $('enable-bluetooth').click(); - - // Wait for the UI to process any pending messages. - window.setTimeout(function() { - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - var pairedDeviceList = $('bluetooth-paired-devices-list'); - - // First connect to the device so that the fake implementation state is - // connected. - chrome.bluetoothPrivate.connect( - this.fakePairedDevice.address, function(result) { - assertEquals( - chrome.bluetoothPrivate.ConnectResultType.SUCCESS, result); - - var element = this.getElementForDevice( - pairedDeviceList, this.fakePairedDevice.name); - assertTrue(!!element, this.fakePairedDevice.name); - expectTrue(!!element.getAttribute('connected')); - - // Simulate disconnecting from a connected device. - var button = element.querySelector('.row-delete-button'); - button.click(); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - element = this.getElementForDevice( - pairedDeviceList, this.fakePairedDevice.name); - expectFalse(!!element.getAttribute('connected')); - button = element.querySelector('.row-delete-button'); - expectTrue(!!button); - testDone(); - }.bind(this)); - }.bind(this)); - }.bind(this)); - }.bind(this)); -}); - -// TODO(crbug.com/605090): Disabled because of flakiness. -TEST_F('BluetoothWebUITestAsync', 'DISABLED_testForget', function() { - assertEquals(this.browsePreload, document.location.href); - - // Enable bluetooth. - $('enable-bluetooth').click(); - - // Wait for the UI to process any pending messages. - window.setTimeout(function() { - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - var pairedDeviceList = $('bluetooth-paired-devices-list'); - - var element = this.getElementForDevice(pairedDeviceList, - this.fakePairedDevice.name); - var button = element.querySelector('.row-delete-button'); - button.click(); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - expectFalse(!!this.getElementForDevice(pairedDeviceList, - this.fakePairedDevice.name)); - testDone(); - }.bind(this)); - }.bind(this)); - }.bind(this)); -}); - - -TEST_F('BluetoothWebUITestAsync', 'testMaliciousInput', function() { - assertEquals(this.browsePreload, document.location.href); - - var maliciousStrings = [ - '<SCRIPT>alert(1)</SCRIPT>', - '>\'>\\"><SCRIPT>alert(1)</SCRIPT>', - '<IMG SRC=\\"javascript:alert(1)\\">', - '<A HREF=\\"data:text/html;base64,' + - 'PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo=\\">..</A>', - '<div>', - '<textarea>', - '<style>', - '[0xC0][0xBC]SCRIPT[0xC0][0xBE]alert(1)[0xC0][0xBC]/SCRIPT[0xC0][0xBE]', - '+ADw-SCRIPT+AD4-alert(1)+ADw-/SCRIPT+AD4-', - '&#<script>alert(1)</script>;', - '<!-- Hello -- world > <SCRIPT>alert(1)</SCRIPT> -->', - '<!<!-- Hello world > <SCRIPT>alert(1)</SCRIPT> -->', - '\x3CSCRIPT\x3Ealert(1)\x3C/SCRIPT\x3E', - '<IMG SRC=\\"j[0x00]avascript:alert(1)\\">', - '<BASE HREF=\\"javascript:1;/**/\\"><IMG SRC=\\"alert(1)\\">', - 'javascript:alert(1);', - ' xss_injection=\\"\\" ', - '\\" xss_injection=\\"', - '\' xss_injection=\'', - '<!--', - '\'', - '\\"' - ]; - - var fakeEvent = { - device: { - address: '28:CF:DA:00:00:00', - connectable: true, - connected: false, - name: 'Bluetooth 2.0 Mouse', - paired: false - }, - pairing: 'bluetoothStartConnecting' - }; - - var nodeCount = function(node) { - if (node.getAttribute) - assertFalse(!!node.getAttribute('xss_injection')); - var length = node.childNodes.length; - var tally = length; - for (var i = 0; i < length; i++) { - tally += nodeCount(node.childNodes[i]); - } - return tally; - }; - - // Enable bluetooth. - $('enable-bluetooth').click(); - - // Wait for the UI to process any pending messages. - window.setTimeout(function() { - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - var unpairedDeviceList = $('bluetooth-unpaired-devices-list'); - var pairDeviceDialog = $('bluetooth-pairing'); - - // Show the pairing dialog. - $('bluetooth-add-device').click(); - BluetoothPairing.showDialog(fakeEvent); - - // Wait for fake bluetooth impl to send any updates. - chrome.bluetooth.getAdapterState(function(state) { - expectFalse(unpairedDeviceList.parentNode.hidden); - - // Determine the expected sizes. - var unpairedDeviceListSize = nodeCount(unpairedDeviceList); - var pairDeviceDialogSize = nodeCount(pairDeviceDialog); - - // Ensure that updating the device with a malicious name does not - // corrupt the structure of the document. Tests the unpaired device - // list and bluetooth pairing dialog. - for (var i = 0; i < maliciousStrings.length; i++) { - fakeEvent.device.name = maliciousStrings[i]; - BluetoothPairing.showDialog(fakeEvent); - assertEquals(unpairedDeviceListSize, nodeCount(unpairedDeviceList)); - var element = this.getElementForDevice( - unpairedDeviceList, fakeEvent.device.name); - assertTrue(!!element, fakeEvent.device.name); - var label = element.querySelector('.bluetooth-device-label'); - assertTrue(!!label); - assertEquals(maliciousStrings[i], label.textContent); - assertEquals(pairDeviceDialogSize, nodeCount(pairDeviceDialog)); - } - - testDone(); - }.bind(this)); - }.bind(this)); - }.bind(this)); -}); - -GEN('#endif');
diff --git a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler_unittest.cc b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler_unittest.cc deleted file mode 100644 index 74dbe66..0000000 --- a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler_unittest.cc +++ /dev/null
@@ -1,92 +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 "chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.h" - -#include <memory> - -#include "base/values.h" -#include "chrome/browser/chromeos/input_method/input_method_configuration.h" -#include "chrome/browser/ui/webui/chromeos/login/l10n_util_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace chromeos { -namespace options { - -class CrosLanguageOptionsHandlerTest : public testing::Test { - public: - CrosLanguageOptionsHandlerTest() - : input_manager_(new MockInputMethodManagerWithInputMethods) { - chromeos::input_method::InitializeForTesting(input_manager_); - } - - ~CrosLanguageOptionsHandlerTest() override { - chromeos::input_method::Shutdown(); - } - - // testing::Test: - void SetUp() override { - input_manager_->AddInputMethod("xkb:us::eng", "us", "en-US"); - input_manager_->AddInputMethod("xkb:fr::fra", "fr", "fr"); - input_manager_->AddInputMethod("xkb:be::fra", "be", "fr"); - input_manager_->AddInputMethod("xkb:is::ice", "is", "is"); - } - - private: - MockInputMethodManagerWithInputMethods* input_manager_; -}; - -TEST_F(CrosLanguageOptionsHandlerTest, GetInputMethodList) { - std::unique_ptr<base::ListValue> list( - CrosLanguageOptionsHandler::GetInputMethodList()); - ASSERT_EQ(4U, list->GetSize()); - - base::DictionaryValue* entry = NULL; - base::DictionaryValue *language_code_set = NULL; - std::string input_method_id; - std::string display_name; - std::string language_code; - - // As shown below, the list should be input method ids should appear in - // the same order of the descriptors. - ASSERT_TRUE(list->GetDictionary(0, &entry)); - ASSERT_TRUE(entry->GetString("id", &input_method_id)); - ASSERT_TRUE(entry->GetString("displayName", &display_name)); - ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set)); - EXPECT_EQ("xkb:us::eng", input_method_id); - // Commented out as it depends on translation in generated_resources.grd - // (i.e. makes the test fragile). - // EXPECT_EQ("English (USA) keyboard layout", display_name); - ASSERT_TRUE(language_code_set->HasKey("en-US")); - - ASSERT_TRUE(list->GetDictionary(1, &entry)); - ASSERT_TRUE(entry->GetString("id", &input_method_id)); - ASSERT_TRUE(entry->GetString("displayName", &display_name)); - ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set)); - EXPECT_EQ("xkb:fr::fra", input_method_id); - // Commented out. See above. - // EXPECT_EQ("French keyboard layout", display_name); - ASSERT_TRUE(language_code_set->HasKey("fr")); - - ASSERT_TRUE(list->GetDictionary(2, &entry)); - ASSERT_TRUE(entry->GetString("id", &input_method_id)); - ASSERT_TRUE(entry->GetString("displayName", &display_name)); - ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set)); - EXPECT_EQ("xkb:be::fra", input_method_id); - // Commented out. See above. - // EXPECT_EQ("Belgian keyboard layout", display_name); - ASSERT_TRUE(language_code_set->HasKey("fr")); - - ASSERT_TRUE(list->GetDictionary(3, &entry)); - ASSERT_TRUE(entry->GetString("id", &input_method_id)); - ASSERT_TRUE(entry->GetString("displayName", &display_name)); - ASSERT_TRUE(entry->GetDictionary("languageCodeSet", &language_code_set)); - EXPECT_EQ("xkb:is::ice", input_method_id); - // Commented out. See above. - // EXPECT_EQ("Japanese input method (for US keyboard)", display_name); - ASSERT_TRUE(language_code_set->HasKey("is")); -} - -} // namespace options -} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options/chromeos/date_time_options_browsertest.js b/chrome/browser/ui/webui/options/chromeos/date_time_options_browsertest.js deleted file mode 100644 index 4f0845b..0000000 --- a/chrome/browser/ui/webui/options/chromeos/date_time_options_browsertest.js +++ /dev/null
@@ -1,38 +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. - -GEN_INCLUDE(['../options_browsertest_base.js']); - -GEN('#if defined(OS_CHROMEOS)'); - -/** - * DateTimeOptionsWebUITest tests the date and time section of the options page. - * @constructor - * @extends {testing.Test} - */ -function DateTimeOptionsWebUITest() {} - -DateTimeOptionsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to date/time options. - * @override - */ - browsePreload: 'chrome://settings-frame/search#date', -}; - -TEST_F('DateTimeOptionsWebUITest', 'testShowSetTimeButton', function() { - assertEquals(this.browsePreload, document.location.href); - - // Show button. - BrowserOptions.setCanSetTime(true); - expectFalse($('set-time').hidden); - - // Hide button. - BrowserOptions.setCanSetTime(false); - expectTrue($('set-time').hidden); -}); - -GEN('#endif');
diff --git a/chrome/browser/ui/webui/options/chromeos/power_overlay_browsertest.js b/chrome/browser/ui/webui/options/chromeos/power_overlay_browsertest.js deleted file mode 100644 index d49131c..0000000 --- a/chrome/browser/ui/webui/options/chromeos/power_overlay_browsertest.js +++ /dev/null
@@ -1,175 +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. - -GEN_INCLUDE(['../options_browsertest_base.js']); - -function PowerOverlayWebUITest() {} - -PowerOverlayWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - browsePreload: 'chrome://settings-frame/', - - commandLineSwitches: [{ - switchName: 'enable-power-overlay', - }], - - /** @override */ - preLoad: function() { - this.makeAndRegisterMockHandler([ - 'updatePowerStatus', - 'setPowerSource', - ]); - this.mockHandler.expects(atLeastOnce()).updatePowerStatus(); - }, - - /** - * Sets power sources using a deep copy of |sources|. - * @param {Array<Object>} sources - * @param {string} sourceId - * @param {bool} isUsbCharger - * @param {bool} isCalculating - */ - setPowerSources: function(sources, sourceId, isUsbCharger, isCalculating) { - var sourcesCopy = sources.map(function(source) { - return Object.assign({}, source); - }); - options.PowerOverlay.setPowerSources( - sourcesCopy, sourceId, isUsbCharger, isCalculating); - }, - - /** - * Simulates the user selecting a power source, verifying that the overlay - * calls setPowerSource. - * @param {string} sourceId - */ - selectPowerSource: function(sourceId) { - this.mockHandler.expects(once()).setPowerSource(eq(sourceId)); - $('power-source-dropdown').value = sourceId; - expectTrue(cr.dispatchSimpleEvent($('power-source-dropdown'), 'change')); - }, - - /** - * Checks that the sources dropdown is visible. - * @param {string} sourceId The ID of the source that should be selected. - */ - checkSource: function(sourceId) { - expectTrue($('power-source-charger').hidden); - expectFalse($('power-sources').hidden); - expectEquals(sourceId, $('power-source-dropdown').value); - }, - - checkNoSources: function() { - expectTrue($('power-source-charger').hidden); - expectTrue($('power-sources').hidden); - }, - - checkDedicatedCharger: function() { - expectFalse($('power-source-charger').hidden); - expectTrue($('power-sources').hidden); - }, -}; - -TEST_F('PowerOverlayWebUITest', 'testNoPowerSources', function() { - assertEquals(this.browsePreload, document.location.href); - this.mockHandler.expects(never()).setPowerSource(); - $('power-settings-link').click(); - - // This should be the initial state. - this.checkNoSources(); - - // Setting an empty sources list shouldn't change the state. - this.setPowerSources([], '', false, false); - this.checkNoSources(); -}); - -TEST_F('PowerOverlayWebUITest', 'testDedicatedCharger', function() { - assertEquals(this.browsePreload, document.location.href); - this.mockHandler.expects(never()).setPowerSource(); - $('power-settings-link').click(); - - var fakeSources = [{ - id: 'source1', - description: 'Left port', - type: options.PowerStatusDeviceType.DEDICATED_CHARGER, - }]; - - this.setPowerSources(fakeSources, 'source1', false, false); - this.checkDedicatedCharger(); - - // Remove the charger. - this.setPowerSources([], ''); - this.checkNoSources(); - - // Set a low-powered charger. - this.setPowerSources(fakeSources, 'source1', true, false); - this.checkDedicatedCharger(); -}); - -TEST_F('PowerOverlayWebUITest', 'testSingleSource', function() { - assertEquals(this.browsePreload, document.location.href); - $('power-settings-link').click(); - - var fakeSources = [{ - id: 'source1', - description: 'Left port', - type: options.PowerStatusDeviceType.DUAL_ROLE_USB, - }]; - - this.setPowerSources(fakeSources, '', false, false); - this.checkSource(''); - - this.selectPowerSource('source1'); - this.checkSource('source1'); - - // Remove the device. - this.setPowerSources([], '', false, false); - this.checkNoSources(); -}); - -TEST_F('PowerOverlayWebUITest', 'testMultipleSources', function() { - assertEquals(this.browsePreload, document.location.href); - $('power-settings-link').click(); - - var fakeSources = [{ - id: 'source1', - description: 'Left port', - type: options.PowerStatusDeviceType.DUAL_ROLE_USB, - }, { - id: 'source2', - description: 'Right port', - type: options.PowerStatusDeviceType.DUAL_ROLE_USB, - }, { - id: 'source3', - description: 'Front port', - type: options.PowerStatusDeviceType.DUAL_ROLE_USB, - }, { - id: 'source4', - description: 'Rear port', - type: options.PowerStatusDeviceType.DUAL_ROLE_USB, - }]; - - // Use a dual-role device. - this.setPowerSources(fakeSources, 'source2', false, false); - this.checkSource('source2'); - - // Use a USB charger. - this.setPowerSources(fakeSources, 'source3', true, false); - this.checkSource('source3'); - - // Remove the currently used device. - fakeSources.splice(2, 1); - this.setPowerSources(fakeSources, 'source4', false, false); - this.checkSource('source4'); - - // Do not charge (use battery). - this.setPowerSources(fakeSources, '', false, false); - this.checkSource(''); - - // The user selects a device. - this.selectPowerSource('source1'); - - // The user selects the battery. - this.selectPowerSource(''); -});
diff --git a/chrome/browser/ui/webui/options/chromeos/shared_options_browsertest.cc b/chrome/browser/ui/webui/options/chromeos/shared_options_browsertest.cc deleted file mode 100644 index 7e7b7fa..0000000 --- a/chrome/browser/ui/webui/options/chromeos/shared_options_browsertest.cc +++ /dev/null
@@ -1,467 +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 <stddef.h> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/strings/stringprintf.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/chromeos/login/login_manager_test.h" -#include "chrome/browser/chromeos/login/startup_utils.h" -#include "chrome/browser/chromeos/login/ui/user_adding_screen.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/ui_test_utils.h" -#include "chromeos/settings/cros_settings_names.h" -#if defined(GOOGLE_CHROME_BUILD) -#include "components/spellcheck/browser/pref_names.h" -#endif -#include "components/prefs/pref_service.h" -#include "components/signin/core/browser/signin_manager.h" -#include "components/user_manager/user_manager.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/browser_test_utils.h" -#include "content/public/test/test_utils.h" - -namespace chromeos { - -namespace { - -// Because policy is not needed in this test it is better to use e-mails that -// are definitely not enterprise. This lets us to avoid faking of policy fetch -// procedure. -const char* kTestOwner = "test-owner@gmail.com"; -const char* kTestNonOwner = "test-user1@gmail.com"; - -const char* kKnownSettings[] = { - kDeviceOwner, - kAccountsPrefAllowGuest, - kAccountsPrefAllowNewUser, - kAccountsPrefDeviceLocalAccounts, - kAccountsPrefShowUserNamesOnSignIn, - kAccountsPrefSupervisedUsersEnabled, -}; - -// Stub settings provider that only handles the settings we need to control. -// StubCrosSettingsProvider handles more settings but leaves many of them unset -// which the Settings page doesn't expect. -class StubAccountSettingsProvider : public StubCrosSettingsProvider { - public: - StubAccountSettingsProvider() { - } - - ~StubAccountSettingsProvider() override {} - - // StubCrosSettingsProvider implementation. - bool HandlesSetting(const std::string& path) const override { - const char** end = kKnownSettings + arraysize(kKnownSettings); - return std::find(kKnownSettings, end, path) != end; - } -}; - -struct PrefTest { - const char* pref_name; - bool owner_only; - bool indicator; -}; - -const PrefTest kPrefTests[] = { - { kSystemTimezone, false, false }, - { prefs::kUse24HourClock, false, false }, - { kAttestationForContentProtectionEnabled, true, true }, - { kAccountsPrefAllowGuest, true, false }, - { kAccountsPrefAllowNewUser, true, false }, - { kAccountsPrefShowUserNamesOnSignIn, true, false }, - { kAccountsPrefSupervisedUsersEnabled, true, false }, -#if defined(GOOGLE_CHROME_BUILD) - { kStatsReportingPref, true, true }, - { spellcheck::prefs::kSpellCheckUseSpellingService, false, false }, -#endif -}; - -} // namespace - -class SharedOptionsTest : public LoginManagerTest { - public: - SharedOptionsTest() - : LoginManagerTest(false), - stub_settings_provider_(base::MakeUnique<StubCrosSettingsProvider>()), - stub_settings_provider_ptr_(static_cast<StubCrosSettingsProvider*>( - stub_settings_provider_.get())), - test_owner_account_id_(AccountId::FromUserEmail(kTestOwner)), - test_non_owner_account_id_(AccountId::FromUserEmail(kTestNonOwner)) { - stub_settings_provider_->Set(kDeviceOwner, base::Value(kTestOwner)); - } - - ~SharedOptionsTest() override {} - - void SetUpOnMainThread() override { - LoginManagerTest::SetUpOnMainThread(); - - CrosSettings* settings = CrosSettings::Get(); - - // Add the stub settings provider, moving the device settings provider - // behind it so our stub takes precedence. - std::unique_ptr<CrosSettingsProvider> device_settings_provider = - settings->RemoveSettingsProvider(settings->GetProvider(kDeviceOwner)); - settings->AddSettingsProvider(std::move(stub_settings_provider_)); - settings->AddSettingsProvider(std::move(device_settings_provider)); - - // Notify ChromeUserManager of ownership change. - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_OWNERSHIP_STATUS_CHANGED, - content::Source<SharedOptionsTest>(this), - content::NotificationService::NoDetails()); - } - - void TearDownOnMainThread() override { - CrosSettings* settings = CrosSettings::Get(); - settings->RemoveSettingsProvider(stub_settings_provider_ptr_); - LoginManagerTest::TearDownOnMainThread(); - } - - protected: - void CheckOptionsUI(const user_manager::User* user, - bool is_owner, - bool is_primary) { - ASSERT_NE(nullptr, user); - Browser* browser = CreateBrowserForUser(user); - content::WebContents* contents = - browser->tab_strip_model()->GetActiveWebContents(); - - for (size_t i = 0; i < sizeof(kPrefTests) / sizeof(kPrefTests[0]); i++) { - bool disabled = !is_owner && kPrefTests[i].owner_only; - if (strcmp(kPrefTests[i].pref_name, kSystemTimezone) == 0) { - disabled = ProfileHelper::Get() - ->GetProfileByUser(user) - ->GetPrefs() - ->GetBoolean(prefs::kResolveTimezoneByGeolocation); - } - - CheckPreference( - contents, kPrefTests[i].pref_name, disabled, - !is_owner && kPrefTests[i].indicator ? "owner" : std::string()); - } - CheckBanner(contents, is_primary); - CheckSharedSections(contents, is_primary); - CheckAccountsOverlay(contents, is_owner); - } - - // Creates a browser and navigates to the Settings page. - Browser* CreateBrowserForUser(const user_manager::User* user) { - Profile* profile = ProfileHelper::Get()->GetProfileByUser(user); - SigninManagerFactory::GetForProfile(profile)->SetAuthenticatedAccountInfo( - GetGaiaIDForUserID(user->GetAccountId().GetUserEmail()), - user->GetAccountId().GetUserEmail()); - - ui_test_utils::BrowserAddedObserver observer; - Browser* browser = CreateBrowser(profile); - observer.WaitForSingleNewBrowser(); - - ui_test_utils::NavigateToURL(browser, - GURL("chrome://settings-frame")); - return browser; - } - - // Verifies a preference's disabled state and controlled-by indicator. - void CheckPreference(content::WebContents* contents, - std::string pref_name, - bool disabled, - std::string controlled_by) { - bool success; - std::string js_expression = base::StringPrintf( - "var prefSelector = '[pref=\"%s\"]';" - "var controlledBy = '%s';" - "var input = document.querySelector(" - " 'input' + prefSelector + ', select' + prefSelector);" - "var success = false;" - "if (input) {" - " success = input.disabled == %d;" - " var indicator = input.parentNode.parentNode.querySelector(" - " '.controlled-setting-indicator');" - " if (controlledBy) {" - " success = success && indicator &&" - " indicator.getAttribute('controlled-by') == controlledBy;" - " } else {" - " success = success && (!indicator ||" - " !indicator.hasAttribute('controlled-by') ||" - " indicator.getAttribute('controlled-by') == '')" - " }" - "}" - "window.domAutomationController.send(!!success);", - pref_name.c_str(), controlled_by.c_str(), disabled); - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, js_expression, &success)); - EXPECT_TRUE(success); - } - - // Verifies a checkbox's disabled state, controlled-by indicator and value. - void CheckBooleanPreference(content::WebContents* contents, - std::string pref_name, - bool disabled, - std::string controlled_by, - bool expected_value) { - CheckPreference(contents, pref_name, disabled, controlled_by); - bool actual_value; - std::string js_expression = base::StringPrintf( - "window.domAutomationController.send(document.querySelector('" - " input[type=\"checkbox\"][pref=\"%s\"]').checked);", - pref_name.c_str()); - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, js_expression, &actual_value)); - EXPECT_EQ(expected_value, actual_value); - } - - // Verifies that the shared settings banner is visible only for - // secondary users. - void CheckBanner(content::WebContents* contents, - bool is_primary) { - bool banner_visible; - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, - "var e = $('secondary-user-banner');" - "window.domAutomationController.send(e && !e.hidden);", - &banner_visible)); - EXPECT_EQ(!is_primary, banner_visible); - } - - // Verifies that sections of shared settings have the appropriate indicator. - void CheckSharedSections(content::WebContents* contents, - bool is_primary) { - // This only applies to the Internet options section. - std::string controlled_by; - ASSERT_TRUE(content::ExecuteScriptAndExtractString( - contents, - "var e = document.querySelector(" - " '#network-section-header span.controlled-setting-indicator');" - "if (!e || !e.getAttribute('controlled-by')) {" - " window.domAutomationController.send('');" - "} else {" - " window.domAutomationController.send(" - " e.getAttribute('controlled-by'));" - "}", - &controlled_by)); - EXPECT_EQ(!is_primary ? "shared" : std::string(), controlled_by); - } - - // Checks the Accounts header and non-checkbox inputs. - void CheckAccountsOverlay(content::WebContents* contents, bool is_owner) { - // Set cros.accounts.allowGuest to false so we can test the accounts list. - // This has to be done after the PRE_* test or we can't add the owner. - stub_settings_provider_ptr_->Set(kAccountsPrefAllowNewUser, - base::Value(false)); - - bool success; - std::string js_expression = base::StringPrintf( - "var controlled = %d;" - "var warning = $('ownerOnlyWarning');" - "var userList = $('userList');" - "var input = $('userNameEdit');" - "var success;" - "if (controlled)" - " success = warning && !warning.hidden && userList.disabled &&" - " input.disabled;" - "else" - " success = (!warning || warning.hidden) && !userList.disabled &&" - " !input.disabled;" - "window.domAutomationController.send(!!success);", - !is_owner); - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - contents, js_expression, &success)); - EXPECT_TRUE(success) << "Accounts overlay incorrect for " << - (is_owner ? "owner." : "non-owner."); - } - - std::unique_ptr<CrosSettingsProvider> stub_settings_provider_; - StubCrosSettingsProvider* stub_settings_provider_ptr_; - - const AccountId test_owner_account_id_; - const AccountId test_non_owner_account_id_; - - private: - DISALLOW_COPY_AND_ASSIGN(SharedOptionsTest); -}; - -IN_PROC_BROWSER_TEST_F(SharedOptionsTest, PRE_SharedOptions) { - RegisterUser(test_owner_account_id_.GetUserEmail()); - RegisterUser(test_non_owner_account_id_.GetUserEmail()); - StartupUtils::MarkOobeCompleted(); -} - -IN_PROC_BROWSER_TEST_F(SharedOptionsTest, SharedOptions) { - // Log in the owner first, then add a secondary user. - LoginUser(test_owner_account_id_.GetUserEmail()); - UserAddingScreen::Get()->Start(); - content::RunAllPendingInMessageLoop(); - AddUser(test_non_owner_account_id_.GetUserEmail()); - - user_manager::UserManager* manager = user_manager::UserManager::Get(); - ASSERT_EQ(2u, manager->GetLoggedInUsers().size()); - { - SCOPED_TRACE("Checking settings for owner, primary user."); - CheckOptionsUI(manager->FindUser(manager->GetOwnerAccountId()), true, true); - } - { - SCOPED_TRACE("Checking settings for non-owner, secondary user."); - CheckOptionsUI(manager->FindUser(test_non_owner_account_id_), false, false); - } - // TODO(michaelpg): Add tests for non-primary owner and primary non-owner - // when the owner-only multiprofile restriction is removed, probably M38. -} - -IN_PROC_BROWSER_TEST_F(SharedOptionsTest, PRE_ScreenLockPreferencePrimary) { - RegisterUser(test_owner_account_id_.GetUserEmail()); - RegisterUser(test_non_owner_account_id_.GetUserEmail()); - StartupUtils::MarkOobeCompleted(); -} - -// Tests the shared setting indicator for the primary user's auto-lock setting -// when the secondary user has enabled or disabled their preference. -// (The checkbox is unset if the current user's preference is false, but if any -// other signed-in user has enabled this preference, the shared setting -// indicator explains this.) -IN_PROC_BROWSER_TEST_F(SharedOptionsTest, ScreenLockPreferencePrimary) { - LoginUser(test_owner_account_id_.GetUserEmail()); - UserAddingScreen::Get()->Start(); - content::RunAllPendingInMessageLoop(); - AddUser(test_non_owner_account_id_.GetUserEmail()); - - user_manager::UserManager* manager = user_manager::UserManager::Get(); - const user_manager::User* user1 = manager->FindUser(test_owner_account_id_); - const user_manager::User* user2 = - manager->FindUser(test_non_owner_account_id_); - - PrefService* prefs1 = - ProfileHelper::Get()->GetProfileByUser(user1)->GetPrefs(); - PrefService* prefs2 = - ProfileHelper::Get()->GetProfileByUser(user2)->GetPrefs(); - - // Set both users' preference to false, then change the secondary user's to - // true. We'll do the opposite in the next test. Doesn't provide 100% coverage - // but reloading the settings page is super slow on debug builds. - prefs1->SetBoolean(prefs::kEnableAutoScreenLock, false); - prefs2->SetBoolean(prefs::kEnableAutoScreenLock, false); - - Browser* browser = CreateBrowserForUser(user1); - content::WebContents* contents = - browser->tab_strip_model()->GetActiveWebContents(); - - bool disabled = false; - bool expected_value; - std::string empty_controlled; - std::string shared_controlled("shared"); - - { - SCOPED_TRACE("Screen lock false for both users"); - expected_value = false; - CheckBooleanPreference(contents, prefs::kEnableAutoScreenLock, disabled, - empty_controlled, expected_value); - } - - // Set the secondary user's preference to true, and reload the primary user's - // browser to see the updated controlled-by indicator. - prefs2->SetBoolean(prefs::kEnableAutoScreenLock, true); - chrome::Reload(browser, WindowOpenDisposition::CURRENT_TAB); - content::WaitForLoadStop(contents); - { - SCOPED_TRACE("Screen lock false for primary user"); - expected_value = false; - CheckBooleanPreference(contents, prefs::kEnableAutoScreenLock, disabled, - shared_controlled, expected_value); - } - - // Set the preference to true for the primary user and check that the - // indicator disappears. - prefs1->SetBoolean(prefs::kEnableAutoScreenLock, true); - { - SCOPED_TRACE("Screen lock true for both users"); - expected_value = true; - CheckBooleanPreference(contents, prefs::kEnableAutoScreenLock, disabled, - empty_controlled, expected_value); - } -} - -IN_PROC_BROWSER_TEST_F(SharedOptionsTest, PRE_ScreenLockPreferenceSecondary) { - RegisterUser(test_owner_account_id_.GetUserEmail()); - RegisterUser(test_non_owner_account_id_.GetUserEmail()); - StartupUtils::MarkOobeCompleted(); -} - -// Tests the shared setting indicator for the secondary user's auto-lock setting -// when the primary user has enabled or disabled their preference. -// (The checkbox is unset if the current user's preference is false, but if any -// other signed-in user has enabled this preference, the shared setting -// indicator explains this.) -IN_PROC_BROWSER_TEST_F(SharedOptionsTest, ScreenLockPreferenceSecondary) { - LoginUser(test_owner_account_id_.GetUserEmail()); - UserAddingScreen::Get()->Start(); - content::RunAllPendingInMessageLoop(); - AddUser(test_non_owner_account_id_.GetUserEmail()); - - user_manager::UserManager* manager = user_manager::UserManager::Get(); - const user_manager::User* user1 = manager->FindUser(test_owner_account_id_); - const user_manager::User* user2 = - manager->FindUser(test_non_owner_account_id_); - - PrefService* prefs1 = - ProfileHelper::Get()->GetProfileByUser(user1)->GetPrefs(); - PrefService* prefs2 = - ProfileHelper::Get()->GetProfileByUser(user2)->GetPrefs(); - - // Set both users' preference to true, then change the secondary user's to - // false. - prefs1->SetBoolean(prefs::kEnableAutoScreenLock, true); - prefs2->SetBoolean(prefs::kEnableAutoScreenLock, true); - - Browser* browser = CreateBrowserForUser(user2); - content::WebContents* contents = - browser->tab_strip_model()->GetActiveWebContents(); - - bool disabled = false; - bool expected_value; - std::string empty_controlled; - std::string shared_controlled("shared"); - - { - SCOPED_TRACE("Screen lock true for both users"); - expected_value = true; - CheckBooleanPreference(contents, prefs::kEnableAutoScreenLock, disabled, - empty_controlled, expected_value); - } - - // Set the secondary user's preference to false and check that the - // controlled-by indicator is shown. - prefs2->SetBoolean(prefs::kEnableAutoScreenLock, false); - { - SCOPED_TRACE("Screen lock false for secondary user"); - expected_value = false; - CheckBooleanPreference(contents, prefs::kEnableAutoScreenLock, disabled, - shared_controlled, expected_value); - } - - // Set the preference to false for the primary user and check that the - // indicator disappears. - prefs1->SetBoolean(prefs::kEnableAutoScreenLock, false); - chrome::Reload(browser, WindowOpenDisposition::CURRENT_TAB); - content::WaitForLoadStop(contents); - { - SCOPED_TRACE("Screen lock false for both users"); - expected_value = false; - CheckBooleanPreference(contents, prefs::kEnableAutoScreenLock, disabled, - empty_controlled, expected_value); - } -} - -} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options/content_options_browsertest.js b/chrome/browser/ui/webui/options/content_options_browsertest.js deleted file mode 100644 index 863fb28f..0000000 --- a/chrome/browser/ui/webui/options/content_options_browsertest.js +++ /dev/null
@@ -1,27 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for content options WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function ContentOptionsWebUITest() {} - -ContentOptionsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to content options. - * @override - */ - browsePreload: 'chrome://settings-frame/content', -}; - -// Test opening the content options has correct location. -TEST_F('ContentOptionsWebUITest', 'testOpenContentOptions', function() { - assertEquals(this.browsePreload, document.location.href); -});
diff --git a/chrome/browser/ui/webui/options/content_settings_exception_area_browsertest.js b/chrome/browser/ui/webui/options/content_settings_exception_area_browsertest.js deleted file mode 100644 index 7cfc1ed..0000000 --- a/chrome/browser/ui/webui/options/content_settings_exception_area_browsertest.js +++ /dev/null
@@ -1,109 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for content settings exception area WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function ContentSettingsExceptionAreaWebUITest() {} - -ContentSettingsExceptionAreaWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/contentExceptions', -}; - -// See crbug.com/579666 for OS_LINUX and crbug.com/588586 for Windows and -// crbug.com/718947 for Mac. -GEN('#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN) || ' + - 'defined(OS_MACOSX)'); -GEN('#define MAYBE_testOpenContentSettingsExceptionArea ' + - 'DISABLED_testOpenContentSettingsExceptionArea'); -GEN('#else'); -GEN('#define MAYBE_testOpenContentSettingsExceptionArea ' + - 'testOpenContentSettingsExceptionArea'); -GEN('#endif // defined(OS_CHROMEOS) || defined(OS_LINUX)'); -// Test opening the content settings exception area has correct location. -TEST_F('ContentSettingsExceptionAreaWebUITest', - 'MAYBE_testOpenContentSettingsExceptionArea', function() { - assertEquals(this.browsePreload, document.location.href); -}); - -/** - * A class to asynchronously test the content settings exception area dialog. - * @extends {testing.Test} - * @constructor - */ -function ContentSettingsExceptionsAreaAsyncWebUITest() {} - -ContentSettingsExceptionsAreaAsyncWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/contentExceptions', - - /** @override */ - isAsync: true, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/570562 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - '#content-settings-exceptions-area > .content-area > *'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/570563 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#content-settings-exceptions-area > .action-area > *'); - }, -}; - -// Adds and removes a location content setting exception. -TEST_F('ContentSettingsExceptionsAreaAsyncWebUITest', - 'testAddRemoveLocationExceptions', function() { - assertEquals(this.browsePreload, document.location.href); - - /** @const */ var origin = 'http://google.com:80'; - /** @const */ var setExceptions = ContentSettings.setExceptions; - - var list = ContentSettings.getExceptionsList('cookies', 'normal'); - assertEquals(1, list.items.length); - - var setExceptionsCounter = 0; - var setExceptionsCallback = function() { - setExceptionsCounter++; - if (setExceptionsCounter == 1) { - // The first item is now the exception (edit items are always last). - expectEquals('block', list.dataModel.item(0).setting); - expectEquals(origin, list.dataModel.item(0).origin); - - // Delete the item and verify it worked. - list.deleteItemAtIndex(0); - } else if (setExceptionsCounter == 2) { - // Verify the item was deleted, restore the original method, and finish. - expectEquals(1, list.items.length); - ContentSettings.setExceptions = setExceptions; - testDone(); - } - }; - - // NOTE: if this test doesn't succeed, |ContentSettings.setExceptions| may not - // be restored to its original method. I know no easy way to fix this. - ContentSettings.setExceptions = function() { - setExceptions.apply(ContentSettings, arguments); - setExceptionsCallback(); - }; - - // Add an item to the location exception area to start the test. - list.items[0].finishEdit(origin, 'block'); -});
diff --git a/chrome/browser/ui/webui/options/cookies_view_browsertest.js b/chrome/browser/ui/webui/options/cookies_view_browsertest.js deleted file mode 100644 index e2c094d..0000000 --- a/chrome/browser/ui/webui/options/cookies_view_browsertest.js +++ /dev/null
@@ -1,60 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for cookies view WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function CookiesViewWebUITest() {} - -CookiesViewWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to the cookies view. - */ - browsePreload: 'chrome://settings-frame/cookies', - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/570560 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - '#cookies-view-page > .content-area.cookies-list-content-area > *'); - - var requiredOwnedAriaRoleMissingSelectors = [ - '#default-search-engine-list', - '#other-search-engine-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/605689 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - }, -}; - -// Test opening the cookies view has correct location. -TEST_F('CookiesViewWebUITest', 'testOpenCookiesView', function() { - assertEquals(this.browsePreload, document.location.href); -}); - -TEST_F('CookiesViewWebUITest', 'testNoCloseOnSearchEnter', function() { - var cookiesView = CookiesView.getInstance(); - assertTrue(cookiesView.visible); - var searchBox = cookiesView.pageDiv.querySelector('.cookies-search-box'); - searchBox.dispatchEvent(new KeyboardEvent('keydown', { - 'bubbles': true, - 'cancelable': true, - 'key': 'Enter' - })); - assertTrue(cookiesView.visible); -});
diff --git a/chrome/browser/ui/webui/options/edit_dictionary_browsertest.js b/chrome/browser/ui/webui/options/edit_dictionary_browsertest.js deleted file mode 100644 index 5bcb0e0b..0000000 --- a/chrome/browser/ui/webui/options/edit_dictionary_browsertest.js +++ /dev/null
@@ -1,166 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for EditDictionaryOverlay WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function EditDictionaryWebUITest() {} - -EditDictionaryWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to the edit dictionary page & call our preLoad(). - */ - browsePreload: 'chrome://settings-frame/editDictionary', - - /** - * Register a mock dictionary handler. - */ - preLoad: function() { - this.makeAndRegisterMockHandler( - ['refreshDictionaryWords', - 'addDictionaryWord', - 'removeDictionaryWord', - ]); - this.mockHandler.stubs().refreshDictionaryWords(). - will(callFunction(function() { - EditDictionaryOverlay.setWordList([]); - })); - this.mockHandler.stubs().addDictionaryWord(ANYTHING); - this.mockHandler.stubs().removeDictionaryWord(ANYTHING); - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/570556 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - '#language-dictionary-overlay-word-list > .deletable-item > *'); - - var unsupportedAriaAttributeSelectors = [ - '#language-dictionary-overlay-word-list', - '#language-options-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/570559 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - unsupportedAriaAttributeSelectors); - }, -}; - -// Verify that users can add and remove words in the dictionary. -TEST_F('EditDictionaryWebUITest', 'testAddRemoveWords', function() { - var testWord = 'foo'; - $('language-dictionary-overlay-word-list').querySelector('input').value = - testWord; - - this.mockHandler.expects(once()).addDictionaryWord([testWord]). - will(callFunction(function() { - EditDictionaryOverlay.setWordList([testWord]); - })); - var addWordItem = EditDictionaryOverlay.getWordListForTesting().items[0]; - addWordItem.onEditCommitted_({currentTarget: addWordItem}); - - this.mockHandler.expects(once()).removeDictionaryWord([testWord]). - will(callFunction(function() { - EditDictionaryOverlay.setWordList([]); - })); - EditDictionaryOverlay.getWordListForTesting().deleteItemAtIndex(0); -}); - -// Verify that users can search words in the dictionary. -TEST_F('EditDictionaryWebUITest', 'testSearch', function() { - EditDictionaryOverlay.setWordList(['foo', 'bar']); - expectEquals(3, EditDictionaryOverlay.getWordListForTesting().items.length); - - /** - * @param {Element} el The element to dispatch an event on. - * @param {string} value The text of the search event. - */ - var fakeSearchEvent = function(el, value) { - el.value = value; - cr.dispatchSimpleEvent(el, 'search'); - }; - var searchField = $('language-dictionary-overlay-search-field'); - fakeSearchEvent(searchField, 'foo'); - expectEquals(2, EditDictionaryOverlay.getWordListForTesting().items.length); - - fakeSearchEvent(searchField, ''); - expectEquals(3, EditDictionaryOverlay.getWordListForTesting().items.length); -}); - -TEST_F('EditDictionaryWebUITest', 'testNoCloseOnSearchEnter', function() { - var editDictionaryPage = EditDictionaryOverlay.getInstance(); - assertTrue(editDictionaryPage.visible); - var searchField = $('language-dictionary-overlay-search-field'); - searchField.dispatchEvent(new KeyboardEvent('keydown', { - 'bubbles': true, - 'cancelable': true, - 'key': 'Enter' - })); - assertTrue(editDictionaryPage.visible); -}); - -// Verify that dictionary shows newly added words that arrived in a -// notification, but ignores duplicate add notifications. -TEST_F('EditDictionaryWebUITest', 'testAddNotification', function() { - // Begin with an empty dictionary. - EditDictionaryOverlay.setWordList([]); - expectEquals(1, EditDictionaryOverlay.getWordListForTesting().items.length); - - // User adds word 'foo'. - EditDictionaryOverlay.getWordListForTesting().addDictionaryWord_('foo'); - expectEquals(2, EditDictionaryOverlay.getWordListForTesting().items.length); - - // Backend notifies UI that the word 'foo' has been added. UI ignores this - // notification, because the word is displayed immediately after user added - // it. - EditDictionaryOverlay.updateWords(['foo'], []); - expectEquals(2, EditDictionaryOverlay.getWordListForTesting().items.length); - - // Backend notifies UI that the words 'bar' and 'baz' were added. UI shows - // these new words. - EditDictionaryOverlay.updateWords(['bar', 'baz'], []); - expectEquals(4, EditDictionaryOverlay.getWordListForTesting().items.length); -}); - -// Verify that dictionary hides newly removed words that arrived in a -// notification, but ignores duplicate remove notifications. -// TODO(crbug.com/631940): Flaky on Win 7. -GEN('#if defined(OS_WIN)'); -GEN('#define MAYBE_testRemoveNotification DISABLED_testRemoveNotification'); -GEN('#else'); -GEN('#define MAYBE_testRemoveNotification testRemoveNotification'); -GEN('#endif // defined(OS_WIN)'); -TEST_F('EditDictionaryWebUITest', 'MAYBE_testRemoveNotification', function() { - // Begin with a dictionary with words 'foo', 'bar', 'baz', and 'baz'. The - // second instance of 'baz' appears because the user added the word twice. - // The backend keeps only one copy of the word. - EditDictionaryOverlay.setWordList(['foo', 'bar', 'baz', 'baz']); - expectEquals(5, EditDictionaryOverlay.getWordListForTesting().items.length); - - // User deletes the second instance of 'baz'. - EditDictionaryOverlay.getWordListForTesting().deleteItemAtIndex(3); - expectEquals(4, EditDictionaryOverlay.getWordListForTesting().items.length); - - // Backend notifies UI that the word 'baz' has been removed. UI ignores this - // notification. - EditDictionaryOverlay.updateWords([], ['baz']); - expectEquals(4, EditDictionaryOverlay.getWordListForTesting().items.length); - - // Backend notifies UI that words 'foo' and 'bar' have been removed. UI - // removes these words. - EditDictionaryOverlay.updateWords([], ['foo', 'bar']); - expectEquals(2, EditDictionaryOverlay.getWordListForTesting().items.length); -});
diff --git a/chrome/browser/ui/webui/options/font_settings_browsertest.js b/chrome/browser/ui/webui/options/font_settings_browsertest.js deleted file mode 100644 index 6e419a2..0000000 --- a/chrome/browser/ui/webui/options/font_settings_browsertest.js +++ /dev/null
@@ -1,66 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for font settings WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function FontSettingsWebUITest() {} - -FontSettingsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to the font settings page. - */ - browsePreload: 'chrome://settings-frame/fonts', - - /** @override */ - preLoad: function() { - this.makeAndRegisterMockHandler(['openAdvancedFontSettingsOptions']); - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - var controlsWithoutLabelSelectors = [ - '#standard-font-size', - '#minimum-font-size', - ]; - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/570555 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - controlsWithoutLabelSelectors); - }, -}; - -// Test opening font settings has correct location. -TEST_F('FontSettingsWebUITest', 'testOpenFontSettings', function() { - assertEquals(this.browsePreload, document.location.href); -}); - -// Test setup of the Advanced Font Settings links. -TEST_F('FontSettingsWebUITest', 'testAdvancedFontSettingsLink', function() { - var installElement = $('advanced-font-settings-install'); - var optionsElement = $('advanced-font-settings-options'); - var expectedUrl = 'https://chrome.google.com/webstore/detail/' + - 'caclkomlalccbpcdllchkeecicepbmbm'; - - FontSettings.notifyAdvancedFontSettingsAvailability(false); - assertFalse(installElement.hidden); - assertEquals(expectedUrl, installElement.querySelector('a').href); - assertTrue(optionsElement.hidden); - - FontSettings.notifyAdvancedFontSettingsAvailability(true); - assertTrue(installElement.hidden); - assertFalse(optionsElement.hidden); - this.mockHandler.expects(once()).openAdvancedFontSettingsOptions(); - optionsElement.click(); -});
diff --git a/chrome/browser/ui/webui/options/font_settings_utils_unittest.cc b/chrome/browser/ui/webui/options/font_settings_utils_unittest.cc deleted file mode 100644 index 2c274d1..0000000 --- a/chrome/browser/ui/webui/options/font_settings_utils_unittest.cc +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/options/font_settings_utils.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace options { - -TEST(FontSettingsUtilitiesTest, ResolveFontList) { - EXPECT_TRUE(FontSettingsUtilities::ResolveFontList("").empty()); - - // Returns the first available font if starts with ",". - EXPECT_EQ("Arial", - FontSettingsUtilities::ResolveFontList(",not exist, Arial")); - - // Returns the first font if no fonts are available. - EXPECT_EQ("not exist", - FontSettingsUtilities::ResolveFontList(",not exist, not exist 2")); - - // Otherwise returns any strings as they were set. - std::string non_lists[] = { - "Arial", "not exist", "not exist, Arial", - }; - for (const std::string& name : non_lists) - EXPECT_EQ(name, FontSettingsUtilities::ResolveFontList(name)); -} - -} // namespace options
diff --git a/chrome/browser/ui/webui/options/language_options_browsertest.js b/chrome/browser/ui/webui/options/language_options_browsertest.js deleted file mode 100644 index bfd3acb6..0000000 --- a/chrome/browser/ui/webui/options/language_options_browsertest.js +++ /dev/null
@@ -1,56 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for language options WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function LanguageOptionsWebUITest() {} - -LanguageOptionsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/languages', - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559266 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#language-options-list'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559271 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#languagePage > .content-area > .language-options-header > A'); - } -}; - -// Test opening language options has correct location. -TEST_F('LanguageOptionsWebUITest', 'testOpenLanguageOptions', function() { - assertEquals(this.browsePreload, document.location.href); -}); - -GEN('#if defined(OS_WIN) || defined(OS_CHROMEOS)'); -// Test reselecting the same language as the current UI locale. This should show -// a "Chrome is displayed in this language" message rather than a restart banner -// or a [ Display Chrome in this language ] button. -TEST_F('LanguageOptionsWebUITest', 'reselectUILocale', function() { - var currentLang = loadTimeData.getString('currentUiLanguageCode'); - $('language-options-list').selectLanguageByCode(currentLang); - LanguageOptions.uiLanguageSaved(currentLang); - - expectTrue($('language-options-ui-language-button').hidden); - expectFalse($('language-options-ui-language-message').hidden); - expectTrue($('language-options-ui-notification-bar').hidden); -}); -GEN('#endif'); // defined(OS_WIN) || defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/options/language_options_dictionary_download_browsertest.js b/chrome/browser/ui/webui/options/language_options_dictionary_download_browsertest.js deleted file mode 100644 index 174b323..0000000 --- a/chrome/browser/ui/webui/options/language_options_dictionary_download_browsertest.js +++ /dev/null
@@ -1,129 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for testing messages of dictionary download progress in language - * options WebUI. - * @extends {testing.Test} - * @constructor - */ -function LanguagesOptionsDictionaryDownloadWebUITest() {} - -LanguagesOptionsDictionaryDownloadWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to languages options. - */ - browsePreload: 'chrome://settings-frame/languages', - - /** - * Register a mock dictionary handler. - */ - preLoad: function() { - this.makeAndRegisterMockHandler(['retryDictionaryDownload']); - this.mockHandler.stubs().retryDictionaryDownload(). - will(callFunction(function() { - options.LanguageOptions.onDictionaryDownloadBegin('en-US'); - })); - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/570554 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#language-options-list'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/570553 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#languagePage > .content-area > .language-options-header > A'); - }, -}; - -// Verify that dictionary download success does not show, "This language can't -// be used for spellchecking." or "Download failed." -// Disabled due to flakiness (crbug.com/616550). -TEST_F('LanguagesOptionsDictionaryDownloadWebUITest', - 'DISABLED_testdictionaryDownloadSuccess', - function() { - options.LanguageOptions.onDictionaryDownloadSuccess('en-US'); - expectTrue($('spellcheck-language-message').hidden); - expectTrue($('language-options-dictionary-downloading-message').hidden); - expectTrue($('language-options-dictionary-download-failed-message').hidden); - expectTrue( - $('language-options-dictionary-download-fail-help-message').hidden); -}); - -// Verify that dictionary download in progress shows 'Downloading spell check -// language' message. -// Disabled due to flakiness (crbug.com/616550). -TEST_F('LanguagesOptionsDictionaryDownloadWebUITest', - 'DISABLED_testdictionaryDownloadProgress', - function() { - options.LanguageOptions.onDictionaryDownloadBegin('en-US'); - expectTrue($('spellcheck-language-message').hidden); - expectFalse($('language-options-dictionary-downloading-message').hidden); - expectTrue($('language-options-dictionary-download-failed-message').hidden); - expectTrue( - $('language-options-dictionary-download-fail-help-message').hidden); -}); - -// Verify that failure in dictionary download shows 'Dictionary download failed' -// message. -TEST_F('LanguagesOptionsDictionaryDownloadWebUITest', - 'testdictionaryDownloadFailed', - function() { - // Clear the failure counter: - options.LanguageOptions.onDictionaryDownloadSuccess('en-US'); - - // First failure shows a short error message. - options.LanguageOptions.onDictionaryDownloadFailure('en-US'); - expectTrue($('spellcheck-language-message').hidden); - expectTrue($('language-options-dictionary-downloading-message').hidden); - expectFalse($('language-options-dictionary-download-failed-message').hidden); - expectTrue( - $('language-options-dictionary-download-fail-help-message').hidden); - - // Second and all following failures show a longer error message. - options.LanguageOptions.onDictionaryDownloadFailure('en-US'); - expectTrue($('spellcheck-language-message').hidden); - expectTrue($('language-options-dictionary-downloading-message').hidden); - expectFalse($('language-options-dictionary-download-failed-message').hidden); - expectFalse( - $('language-options-dictionary-download-fail-help-message').hidden); - - options.LanguageOptions.onDictionaryDownloadFailure('en-US'); - expectTrue($('spellcheck-language-message').hidden); - expectTrue($('language-options-dictionary-downloading-message').hidden); - expectFalse($('language-options-dictionary-download-failed-message').hidden); - expectFalse( - $('language-options-dictionary-download-fail-help-message').hidden); -}); - -// Verify that clicking the retry button calls the handler. -// This test is flaky on Windows. https://crbug.com/616791 -GEN('#if defined(OS_WIN)'); -GEN('#define MAYBE_testdictionaryDownloadRetry ' + - 'DISABLED_testdictionaryDownloadRetry'); -GEN('#else'); -GEN('#define MAYBE_testdictionaryDownloadRetry testdictionaryDownloadRetry'); -GEN('#endif // defined(OS_WIN)'); -TEST_F('LanguagesOptionsDictionaryDownloadWebUITest', - 'MAYBE_testdictionaryDownloadRetry', - function() { - this.mockHandler.expects(once()).retryDictionaryDownload('en-US'). - will(callFunction(function() { - options.LanguageOptions.onDictionaryDownloadBegin('en-US'); - })); - options.LanguageOptions.onDictionaryDownloadFailure('en-US'); - $('dictionary-download-retry-button').click(); -});
diff --git a/chrome/browser/ui/webui/options/language_options_handler_unittest.cc b/chrome/browser/ui/webui/options/language_options_handler_unittest.cc deleted file mode 100644 index e290a98..0000000 --- a/chrome/browser/ui/webui/options/language_options_handler_unittest.cc +++ /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. - -#include "chrome/browser/ui/webui/options/language_options_handler.h" - -#include <string> - -#include "base/values.h" -#include "build/build_config.h" -#include "testing/gtest/include/gtest/gtest.h" - -#if !defined(OS_MACOSX) -TEST(LanguageOptionsHandlerTest, GetUILanguageCodeSet) { - std::unique_ptr<base::DictionaryValue> dictionary( - options::LanguageOptionsHandler::GetUILanguageCodeSet()); - EXPECT_TRUE(dictionary->HasKey("en-US")); - // Note that we don't test a false case, as such an expectation will - // fail when we add support for the language. - // EXPECT_FALSE(dictionary->HasKey("no")); -} -#endif // !defined(OS_MACOSX) - -TEST(LanguageOptionsHandlerTest, GetSpellCheckLanguageCodeSet) { - std::unique_ptr<base::DictionaryValue> dictionary( - options::LanguageOptionsHandler::GetSpellCheckLanguageCodeSet()); - EXPECT_TRUE(dictionary->HasKey("en-US")); -}
diff --git a/chrome/browser/ui/webui/options/manage_profile_browsertest.js b/chrome/browser/ui/webui/options/manage_profile_browsertest.js deleted file mode 100644 index d4144e0..0000000 --- a/chrome/browser/ui/webui/options/manage_profile_browsertest.js +++ /dev/null
@@ -1,672 +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. - -// None of these tests is relevant for Chrome OS. -GEN('#if !defined(OS_CHROMEOS)'); - -/** - * TestFixture for ManageProfileOverlay and CreateProfileOverlay WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function ManageProfileUITest() {} - -ManageProfileUITest.prototype = { - __proto__: testing.Test.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/manageProfile', - - /** - * No need to run these for every OptionsPage test, since they'll cover the - * whole consolidated page each time. - * @override - */ - runAccessibilityChecks: false, - - /** - * Some default profile infos. - */ - defaultIconURLs: [], - defaultNames: [], - - /** - * Returns a test profile-info object with configurable "supervised" status. - * @param {boolean} supervised If true, the test profile will be marked as - * supervised. - * @return {Object} A test profile-info object. - */ - testProfileInfo_: function(supervised) { - return { - name: 'Test Profile', - iconURL: 'chrome://path/to/icon/image', - filePath: '/path/to/profile/data/on/disk', - isCurrentProfile: true, - isSupervised: supervised - }; - }, - - /** - * Overrides WebUI methods that provide profile info, making them return a - * test profile-info object. - * @param {boolean} supervised Whether the test profile should be marked - * as supervised. - * @param {string} mode The mode of the overlay (either 'manage' or 'create'). - */ - setProfileSupervised_: function(supervised, mode) { - // Override the BrowserOptions method to return the fake info. - BrowserOptions.getCurrentProfile = function() { - return this.testProfileInfo_(supervised); - }.bind(this); - // Set the profile info in the overlay. - ManageProfileOverlay.setProfileInfo(this.testProfileInfo_(supervised), - mode); - }, - - /** - * Set some default profile infos (icon URLs and names). - * @param {boolean} supervised Whether the test profile should be marked as - * supervised. - * @param {string} mode The mode of the overlay (either 'manage' or 'create'). - */ - initDefaultProfiles_: function(mode) { - PageManager.showPageByName(mode + 'Profile'); - - var defaultProfile = { - name: 'Default Name', - iconURL: '/default/path', - }; - this.defaultIconURLs = ['/some/path', - defaultProfile.iconURL, - '/another/path', - '/one/more/path']; - this.defaultNames = ['Some Name', defaultProfile.name, '', 'Another Name']; - ManageProfileOverlay.receiveDefaultProfileIconsAndNames( - mode, this.defaultIconURLs, this.defaultNames); - ManageProfileOverlay.receiveNewProfileDefaults(defaultProfile); - - // Make sure the correct item in the icon grid was selected. - var gridEl = $(mode + '-profile-icon-grid'); - expectEquals(defaultProfile.iconURL, gridEl.selectedItem); - }, -}; - -// Receiving the new profile defaults in the manage-user overlay shouldn't mess -// up the focus in a visible higher-level overlay. -TEST_F('ManageProfileUITest', 'NewProfileDefaultsFocus', function() { - var self = this; - - function checkFocus(pageName, expectedFocus, initialFocus) { - PageManager.showPageByName(pageName); - initialFocus.focus(); - expectEquals(initialFocus, document.activeElement, pageName); - - ManageProfileOverlay.receiveNewProfileDefaults( - self.testProfileInfo_(false)); - expectEquals(expectedFocus, document.activeElement, pageName); - PageManager.closeOverlay(); - } - - // Receiving new profile defaults sets focus to the name field if the create - // overlay is open, and should not change focus at all otherwise. - checkFocus('manageProfile', - $('manage-profile-cancel'), - $('manage-profile-cancel')); - checkFocus('createProfile', - $('create-profile-name'), - $('create-profile-cancel')); - checkFocus('supervisedUserLearnMore', - $('supervised-user-learn-more-done'), - $('supervised-user-learn-more-done')); - checkFocus('supervisedUserLearnMore', - document.querySelector('#supervised-user-learn-more-text a'), - document.querySelector('#supervised-user-learn-more-text a')); -}); - -// The default options should be reset each time the creation overlay is shown. -TEST_F('ManageProfileUITest', 'DefaultCreateOptions', function() { - PageManager.showPageByName('createProfile'); - var shortcutsAllowed = loadTimeData.getBoolean('profileShortcutsEnabled'); - var createShortcut = $('create-shortcut'); - var createSupervised = $('create-profile-supervised'); - assertEquals(shortcutsAllowed, createShortcut.checked); - assertFalse(createSupervised.checked); - - createShortcut.checked = !shortcutsAllowed; - createSupervised.checked = true; - PageManager.closeOverlay(); - PageManager.showPageByName('createProfile'); - assertEquals(shortcutsAllowed, createShortcut.checked); - assertFalse(createSupervised.checked); -}); - -// The checkbox label should change depending on whether the user is signed in. -TEST_F('ManageProfileUITest', 'CreateSupervisedUserText', function() { - var signedInText = $('create-profile-supervised-signed-in'); - var notSignedInText = $('create-profile-supervised-not-signed-in'); - - ManageProfileOverlay.getInstance().initializePage(); - - var custodianEmail = 'chrome.playpen.test@gmail.com'; - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - assertEquals(custodianEmail, - CreateProfileOverlay.getInstance().signedInEmail_); - assertFalse(signedInText.hidden); - assertTrue(notSignedInText.hidden); - // Make sure the email is in the string somewhere, without depending on the - // exact details of the message. - assertNotEquals(-1, signedInText.textContent.indexOf(custodianEmail)); - - CreateProfileOverlay.updateSignedInStatus(''); - assertEquals('', CreateProfileOverlay.getInstance().signedInEmail_); - assertTrue(signedInText.hidden); - assertFalse(notSignedInText.hidden); - assertFalse($('create-profile-supervised').checked); - assertTrue($('create-profile-supervised').disabled); -}); - -function ManageProfileUITestAsync() {} - -ManageProfileUITestAsync.prototype = { - __proto__: ManageProfileUITest.prototype, - - isAsync: true, -}; - -// The import link should show up if the user tries to create a profile with the -// same name as an existing supervised user profile. -TEST_F('ManageProfileUITestAsync', 'CreateExistingSupervisedUser', function() { - // Initialize the list of existing supervised users. - var supervisedUsers = [ - { - id: 'supervisedUser1', - name: 'Rosalie', - iconURL: 'chrome://path/to/icon/image', - onCurrentDevice: false, - needAvatar: false - }, - { - id: 'supervisedUser2', - name: 'Fritz', - iconURL: 'chrome://path/to/icon/image', - onCurrentDevice: false, - needAvatar: true - }, - { - id: 'supervisedUser3', - name: 'Test', - iconURL: 'chrome://path/to/icon/image', - onCurrentDevice: true, - needAvatar: false - }, - { - id: 'supervisedUser4', - name: 'RepeatingName', - iconURL: 'chrome://path/to/icon/image', - onCurrentDevice: true, - needAvatar: false - }, - { - id: 'supervisedUser5', - name: 'RepeatingName', - iconURL: 'chrome://path/to/icon/image', - onCurrentDevice: false, - needAvatar: false - }]; - var promise = Promise.resolve(supervisedUsers); - options.SupervisedUserListData.getInstance().promise_ = promise; - - // Initialize the ManageProfileOverlay. - ManageProfileOverlay.getInstance().initializePage(); - var custodianEmail = 'chrome.playpen.test@gmail.com'; - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - assertEquals(custodianEmail, - CreateProfileOverlay.getInstance().signedInEmail_); - this.setProfileSupervised_(false, 'create'); - - // Also add the names 'Test' and 'RepeatingName' to |existingProfileNames_| to - // simulate that profiles with those names exist on the device. - ManageProfileOverlay.getInstance().existingProfileNames_.Test = true; - ManageProfileOverlay.getInstance().existingProfileNames_.RepeatingName = true; - - // Initially, the ok button should be enabled and the import link should not - // exist. - assertFalse($('create-profile-ok').disabled); - assertTrue($('supervised-user-import-existing') == null); - - // Now try to create profiles with the names of existing supervised users. - $('create-profile-supervised').checked = true; - var nameField = $('create-profile-name'); - // A profile which already has an avatar. - nameField.value = 'Rosalie'; - ManageProfileOverlay.getInstance().onNameChanged_('create'); - // Need to wait until the promise resolves. - promise.then(function() { - assertTrue($('create-profile-ok').disabled); - assertFalse($('supervised-user-import-existing') == null); - - // A profile which doesn't have an avatar yet. - nameField.value = 'Fritz'; - ManageProfileOverlay.getInstance().onNameChanged_('create'); - return options.SupervisedUserListData.getInstance().promise_; - }).then(function() { - assertTrue($('create-profile-ok').disabled); - assertFalse($('supervised-user-import-existing') == null); - - // A profile which already exists on the device. - nameField.value = 'Test'; - ManageProfileOverlay.getInstance().onNameChanged_('create'); - return options.SupervisedUserListData.getInstance().promise_; - }).then(function() { - assertTrue($('create-profile-ok').disabled); - assertTrue($('supervised-user-import-existing') == null); - - // A supervised user profile that is on the device, but has the same name - // as a supervised user profile that is not imported. - // This can happen due to a bug (https://crbug.com/557445) - nameField.value = 'RepeatingName'; - ManageProfileOverlay.getInstance().onNameChanged_('create'); - return options.SupervisedUserListData.getInstance().promise_; - }).then(function() { - assertTrue($('create-profile-ok').disabled); - assertFalse($('supervised-user-import-existing') == null); - - // A profile which does not exist yet. - nameField.value = 'NewProfileName'; - ManageProfileOverlay.getInstance().onNameChanged_('create'); - return options.SupervisedUserListData.getInstance().promise_; - }).then(function() { - assertFalse($('create-profile-ok').disabled); - assertTrue($('supervised-user-import-existing') == null); - testDone(); - }); -}); - -// Supervised users should not be able to edit their profile names, and the -// initial focus should be adjusted accordingly. -TEST_F('ManageProfileUITest', 'EditSupervisedUserNameAllowed', function() { - var nameField = $('manage-profile-name'); - - this.setProfileSupervised_(false, 'manage'); - ManageProfileOverlay.showManageDialog(); - expectFalse(nameField.disabled); - expectEquals(nameField, document.activeElement); - - PageManager.closeOverlay(); - - this.setProfileSupervised_(true, 'manage'); - ManageProfileOverlay.showManageDialog(); - expectTrue(nameField.disabled); - expectEquals($('manage-profile-ok'), document.activeElement); -}); - -// Setting profile information should allow the confirmation to be shown. -TEST_F('ManageProfileUITest', 'ShowCreateConfirmation', function() { - var testProfile = this.testProfileInfo_(true); - testProfile.custodianEmail = 'foo@bar.example.com'; - SupervisedUserCreateConfirmOverlay.setProfileInfo(testProfile); - assertTrue(SupervisedUserCreateConfirmOverlay.getInstance().canShowPage()); - PageManager.showPageByName('supervisedUserCreateConfirm', false); - assertEquals('supervisedUserCreateConfirm', - PageManager.getTopmostVisiblePage().name); -}); - -// Trying to show a confirmation dialog with no profile information should fall -// back to the default (main) settings page. -TEST_F('ManageProfileUITest', 'NoEmptyConfirmation', function() { - assertEquals('manageProfile', PageManager.getTopmostVisiblePage().name); - assertFalse(SupervisedUserCreateConfirmOverlay.getInstance().canShowPage()); - PageManager.showPageByName('supervisedUserCreateConfirm', true); - assertEquals('settings', PageManager.getTopmostVisiblePage().name); -}); - -// A confirmation dialog should be shown after creating a new supervised user. -TEST_F('ManageProfileUITest', 'ShowCreateConfirmationOnSuccess', function() { - PageManager.showPageByName('createProfile'); - assertEquals('createProfile', PageManager.getTopmostVisiblePage().name); - CreateProfileOverlay.onSuccess(this.testProfileInfo_(false)); - assertEquals('settings', PageManager.getTopmostVisiblePage().name); - - PageManager.showPageByName('createProfile'); - assertEquals('createProfile', PageManager.getTopmostVisiblePage().name); - CreateProfileOverlay.onSuccess(this.testProfileInfo_(true)); - assertEquals('supervisedUserCreateConfirm', - PageManager.getTopmostVisiblePage().name); - expectEquals($('supervised-user-created-switch'), document.activeElement); -}); - -// An error should be shown if creating a new supervised user fails. -TEST_F('ManageProfileUITest', 'NoCreateConfirmationOnError', function() { - PageManager.showPageByName('createProfile'); - assertEquals('createProfile', PageManager.getTopmostVisiblePage().name); - var errorBubble = $('create-profile-error-bubble'); - assertTrue(errorBubble.hidden); - - CreateProfileOverlay.onError('An Error Message!'); - assertEquals('createProfile', PageManager.getTopmostVisiblePage().name); - assertFalse(errorBubble.hidden); -}); - -// The name and email should be inserted into the confirmation dialog. -TEST_F('ManageProfileUITest', 'CreateConfirmationText', function() { - var self = this; - var custodianEmail = 'foo@example.com'; - - // Checks the strings in the confirmation dialog. If |expectedNameText| is - // given, it should be present in the dialog's textContent; otherwise the name - // is expected. If |expectedNameHtml| is given, it should be present in the - // dialog's innerHTML; otherwise the expected text is expected in the HTML - // too. - function checkDialog(name, expectedNameText, expectedNameHtml) { - var expectedText = expectedNameText || name; - var expectedHtml = expectedNameHtml || expectedText; - - // Configure the test profile and show the confirmation dialog. - var testProfile = self.testProfileInfo_(true); - testProfile.name = name; - CreateProfileOverlay.onSuccess(testProfile); - assertEquals('supervisedUserCreateConfirm', - PageManager.getTopmostVisiblePage().name); - - // Check for the presence of the name and email in the UI, without depending - // on the details of the messages. - assertNotEquals(-1, - $('supervised-user-created-title').textContent.indexOf(expectedText)); - assertNotEquals(-1, - $('supervised-user-created-switch').textContent.indexOf(expectedText)); - var message = $('supervised-user-created-text'); - assertNotEquals(-1, message.textContent.indexOf(expectedText)); - assertNotEquals(-1, message.textContent.indexOf(custodianEmail)); - - // The name should be properly HTML-escaped. - assertNotEquals(-1, message.innerHTML.indexOf(expectedHtml)); - - PageManager.closeOverlay(); - assertEquals('settings', PageManager.getTopmostVisiblePage().name, name); - } - - // Show and configure the create-profile dialog. - PageManager.showPageByName('createProfile'); - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - assertEquals('createProfile', PageManager.getTopmostVisiblePage().name); - - checkDialog('OneWord'); - checkDialog('Multiple Words'); - checkDialog('It\'s "<HTML> injection" & more!', - 'It\'s "<HTML> injection" & more!', - // The innerHTML getter doesn't escape quotation marks, - // independent of whether they were escaped in the setter. - 'It\'s "<HTML> injection" & more!'); - - // Test elision. MAX_LENGTH = 50, minus 1 for the ellipsis. - var name49Characters = '0123456789012345678901234567890123456789012345678'; - var name50Characters = name49Characters + '9'; - var name51Characters = name50Characters + '0'; - var name60Characters = name51Characters + '123456789'; - checkDialog(name49Characters, name49Characters); - checkDialog(name50Characters, name50Characters); - checkDialog(name51Characters, name49Characters + '\u2026'); - checkDialog(name60Characters, name49Characters + '\u2026'); - - // Test both elision and HTML escaping. The allowed string length is the - // visible length, not the length including the entity names. - name49Characters = name49Characters.replace('0', '&').replace('1', '>'); - name60Characters = name60Characters.replace('0', '&').replace('1', '>'); - var escaped = name49Characters.replace('&', '&').replace('>', '>'); - checkDialog( - name60Characters, name49Characters + '\u2026', escaped + '\u2026'); -}); - -// The confirmation dialog should close if the new supervised user is deleted. -TEST_F('ManageProfileUITest', 'CloseConfirmationOnDelete', function() { - // Configure the test profile and show the confirmation dialog. - var testProfile = this.testProfileInfo_(true); - CreateProfileOverlay.onSuccess(testProfile); - assertEquals('supervisedUserCreateConfirm', - PageManager.getTopmostVisiblePage().name); - - SupervisedUserCreateConfirmOverlay.onDeletedProfile(testProfile.filePath); - assertEquals('settings', PageManager.getTopmostVisiblePage().name, name); -}); - -// The confirmation dialog should update if the new supervised user's name is -// changed. -TEST_F('ManageProfileUITest', 'UpdateConfirmationOnRename', function() { - // Configure the test profile and show the confirmation dialog. - var testProfile = this.testProfileInfo_(true); - CreateProfileOverlay.onSuccess(testProfile); - assertEquals('supervisedUserCreateConfirm', - PageManager.getTopmostVisiblePage().name); - - var oldName = testProfile.name; - var newName = 'New Name'; - SupervisedUserCreateConfirmOverlay.onUpdatedProfileName(testProfile.filePath, - newName); - assertEquals('supervisedUserCreateConfirm', - PageManager.getTopmostVisiblePage().name); - - var titleElement = $('supervised-user-created-title'); - var switchElement = $('supervised-user-created-switch'); - var messageElement = $('supervised-user-created-text'); - - assertEquals(-1, titleElement.textContent.indexOf(oldName)); - assertEquals(-1, switchElement.textContent.indexOf(oldName)); - assertEquals(-1, messageElement.textContent.indexOf(oldName)); - - assertNotEquals(-1, titleElement.textContent.indexOf(newName)); - assertNotEquals(-1, switchElement.textContent.indexOf(newName)); - assertNotEquals(-1, messageElement.textContent.indexOf(newName)); -}); - -// An additional warning should be shown when deleting a supervised user. -TEST_F('ManageProfileUITest', 'DeleteSupervisedUserWarning', function() { - var addendum = $('delete-supervised-profile-addendum'); - - ManageProfileOverlay.showDeleteDialog(this.testProfileInfo_(true)); - assertFalse(addendum.hidden); - - ManageProfileOverlay.showDeleteDialog(this.testProfileInfo_(false)); - assertTrue(addendum.hidden); -}); - -// The policy prohibiting supervised users should update the UI dynamically. -TEST_F('ManageProfileUITest', 'PolicyDynamicRefresh', function() { - ManageProfileOverlay.getInstance().initializePage(); - - var custodianEmail = 'chrome.playpen.test@gmail.com'; - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - CreateProfileOverlay.updateSupervisedUsersAllowed(true); - var checkbox = $('create-profile-supervised'); - var signInPromo = $('create-profile-supervised-not-signed-in'); - var signInLink = $('create-profile-supervised-sign-in-link'); - var indicator = $('create-profile-supervised-indicator'); - - assertFalse(checkbox.disabled, 'allowed and signed in'); - assertTrue(signInPromo.hidden, 'allowed and signed in'); - assertEquals('none', window.getComputedStyle(indicator, null).display, - 'allowed and signed in'); - - CreateProfileOverlay.updateSignedInStatus(''); - CreateProfileOverlay.updateSupervisedUsersAllowed(true); - assertTrue(checkbox.disabled, 'allowed, not signed in'); - assertFalse(signInPromo.hidden, 'allowed, not signed in'); - assertTrue(signInLink.enabled, 'allowed, not signed in'); - assertEquals('none', window.getComputedStyle(indicator, null).display, - 'allowed, not signed in'); - - CreateProfileOverlay.updateSignedInStatus(''); - CreateProfileOverlay.updateSupervisedUsersAllowed(false); - assertTrue(checkbox.disabled, 'disallowed, not signed in'); - assertFalse(signInPromo.hidden, 'disallowed, not signed in'); - assertFalse(signInLink.enabled, 'disallowed, not signed in'); - assertEquals('inline-block', window.getComputedStyle(indicator, null).display, - 'disallowed, not signed in'); - assertEquals('policy', indicator.getAttribute('controlled-by')); - - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - CreateProfileOverlay.updateSupervisedUsersAllowed(false); - assertTrue(checkbox.disabled, 'disallowed, signed in'); - assertTrue(signInPromo.hidden, 'disallowed, signed in'); - assertEquals('inline-block', window.getComputedStyle(indicator, null).display, - 'disallowed, signed in'); - assertEquals('policy', indicator.getAttribute('controlled-by')); - - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - CreateProfileOverlay.updateSupervisedUsersAllowed(true); - assertFalse(checkbox.disabled, 're-allowed and signed in'); - assertTrue(signInPromo.hidden, 're-allowed and signed in'); - assertEquals('none', window.getComputedStyle(indicator, null).display, - 're-allowed and signed in'); -}); - -// The supervised user checkbox should correctly update its state during profile -// creation and afterwards. -TEST_F('ManageProfileUITest', 'CreateInProgress', function() { - ManageProfileOverlay.getInstance().initializePage(); - - var custodianEmail = 'chrome.playpen.test@gmail.com'; - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - CreateProfileOverlay.updateSupervisedUsersAllowed(true); - var checkbox = $('create-profile-supervised'); - var signInPromo = $('create-profile-supervised-not-signed-in'); - var indicator = $('create-profile-supervised-indicator'); - - assertFalse(checkbox.disabled, 'allowed and signed in'); - assertTrue(signInPromo.hidden, 'allowed and signed in'); - assertEquals('none', window.getComputedStyle(indicator, null).display, - 'allowed and signed in'); - assertFalse(indicator.hasAttribute('controlled-by')); - - CreateProfileOverlay.updateCreateInProgress(true); - assertTrue(checkbox.disabled, 'creation in progress'); - - // A no-op update to the sign-in status should not change the UI. - CreateProfileOverlay.updateSignedInStatus(custodianEmail); - CreateProfileOverlay.updateSupervisedUsersAllowed(true); - assertTrue(checkbox.disabled, 'creation in progress'); - - CreateProfileOverlay.updateCreateInProgress(false); - assertFalse(checkbox.disabled, 'creation finished'); -}); - -// Supervised users should be able to open the delete dialog, but not the -// create dialog. -TEST_F('ManageProfileUITest', 'SupervisedShowCreate', function() { - this.setProfileSupervised_(false, 'create'); - - ManageProfileOverlay.showCreateDialog(); - assertEquals('createProfile', PageManager.getTopmostVisiblePage().name); - PageManager.closeOverlay(); - assertEquals('settings', PageManager.getTopmostVisiblePage().name); - ManageProfileOverlay.showDeleteDialog(this.testProfileInfo_(false)); - assertEquals('manageProfile', PageManager.getTopmostVisiblePage().name); - assertFalse($('manage-profile-overlay-delete').hidden); - PageManager.closeOverlay(); - assertEquals('settings', PageManager.getTopmostVisiblePage().name); - - this.setProfileSupervised_(true, 'create'); - ManageProfileOverlay.showCreateDialog(); - assertEquals('settings', PageManager.getTopmostVisiblePage().name); - ManageProfileOverlay.showDeleteDialog(this.testProfileInfo_(false)); - assertEquals('manageProfile', PageManager.getTopmostVisiblePage().name); -}); - -// Selecting a different avatar image should update the suggested profile name. -TEST_F('ManageProfileUITest', 'Create_NameUpdateOnAvatarSelected', function() { - var mode = 'create'; - this.initDefaultProfiles_(mode); - - var gridEl = $(mode + '-profile-icon-grid'); - var nameEl = $(mode + '-profile-name'); - - // Select another icon and check that the profile name was updated. - assertNotEquals(gridEl.selectedItem, this.defaultIconURLs[0]); - gridEl.selectedItem = this.defaultIconURLs[0]; - expectEquals(this.defaultNames[0], nameEl.value); - - // Select icon without an associated name; the profile name shouldn't change. - var oldName = nameEl.value; - assertEquals('', this.defaultNames[2]); - gridEl.selectedItem = this.defaultIconURLs[2]; - expectEquals(oldName, nameEl.value); - - // Select another icon with a name and check that the name is updated again. - assertNotEquals('', this.defaultNames[1]); - gridEl.selectedItem = this.defaultIconURLs[1]; - expectEquals(this.defaultNames[1], nameEl.value); - - PageManager.closeOverlay(); -}); - -// After the user edited the profile name, selecting a different avatar image -// should not update the suggested name anymore. -TEST_F('ManageProfileUITest', 'Create_NoNameUpdateOnAvatarSelectedAfterEdit', - function() { - var mode = 'create'; - this.initDefaultProfiles_(mode); - - var gridEl = $(mode + '-profile-icon-grid'); - var nameEl = $(mode + '-profile-name'); - - // After the user manually entered a name, it should not be changed anymore - // (even if the entered name is another default name). - nameEl.value = this.defaultNames[3]; - nameEl.oninput(); - gridEl.selectedItem = this.defaultIconURLs[0]; - expectEquals(this.defaultNames[3], nameEl.value); - - PageManager.closeOverlay(); -}); - -// After the user edited the profile name, selecting a different avatar image -// should not update the suggested name anymore even if the original suggestion -// is entered again. -TEST_F('ManageProfileUITest', 'Create_NoNameUpdateOnAvatarSelectedAfterRevert', - function() { - var mode = 'create'; - this.initDefaultProfiles_(mode); - - var gridEl = $(mode + '-profile-icon-grid'); - var nameEl = $(mode + '-profile-name'); - - // After the user manually entered a name, it should not be changed anymore, - // even if the user then reverts to the original suggestion. - var oldName = nameEl.value; - nameEl.value = 'Custom Name'; - nameEl.oninput(); - nameEl.value = oldName; - nameEl.oninput(); - // Now select another avatar and check that the name remained the same. - assertNotEquals(gridEl.selectedItem, this.defaultIconURLs[0]); - gridEl.selectedItem = this.defaultIconURLs[0]; - expectEquals(oldName, nameEl.value); - - PageManager.closeOverlay(); -}); - -// In the manage dialog, the name should never be updated on avatar selection. -TEST_F('ManageProfileUITest', 'Manage_NoNameUpdateOnAvatarSelected', - function() { - var mode = 'manage'; - this.setProfileSupervised_(false, mode); - PageManager.showPageByName(mode + 'Profile'); - - var testProfile = this.testProfileInfo_(false); - var iconURLs = [testProfile.iconURL, '/some/path', '/another/path']; - var names = [testProfile.name, 'Some Name', '']; - ManageProfileOverlay.receiveDefaultProfileIconsAndNames( - mode, iconURLs, names); - - var gridEl = $(mode + '-profile-icon-grid'); - var nameEl = $(mode + '-profile-name'); - - // Select another icon and check if the profile name was updated. - var oldName = nameEl.value; - gridEl.selectedItem = iconURLs[1]; - expectEquals(oldName, nameEl.value); - - PageManager.closeOverlay(); -}); - -GEN('#endif // OS_CHROMEOS');
diff --git a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.cc b/chrome/browser/ui/webui/options/multilanguage_options_browsertest.cc deleted file mode 100644 index 4c95d59f..0000000 --- a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.cc +++ /dev/null
@@ -1,48 +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/ui/webui/options/multilanguage_options_browsertest.h" - -#include <string> - -#include "base/command_line.h" -#include "build/build_config.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_service.h" -#include "components/spellcheck/browser/pref_names.h" - -MultilanguageOptionsBrowserTest::MultilanguageOptionsBrowserTest() { -} - -MultilanguageOptionsBrowserTest::~MultilanguageOptionsBrowserTest() { -} - -void MultilanguageOptionsBrowserTest::ClearSpellcheckDictionaries() { - SetDictionariesPref(base::ListValue()); -} - -void MultilanguageOptionsBrowserTest::SetUpOnMainThread() { - WebUIBrowserTest::SetUpOnMainThread(); -#if defined(OS_CHROMEOS) - std::string setting_name = prefs::kLanguagePreferredLanguages; -#else - std::string setting_name = prefs::kAcceptLanguages; -#endif - - PrefService* pref_service = browser()->profile()->GetPrefs(); - pref_service->SetString(setting_name, "fr,es,de,en"); - base::ListValue dictionaries; - dictionaries.AppendString("fr"); - SetDictionariesPref(dictionaries); - pref_service->SetString(spellcheck::prefs::kSpellCheckDictionary, - std::string()); -} - -void MultilanguageOptionsBrowserTest::SetDictionariesPref( - const base::ListValue& value) { - browser()->profile()->GetPrefs()->Set( - spellcheck::prefs::kSpellCheckDictionaries, value); -}
diff --git a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.h b/chrome/browser/ui/webui/options/multilanguage_options_browsertest.h deleted file mode 100644 index 2ea4c66e..0000000 --- a/chrome/browser/ui/webui/options/multilanguage_options_browsertest.h +++ /dev/null
@@ -1,29 +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_UI_WEBUI_OPTIONS_MULTILANGUAGE_OPTIONS_BROWSERTEST_H_ -#define CHROME_BROWSER_UI_WEBUI_OPTIONS_MULTILANGUAGE_OPTIONS_BROWSERTEST_H_ - -#include "base/macros.h" -#include "chrome/test/base/web_ui_browser_test.h" - -// This is a helper class used by multilanguage_options_webui_browsertest.js -// to flip the enable-multilingual-spellchecker command line switch and set -// the AcceptLanguages and SpellcheckDictionaries preferences. -class MultilanguageOptionsBrowserTest : public WebUIBrowserTest { - public: - MultilanguageOptionsBrowserTest(); - ~MultilanguageOptionsBrowserTest() override; - // Set the kSpellCheckDictionaries preference to an empty list value. - void ClearSpellcheckDictionaries(); - - private: - // WebUIBrowserTest implementation. - void SetUpOnMainThread() override; - void SetDictionariesPref(const base::ListValue& value); - - DISALLOW_COPY_AND_ASSIGN(MultilanguageOptionsBrowserTest); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_MULTILANGUAGE_OPTIONS_BROWSERTEST_H_
diff --git a/chrome/browser/ui/webui/options/multilanguage_options_webui_browsertest.js b/chrome/browser/ui/webui/options/multilanguage_options_webui_browsertest.js deleted file mode 100644 index 222016cd4..0000000 --- a/chrome/browser/ui/webui/options/multilanguage_options_webui_browsertest.js +++ /dev/null
@@ -1,212 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); -GEN('#include "chrome/browser/ui/webui/options/' + - 'multilanguage_options_browsertest.h"'); - -/** - * Test C++ fixture for Language Options WebUI testing. - * @constructor - * @extends {testing.Test} - */ -function MultilanguageOptionsWebUIBrowserTest() {} - -MultilanguageOptionsWebUIBrowserTest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/languages', - - /** @override */ - typedefCppFixture: 'MultilanguageOptionsBrowserTest', - - /** @override */ - accessibilityIssuesAreErrors: true, - - /** @param {string} expected Sorted currently selected languages. */ - expectCurrentlySelected: function(expected) { - var languages = LanguageOptions.getInstance().spellCheckLanguages_; - expectEquals(expected, Object.keys(languages).sort().join()); - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - assertFalse(cr.isMac); - expectFalse($('edit-custom-dictionary-button').hidden); - this.expectEnableSpellcheckCheckboxVisible(); - this.expectCurrentlySelected('fr'); - - var requiredOwnedAriaRoleMissingSelectors = [ - '#default-search-engine-list', - '#other-search-engine-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/559320 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559266 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#language-options-list'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559271 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#languagePage > .content-area > .language-options-header > A'); - }, - - /** @override */ - tearDown: function() { - testing.Test.prototype.tearDown.call(this); - this.expectEnableSpellcheckCheckboxVisible(); - }, - - /** Make sure the 'Enable spell checking' checkbox is visible. */ - expectEnableSpellcheckCheckboxVisible: function() { - if ($('enable-spellcheck-container')) - expectFalse($('enable-spellcheck-container').hidden); - }, -}; - -// Test that opening language options has the correct location. -TEST_F('MultilanguageOptionsWebUIBrowserTest', 'TestOpenLanguageOptions', - function() { - expectEquals('chrome://settings-frame/languages', document.location.href); -}); - -// Test that only certain languages can be selected and used for spellchecking. -// prefs::kLanguagePreferredLanguages/prefs::kAcceptLanguages is set to -// 'fr,es,de,en' and prefs::kSpellCheckDictionaries is just 'fr' -TEST_F('MultilanguageOptionsWebUIBrowserTest', 'ChangeSpellcheckLanguages', - function() { - expectTrue($('language-options-list').selectLanguageByCode('es')); - expectFalse($('spellcheck-language-checkbox').checked, 'es'); - - // Click 'es' and ensure that it gets checked and 'fr' stays checked. - $('spellcheck-language-checkbox').click(); - expectTrue($('spellcheck-language-checkbox').checked, 'es'); - expectTrue($('language-options-list').selectLanguageByCode('fr')); - expectTrue($('spellcheck-language-checkbox').checked, 'fr'); - this.expectCurrentlySelected('es,fr'); - - // Click 'fr' and ensure that it gets unchecked and 'es' stays checked. - $('spellcheck-language-checkbox').click(); - expectFalse($('spellcheck-language-checkbox').checked, 'fr'); - $('language-options-list').selectLanguageByCode('es'); - expectTrue($('spellcheck-language-checkbox').checked, 'es'); - this.expectCurrentlySelected('es'); -}); - -// Make sure 'am' cannot be selected as a language and 'fr' stays selected. -TEST_F('MultilanguageOptionsWebUIBrowserTest', 'NotAcceptLanguage', function() { - expectFalse($('language-options-list').selectLanguageByCode('am')); - expectTrue($('language-options-list').selectLanguageByCode('fr')); - expectTrue($('spellcheck-language-checkbox').checked, 'fr'); - this.expectCurrentlySelected('fr'); -}); - -// Make sure 'en' cannot be used as a language and 'fr' stays selected. -TEST_F('MultilanguageOptionsWebUIBrowserTest', 'UnusableLanguage', function() { - expectTrue($('language-options-list').selectLanguageByCode('en')); - expectTrue($('spellcheck-language-checkbox-container').hidden); - expectFalse($('spellcheck-language-checkbox').checked, 'en'); - this.expectCurrentlySelected('fr'); -}); - -/** - * Test C++ fixture for Language Options WebUI testing. - * @constructor - * @extends {MultilanguageOptionsWebUIBrowserTest} - */ -function MultilanguagePreferenceWebUIBrowserTest() {} - -MultilanguagePreferenceWebUIBrowserTest.prototype = { - __proto__: MultilanguageOptionsWebUIBrowserTest.prototype, - - /** @override */ - testGenPreamble: function() { - GEN('ClearSpellcheckDictionaries();'); - }, - - /** @override */ - isAsync: true, - - /** - * @param {string} expected Sorted languages in the kSpellCheckDictionaries - * preference. - */ - expectRegisteredDictionariesPref: function(expected) { - var registeredPrefs = - options.Preferences.getInstance().registeredPreferences_; - expectEquals(expected, - registeredPrefs['spellcheck.dictionaries'].orig.value.sort().join()); - }, - - /** - * Watch for a change to the preference |pref| and then call |callback|. - * @param {string} pref The preference to listen for a change on. - * @param {function} callback The function to run after a listener event. - */ - addPreferenceListener: function(pref, callback) { - options.Preferences.getInstance().addEventListener(pref, callback); - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - assertFalse(cr.isMac); - expectTrue($('edit-custom-dictionary-button').hidden); - this.expectEnableSpellcheckCheckboxVisible(); - this.expectCurrentlySelected(''); - this.expectRegisteredDictionariesPref(''); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559266 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#language-options-list'); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559271 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#languagePage > .content-area > .language-options-header > A'); - - // Enable when failure is resolved. - // AX_FOCUS_01: http://crbug.com/570046 - this.accessibilityAuditConfig.ignoreSelectors( - 'focusableElementNotVisibleAndNotAriaHidden', - '#offer-to-translate-in-this-language'); - }, -}; - -// Make sure the case where no languages are selected is handled properly. -TEST_F('MultilanguagePreferenceWebUIBrowserTest', 'SelectFromBlank', - function() { - expectTrue($('language-options-list').selectLanguageByCode('fr')); - expectFalse($('spellcheck-language-checkbox').checked, 'fr'); - expectTrue($('edit-custom-dictionary-button').hidden); - - // Add a preference change event listener which ensures that the preference is - // updated correctly and that 'fr' is the only thing in the dictionary object. - this.addPreferenceListener('spellcheck.dictionaries', function() { - expectTrue($('spellcheck-language-checkbox').checked, 'fr'); - this.expectRegisteredDictionariesPref('fr'); - this.expectCurrentlySelected('fr'); - expectFalse($('edit-custom-dictionary-button').hidden); - testDone(); - }.bind(this)); - - // Click 'fr' and trigger the preference listener. - $('spellcheck-language-checkbox').click(); -});
diff --git a/chrome/browser/ui/webui/options/options_browsertest.cc b/chrome/browser/ui/webui/options/options_browsertest.cc deleted file mode 100644 index 6eca2fc2..0000000 --- a/chrome/browser/ui/webui/options/options_browsertest.cc +++ /dev/null
@@ -1,70 +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. - -#include "chrome/browser/ui/webui/options/options_browsertest.h" - -#include "base/bind.h" -#include "base/values.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "components/prefs/pref_service.h" -#include "content/public/browser/navigation_controller.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_ui.h" -#include "url/gurl.h" - -using content::NavigationController; -using content::NavigationEntry; -using content::WebUIMessageHandler; - -OptionsBrowserTest::OptionsBrowserTest() { -} - -OptionsBrowserTest::~OptionsBrowserTest() { -} - -void OptionsBrowserTest::RegisterMessages() { - web_ui()->RegisterMessageCallback( - "optionsTestReportHistory", base::Bind(&OptionsBrowserTest::ReportHistory, - base::Unretained(this))); - - web_ui()->RegisterMessageCallback( - "optionsTestSetPref", base::Bind(&OptionsBrowserTest::HandleSetPref, - base::Unretained(this))); -} - -// Includes the current entry. -void OptionsBrowserTest::ReportHistory(const base::ListValue* list_value) { - const NavigationController& controller = - browser()->tab_strip_model()->GetActiveWebContents()->GetController(); - base::ListValue history; - const int current = controller.GetCurrentEntryIndex(); - for (int i = 0; i <= current; ++i) { - GURL url = controller.GetEntryAtIndex(i)->GetVirtualURL(); - history.AppendString(url.spec()); - } - web_ui()->CallJavascriptFunctionUnsafe( - "OptionsWebUIExtendedTest.verifyHistoryCallback", history); -} - -void OptionsBrowserTest::ClearPref(const char* path) { - browser()->profile()->GetPrefs()->ClearPref(path); -} - -void OptionsBrowserTest::HandleSetPref(const base::ListValue* args) { - ASSERT_EQ(2u, args->GetSize()); - - std::string pref_name; - ASSERT_TRUE(args->GetString(0, &pref_name)); - const base::Value* pref_value; - ASSERT_TRUE(args->Get(1, &pref_value)); - - browser()->profile()->GetPrefs()->Set(pref_name.c_str(), *pref_value); -} - -content::WebUIMessageHandler* OptionsBrowserTest::GetMockMessageHandler() { - return this; -}
diff --git a/chrome/browser/ui/webui/options/options_browsertest.h b/chrome/browser/ui/webui/options/options_browsertest.h deleted file mode 100644 index d8135a8..0000000 --- a/chrome/browser/ui/webui/options/options_browsertest.h +++ /dev/null
@@ -1,45 +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. - -#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_BROWSERTEST_H_ -#define CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_BROWSERTEST_H_ - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "chrome/test/base/web_ui_browser_test.h" -#include "content/public/browser/web_ui_message_handler.h" - -// This is a helper class used by options_browsertest.js to feed the navigation -// history back to the test. -class OptionsBrowserTest : public WebUIBrowserTest, - public content::WebUIMessageHandler { - public: - OptionsBrowserTest(); - ~OptionsBrowserTest() override; - - protected: - // Clears the preference at the given |path|. - void ClearPref(const char* path); - - private: - // WebUIMessageHandler implementation. - void RegisterMessages() override; - - // WebUIBrowserTest implementation. - content::WebUIMessageHandler* GetMockMessageHandler() override; - - // A callback for the 'optionsTestReportHistory' message, this sends the - // URLs in the "back" tab history, including the current entry, back to the - // WebUI via a callback. - void ReportHistory(const base::ListValue* list_value); - - // A callback for the 'optionsTestSetPref' message. The first argument should - // be a pref path (e.g., "profile.managed_users"); the second, the new value - // to set for that pref. - void HandleSetPref(const base::ListValue* args); - - DISALLOW_COPY_AND_ASSIGN(OptionsBrowserTest); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_OPTIONS_BROWSERTEST_H_
diff --git a/chrome/browser/ui/webui/options/options_browsertest.js b/chrome/browser/ui/webui/options/options_browsertest.js deleted file mode 100644 index 05dfd8c96b..0000000 --- a/chrome/browser/ui/webui/options/options_browsertest.js +++ /dev/null
@@ -1,969 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); -GEN('#include "chrome/browser/ui/webui/options/options_browsertest.h"'); - -/** @const */ var SUPERVISED_USERS_PREF = 'profile.managed_users'; - -/** - * Wait for the method specified by |methodName|, on the |object| object, to be - * called, then execute |afterFunction|. - * @param {*} object Object with callable property named |methodName|. - * @param {string} methodName The name of the property on |object| to use as a - * callback. - * @param {!Function} afterFunction A function to call after object.methodName() - * is called. - */ -function waitForResponse(object, methodName, afterFunction) { - var originalCallback = object[methodName]; - - // Install a wrapper that temporarily replaces the original function. - object[methodName] = function() { - object[methodName] = originalCallback; - originalCallback.apply(this, arguments); - afterFunction(); - }; -} - -/** - * Wait for the global window.onpopstate callback to be called (after a tab - * history navigation), then execute |afterFunction|. - * @param {!Function} afterFunction A function to call after pop state events. - */ -function waitForPopstate(afterFunction) { - waitForResponse(window, 'onpopstate', afterFunction); -} - -/** - * TestFixture for OptionsPage WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function OptionsWebUITest() {} - -OptionsWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to the options page & call our preLoad(). - * @override - */ - browsePreload: 'chrome://settings-frame', - - /** @override */ - isAsync: true, - - /** - * Register a mock handler to ensure expectations are met and options pages - * behave correctly. - */ - preLoad: function() { - this.makeAndRegisterMockHandler( - ['defaultZoomFactorAction', - 'fetchPrefs', - 'observePrefs', - 'setBooleanPref', - 'setIntegerPref', - 'setDoublePref', - 'setStringPref', - 'setObjectPref', - 'clearPref', - 'coreOptionsUserMetricsAction', - ]); - - // Register stubs for methods expected to be called before/during tests. - // Specific expectations can be made in the tests themselves. - this.mockHandler.stubs().fetchPrefs(ANYTHING); - this.mockHandler.stubs().observePrefs(ANYTHING); - this.mockHandler.stubs().coreOptionsUserMetricsAction(ANYTHING); - }, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559329 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#profiles-list'); - - var linkWithUnclearPurposeSelectors = [ - '#sync-overview > A', - '#privacy-explanation > A', - '#languages-section > .settings-row > A', - '#cloudprint-options-mdns > .settings-row > A', - '#cups-printers-section > .settings-row > A', - '#do-not-track-confirm-overlay > .action-area > .hbox.stretch > A', - ]; - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559318 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - linkWithUnclearPurposeSelectors); - - // Causes testDefaultZoomFactor to flake. See http://crbug.com/611233. - var requiredOwnedAriaRoleMissingSelectors = [ - '#default-search-engine-list', - '#other-search-engine-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/606657 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - }, -}; - -/** - * Wait for all targets to be hidden. - * @param {Array<Element>} targets - */ -function waitUntilHidden(targets) { - function isHidden(el) { return el.hidden; } - function ensureTransition(el) { ensureTransitionEndEvent(el, 500); } - - document.addEventListener('transitionend', function f(e) { - if (targets.indexOf(e.target) >= 0 && targets.every(isHidden)) { - document.removeEventListener(f, 'transitionend'); - testDone(); - } - }); - - targets.forEach(ensureTransition); -} - -// Crashes on Mac only. See http://crbug.com/79181 -GEN('#if defined(OS_MACOSX)'); -GEN('#define MAYBE_testSetBooleanPrefTriggers ' + - 'DISABLED_testSetBooleanPrefTriggers'); -GEN('#else'); -GEN('#define MAYBE_testSetBooleanPrefTriggers testSetBooleanPrefTriggers'); -GEN('#endif // defined(OS_MACOSX)'); - -TEST_F('OptionsWebUITest', 'MAYBE_testSetBooleanPrefTriggers', function() { - // TODO(dtseng): make generic to click all buttons. - var showHomeButton = - document.querySelector('input[pref="browser.show_home_button"]'); - var trueListValue = [ - 'browser.show_home_button', - true, - 'Options_Homepage_HomeButton', - ]; - // Note: this expectation is checked in testing::Test::tearDown. - this.mockHandler.expects(once()).setBooleanPref(trueListValue); - - // Cause the handler to be called. - showHomeButton.click(); - showHomeButton.blur(); - testDone(); -}); - -// Not meant to run on ChromeOS at this time. -// Not finishing in windows. http://crbug.com/81723 -TEST_F('OptionsWebUITest', 'DISABLED_testRefreshStaysOnCurrentPage', - function() { - assertTrue($('search-engine-manager-page').hidden); - var item = $('manage-default-search-engines'); - item.click(); - - assertFalse($('search-engine-manager-page').hidden); - - window.location.reload(); - - assertEquals('chrome://settings-frame/searchEngines', document.location.href); - assertFalse($('search-engine-manager-page').hidden); - testDone(); -}); - -/** - * Test the default zoom factor select element. - */ -TEST_F('OptionsWebUITest', 'testDefaultZoomFactor', function() { - // The expected minimum length of the |defaultZoomFactor| element. - var defaultZoomFactorMinimumLength = 10; - // Verify that the zoom factor element exists. - var defaultZoomFactor = $('defaultZoomFactor'); - assertNotEquals(defaultZoomFactor, null); - - // Verify that the zoom factor element has a reasonable number of choices. - expectGE(defaultZoomFactor.options.length, defaultZoomFactorMinimumLength); - - // Simulate a change event, selecting the highest zoom value. Verify that - // the javascript handler was invoked once. - this.mockHandler.expects(once()).defaultZoomFactorAction(NOT_NULL). - will(callFunction(function() { })); - defaultZoomFactor.selectedIndex = defaultZoomFactor.options.length - 1; - var event = {target: defaultZoomFactor}; - if (defaultZoomFactor.onchange) defaultZoomFactor.onchange(event); - testDone(); -}); - -/** - * If |confirmInterstitial| is true, the OK button of the Do Not Track - * interstitial is pressed, otherwise the abort button is pressed. - * @param {boolean} confirmInterstitial Whether to confirm the Do Not Track - * interstitial. - */ -OptionsWebUITest.prototype.testDoNotTrackInterstitial = - function(confirmInterstitial) { - Preferences.prefsFetchedCallback({'enable_do_not_track': {'value': false}}); - var buttonToClick = confirmInterstitial ? $('do-not-track-confirm-ok') : - $('do-not-track-confirm-cancel'); - var dntCheckbox = $('do-not-track-enabled'); - var dntOverlay = PageManager.registeredOverlayPages['donottrackconfirm']; - assertFalse(dntCheckbox.checked); - - var visibleChangeCounter = 0; - var visibleChangeHandler = function() { - ++visibleChangeCounter; - switch (visibleChangeCounter) { - case 1: - window.setTimeout(function() { - assertTrue(dntOverlay.visible); - buttonToClick.click(); - }, 0); - break; - case 2: - window.setTimeout(function() { - assertFalse(dntOverlay.visible); - assertEquals(confirmInterstitial, dntCheckbox.checked); - dntOverlay.removeEventListener('visibleChange', visibleChangeHandler); - testDone(); - }, 0); - break; - default: - assertTrue(false); - } - }; - dntOverlay.addEventListener('visibleChange', visibleChangeHandler); - - if (confirmInterstitial) { - this.mockHandler.expects(once()).setBooleanPref( - ['enable_do_not_track', true, 'Options_DoNotTrackCheckbox']); - } else { - // The mock handler complains if setBooleanPref is called even though - // it should not be. - } - - dntCheckbox.click(); -}; - -TEST_F('OptionsWebUITest', 'EnableDoNotTrackAndConfirmInterstitial', - function() { - this.testDoNotTrackInterstitial(true); -}); - -TEST_F('OptionsWebUITest', 'EnableDoNotTrackAndCancelInterstitial', - function() { - this.testDoNotTrackInterstitial(false); -}); - -// Check that the "Do not Track" preference can be correctly disabled. -// In order to do that, we need to enable it first. -TEST_F('OptionsWebUITest', 'EnableAndDisableDoNotTrack', function() { - Preferences.prefsFetchedCallback({'enable_do_not_track': {'value': false}}); - var dntCheckbox = $('do-not-track-enabled'); - var dntOverlay = PageManager.registeredOverlayPages.donottrackconfirm; - assertFalse(dntCheckbox.checked); - - var visibleChangeCounter = 0; - var visibleChangeHandler = function() { - ++visibleChangeCounter; - switch (visibleChangeCounter) { - case 1: - window.setTimeout(function() { - assertTrue(dntOverlay.visible); - $('do-not-track-confirm-ok').click(); - }, 0); - break; - case 2: - window.setTimeout(function() { - assertFalse(dntOverlay.visible); - assertTrue(dntCheckbox.checked); - dntOverlay.removeEventListener('visibleChange', visibleChangeHandler); - dntCheckbox.click(); - }, 0); - break; - default: - assertNotReached(); - } - }; - dntOverlay.addEventListener('visibleChange', visibleChangeHandler); - - this.mockHandler.expects(once()).setBooleanPref( - eq(['enable_do_not_track', true, 'Options_DoNotTrackCheckbox'])); - - var verifyCorrectEndState = function() { - window.setTimeout(function() { - assertFalse(dntOverlay.visible); - assertFalse(dntCheckbox.checked); - testDone(); - }, 0); - }; - this.mockHandler.expects(once()).setBooleanPref( - eq(['enable_do_not_track', false, 'Options_DoNotTrackCheckbox'])).will( - callFunction(verifyCorrectEndState)); - - dntCheckbox.click(); -}); - -// Fails on chromeos, http://crbug.com/660867 -// Verify that preventDefault() is called on 'Enter' keydown events that trigger -// the default button. If this doesn't happen, other elements that may get -// focus (by the overlay closing for instance), will execute in addition to the -// default button. See crbug.com/268336. -TEST_F('OptionsWebUITest', 'DISABLED_EnterPreventsDefault', function() { - var page = HomePageOverlay.getInstance(); - PageManager.showPageByName(page.name); - var event = new KeyboardEvent('keydown', { - 'bubbles': true, - 'cancelable': true, - 'key': 'Enter' - }); - assertFalse(event.defaultPrevented); - page.pageDiv.dispatchEvent(event); - assertTrue(event.defaultPrevented); - testDone(); -}); - -// Verifies that sending an empty list of indexes to move doesn't crash chrome. -TEST_F('OptionsWebUITest', 'emptySelectedIndexesDoesntCrash', function() { - chrome.send('dragDropStartupPage', [0, []]); - setTimeout(testDone); -}); - -// This test turns out to be flaky on all platforms. -// See http://crbug.com/315250. - -// An overlay's position should remain the same as it shows. -TEST_F('OptionsWebUITest', 'DISABLED_OverlayShowDoesntShift', function() { - var overlayName = 'startup'; - var overlay = $('startup-overlay'); - var frozenPages = document.getElementsByClassName('frozen'); // Gets updated. - expectEquals(0, frozenPages.length); - - document.addEventListener('transitionend', function(e) { - if (e.target != overlay) - return; - - assertFalse(overlay.classList.contains('transparent')); - expectEquals(numFrozenPages, frozenPages.length); - testDone(); - }); - - PageManager.showPageByName(overlayName); - var numFrozenPages = frozenPages.length; - expectGT(numFrozenPages, 0); -}); - -GEN('#if defined(OS_CHROMEOS)'); -// Verify that range inputs respond to touch events. Currently only Chrome OS -// uses slider options. -TEST_F('OptionsWebUITest', 'RangeInputHandlesTouchEvents', function() { - this.mockHandler.expects(once()).setIntegerPref([ - 'settings.touchpad.sensitivity2', 1]); - - var touchpadRange = $('touchpad-sensitivity-range'); - var event = document.createEvent('UIEvent'); - event.initUIEvent('touchstart', true, true, window); - touchpadRange.dispatchEvent(event); - - event = document.createEvent('UIEvent'); - event.initUIEvent('touchmove', true, true, window); - touchpadRange.dispatchEvent(event); - - touchpadRange.value = 1; - - event = document.createEvent('UIEvent'); - event.initUIEvent('touchend', true, true, window); - touchpadRange.dispatchEvent(event); - - // touchcancel should also trigger the handler, since it - // changes the slider position. - this.mockHandler.expects(once()).setIntegerPref([ - 'settings.touchpad.sensitivity2', 2]); - - event = document.createEvent('UIEvent'); - event.initUIEvent('touchstart', true, true, window); - touchpadRange.dispatchEvent(event); - - touchpadRange.value = 2; - - event = document.createEvent('UIEvent'); - event.initUIEvent('touchcancel', true, true, window); - touchpadRange.dispatchEvent(event); - - testDone(); -}); -GEN('#endif'); // defined(OS_CHROMEOS) - -/** - * TestFixture for OptionsPage WebUI testing including tab history and support - * for preference manipulation. If you don't need the features in the C++ - * fixture, use the simpler OptionsWebUITest (above) instead. - * @extends {testing.Test} - * @constructor - */ -function OptionsWebUIExtendedTest() {} - -OptionsWebUIExtendedTest.prototype = { - __proto__: OptionsWebUITest.prototype, - - /** @override */ - typedefCppFixture: 'OptionsBrowserTest', - - /** @override */ - setUp: function() { - OptionsWebUITest.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/559329 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#profiles-list'); - - var controlsWithoutLabelSelectors = [ - '#cookies-view-page > .content-area.cookies-list-content-area > *', - '#other-search-engine-list > .deletable-item > DIV > *', - ]; - - // Enable when failure is resolved. - // AX_TEXT_01: http://crbug.com/559330 - this.accessibilityAuditConfig.ignoreSelectors( - 'controlsWithoutLabel', - controlsWithoutLabelSelectors); - - var linkWithUnclearPurposeSelectors = [ - '#sync-overview > A', - '#privacy-explanation > A', - '#languages-section > .settings-row > A', - '#cloudprint-options-mdns > .settings-row > A', - // Selectors below only affect ChromeOS tests. - '#privacy-section > DIV > DIV:nth-of-type(9) > A', - '#accessibility-learn-more', - ]; - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/559326 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - linkWithUnclearPurposeSelectors); - - var requiredOwnedAriaRoleMissingSelectors = [ - '#default-search-engine-list', - '#other-search-engine-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/605689 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - }, - - testGenPreamble: function() { - // Start with no supervised users managed by this profile. - GEN(' ClearPref("' + SUPERVISED_USERS_PREF + '");'); - }, - - /** - * Asserts that two non-nested arrays are equal. The arrays must contain only - * plain data types, no nested arrays or other objects. - * @param {Array} expected An array of expected values. - * @param {Array} result An array of actual values. - * @param {boolean} doSort If true, the arrays will be sorted before being - * compared. - * @param {string} description A brief description for the array of actual - * values, to use in an error message if the arrays differ. - * @private - */ - compareArrays_: function(expected, result, doSort, description) { - var errorMessage = '\n' + description + ': ' + result + - '\nExpected: ' + expected; - assertEquals(expected.length, result.length, errorMessage); - - var expectedSorted = expected.slice(); - var resultSorted = result.slice(); - if (doSort) { - expectedSorted.sort(); - resultSorted.sort(); - } - - for (var i = 0; i < expectedSorted.length; ++i) { - assertEquals(expectedSorted[i], resultSorted[i], errorMessage); - } - }, - - /** - * Verifies that the correct pages are currently open/visible. - * @param {!Array<string>} expectedPages An array of page names expected to - * be open, with the topmost listed last. - * @param {string=} opt_expectedUrl The URL path, including hash, expected to - * be open. If undefined, the topmost (last) page name in |expectedPages| - * will be used. In either case, 'chrome://settings-frame/' will be - * prepended. - * @private - */ - verifyOpenPages_: function(expectedPages, opt_expectedUrl) { - // Check the topmost page. - expectEquals(null, PageManager.getVisibleBubble()); - var currentPage = PageManager.getTopmostVisiblePage(); - - var lastExpected = expectedPages[expectedPages.length - 1]; - expectEquals(lastExpected, currentPage.name); - // We'd like to check the title too, but we have to load the settings-frame - // instead of the outer settings page in order to have access to - // OptionsPage, and setting the title from within the settings-frame fails - // because of cross-origin access restrictions. - // TODO(pamg): Add a test fixture that loads chrome://settings and uses - // UI elements to access sub-pages, so we can test the titles and - // search-page URLs. - var expectedUrl = (typeof opt_expectedUrl == 'undefined') ? - lastExpected : opt_expectedUrl; - var fullExpectedUrl = 'chrome://settings-frame/' + expectedUrl; - expectEquals(fullExpectedUrl, window.location.href); - - // Collect open pages. - var allPageNames = Object.keys(PageManager.registeredPages).concat( - Object.keys(PageManager.registeredOverlayPages)); - var openPages = []; - for (var i = 0; i < allPageNames.length; ++i) { - var name = allPageNames[i]; - var page = PageManager.registeredPages[name] || - PageManager.registeredOverlayPages[name]; - if (page.visible) - openPages.push(page.name); - } - - this.compareArrays_(expectedPages, openPages, true, 'Open pages'); - }, - - /* - * Verifies that the correct URLs are listed in the history. Asynchronous. - * @param {!Array<string>} expectedHistory An array of URL paths expected to - * be in the tab navigation history, sorted by visit time, including the - * current page as the last entry. The base URL (chrome://settings-frame/) - * will be prepended to each. An initial 'about:blank' history entry is - * assumed and should not be included in this list. - * @param {Function=} callback A function to be called after the history has - * been verified successfully. May be undefined. - * @private - */ - verifyHistory_: function(expectedHistory, callback) { - var self = this; - OptionsWebUIExtendedTest.verifyHistoryCallback = function(results) { - // The history always starts with a blank page. - assertEquals('about:blank', results.shift()); - var fullExpectedHistory = []; - for (var i = 0; i < expectedHistory.length; ++i) { - fullExpectedHistory.push( - 'chrome://settings-frame/' + expectedHistory[i]); - } - self.compareArrays_(fullExpectedHistory, results, false, 'History'); - callback(); - }; - - // The C++ fixture will call verifyHistoryCallback with the results. - chrome.send('optionsTestReportHistory'); - }, - - /** - * Overrides the page callbacks for the given PageManager overlay to verify - * that they are not called. - * @param {Object} overlay The singleton instance of the overlay. - * @private - */ - prohibitChangesToOverlay_: function(overlay) { - overlay.initializePage = - overlay.didShowPage = - overlay.didClosePage = function() { - assertTrue(false, - 'Overlay was affected when changes were prohibited.'); - }; - }, -}; - -/** - * Set by verifyHistory_ to incorporate a followup callback, then called by the - * C++ fixture with the navigation history to be verified. - * @type {Function} - */ -OptionsWebUIExtendedTest.verifyHistoryCallback = null; - -// Show the search page with no query string, to fall back to the settings page. -// Test disabled because it's flaky. crbug.com/303841 -TEST_F('OptionsWebUIExtendedTest', 'DISABLED_ShowSearchPageNoQuery', - function() { - PageManager.showPageByName('search'); - this.verifyOpenPages_(['settings']); - this.verifyHistory_(['settings'], testDone); -}); - -// Manipulate the search page via the search field. -TEST_F('OptionsWebUIExtendedTest', 'ShowSearchFromField', function() { - $('search-field').onsearch({currentTarget: {value: 'query'}}); - this.verifyOpenPages_(['settings', 'search'], 'search#query'); - this.verifyHistory_(['', 'search#query'], function() { - $('search-field').onsearch({currentTarget: {value: 'query2'}}); - this.verifyOpenPages_(['settings', 'search'], 'search#query2'); - this.verifyHistory_(['', 'search#query', 'search#query2'], function() { - $('search-field').onsearch({currentTarget: {value: ''}}); - this.verifyOpenPages_(['settings'], ''); - this.verifyHistory_(['', 'search#query', 'search#query2', ''], testDone); - }.bind(this)); - }.bind(this)); -}); - -// Show a page without updating history. -TEST_F('OptionsWebUIExtendedTest', 'ShowPageNoHistory', function() { - this.verifyOpenPages_(['settings'], ''); - PageManager.showPageByName('search', true, {hash: '#query'}); - - // The settings page is also still "open" (i.e., visible), in order to show - // the search results. Furthermore, the URL hasn't been updated in the parent - // page, because we've loaded the chrome-settings frame instead of the whole - // settings page, so the cross-origin call to set the URL fails. - this.verifyOpenPages_(['settings', 'search'], 'search#query'); - var self = this; - this.verifyHistory_(['', 'search#query'], function() { - PageManager.showPageByName('settings', false); - self.verifyOpenPages_(['settings'], 'search#query'); - self.verifyHistory_(['', 'search#query'], testDone); - }); -}); - -TEST_F('OptionsWebUIExtendedTest', 'ShowPageWithHistory', function() { - PageManager.showPageByName('search', true, {hash: '#query'}); - var self = this; - this.verifyHistory_(['', 'search#query'], function() { - PageManager.showPageByName('settings', true); - self.verifyOpenPages_(['settings'], ''); - self.verifyHistory_(['', 'search#query', ''], - testDone); - }); -}); - -TEST_F('OptionsWebUIExtendedTest', 'ShowPageReplaceHistory', function() { - PageManager.showPageByName('search', true, {hash: '#query'}); - var self = this; - this.verifyHistory_(['', 'search#query'], function() { - PageManager.showPageByName('settings', true, {'replaceState': true}); - self.verifyOpenPages_(['settings'], ''); - self.verifyHistory_(['', ''], testDone); - }); -}); - -// This should be identical to ShowPageWithHisory. -TEST_F('OptionsWebUIExtendedTest', 'NavigateToPage', function() { - PageManager.showPageByName('search', true, {hash: '#query'}); - var self = this; - this.verifyHistory_(['', 'search#query'], function() { - PageManager.showPageByName('settings'); - self.verifyOpenPages_(['settings'], ''); - self.verifyHistory_(['', 'search#query', ''], testDone); - }); -}); - -// Settings overlays are much more straightforward than settings pages, opening -// normally with none of the latter's quirks in the expected history or URL. -TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayNoHistory', function() { - // Open a layer-1 overlay, not updating history. - PageManager.showPageByName('languages', false); - this.verifyOpenPages_(['settings', 'languages'], ''); - - var self = this; - this.verifyHistory_([''], function() { - // Open a layer-2 overlay for which the layer-1 is a parent, not updating - // history. - PageManager.showPageByName('addLanguage', false); - self.verifyOpenPages_(['settings', 'languages', 'addLanguage'], - ''); - self.verifyHistory_([''], testDone); - }); -}); - -TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayWithHistory', function() { - // Open a layer-1 overlay, updating history. - PageManager.showPageByName('languages', true); - this.verifyOpenPages_(['settings', 'languages']); - - var self = this; - this.verifyHistory_(['', 'languages'], function() { - // Open a layer-2 overlay, updating history. - PageManager.showPageByName('addLanguage', true); - self.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - self.verifyHistory_(['', 'languages', 'addLanguage'], testDone); - }); -}); - -TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayReplaceHistory', function() { - // Open a layer-1 overlay, updating history. - PageManager.showPageByName('languages', true); - var self = this; - this.verifyHistory_(['', 'languages'], function() { - // Open a layer-2 overlay, replacing history. - PageManager.showPageByName('addLanguage', true, {'replaceState': true}); - self.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - self.verifyHistory_(['', 'addLanguage'], testDone); - }); -}); - -// Directly show an overlay further above this page, i.e. one for which the -// current page is an ancestor but not a parent. -TEST_F('OptionsWebUIExtendedTest', 'ShowOverlayFurtherAbove', function() { - // Open a layer-2 overlay directly. - PageManager.showPageByName('addLanguage', true); - this.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - var self = this; - this.verifyHistory_(['', 'addLanguage'], testDone); -}); - -// Directly show a layer-2 overlay for which the layer-1 overlay is not a -// parent. -TEST_F('OptionsWebUIExtendedTest', 'ShowUnrelatedOverlay', function() { - // Open a layer-1 overlay. - PageManager.showPageByName('languages', true); - this.verifyOpenPages_(['settings', 'languages']); - - var self = this; - this.verifyHistory_(['', 'languages'], function() { - // Open an unrelated layer-2 overlay. - PageManager.showPageByName('cookies', true); - self.verifyOpenPages_(['settings', 'content', 'cookies']); - self.verifyHistory_(['', 'languages', 'cookies'], testDone); - }); -}); - -// Close an overlay. -TEST_F('OptionsWebUIExtendedTest', 'CloseOverlay', function() { - // Open a layer-1 overlay, then a layer-2 overlay on top of it. - PageManager.showPageByName('languages', true); - this.verifyOpenPages_(['settings', 'languages']); - PageManager.showPageByName('addLanguage', true); - this.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - - var self = this; - this.verifyHistory_(['', 'languages', 'addLanguage'], function() { - // Close the layer-2 overlay. - PageManager.closeOverlay(); - self.verifyOpenPages_(['settings', 'languages']); - self.verifyHistory_( - ['', 'languages', 'addLanguage', 'languages'], - function() { - // Close the layer-1 overlay. - PageManager.closeOverlay(); - self.verifyOpenPages_(['settings'], ''); - self.verifyHistory_( - ['', 'languages', 'addLanguage', 'languages', ''], - function noop() {}); - waitUntilHidden([$('overlay-container-1'), $('overlay-container-2')]); - }); - }); -}); - -// Hashes are maintained separately for each page and are preserved when -// overlays close. -TEST_F('OptionsWebUIExtendedTest', 'CloseOverlayWithHashes', function() { - // Open an overlay on top of the search page. - PageManager.showPageByName('search', true, {hash: '#1'}); - this.verifyOpenPages_(['settings', 'search'], 'search#1'); - PageManager.showPageByName('languages', true, {hash: '#2'}); - this.verifyOpenPages_(['settings', 'search', 'languages'], - 'languages#2'); - PageManager.showPageByName('addLanguage', true, {hash: '#3'}); - this.verifyOpenPages_(['settings', 'search', 'languages', 'addLanguage'], - 'addLanguage#3'); - - this.verifyHistory_(['', 'search#1', 'languages#2', 'addLanguage#3'], - function() { - // Close the layer-2 overlay. - PageManager.closeOverlay(); - this.verifyOpenPages_(['settings', 'search', 'languages'], 'languages#2'); - this.verifyHistory_( - ['', 'search#1', 'languages#2', 'addLanguage#3', 'languages#2'], - function() { - // Close the layer-1 overlay. - PageManager.closeOverlay(); - this.verifyOpenPages_(['settings', 'search'], 'search#1'); - this.verifyHistory_( - ['', 'search#1', 'languages#2', 'addLanguage#3', 'languages#2', - 'search#1'], - function noop() {}); - waitUntilHidden([$('overlay-container-1'), $('overlay-container-2')]); - }.bind(this)); - }.bind(this)); -}); - -// Test that closing an overlay that did not push history when opening does not -// again push history. -TEST_F('OptionsWebUIExtendedTest', 'CloseOverlayNoHistory', function() { - // Open the do not track confirmation prompt. - PageManager.showPageByName('doNotTrackConfirm', false); - - // Opening the prompt does not add to the history. - this.verifyHistory_([''], function() { - // Close the overlay. - PageManager.closeOverlay(); - // Still no history changes. - this.verifyHistory_([''], function noop() {}); - waitUntilHidden([$('overlay-container-1')]); - }.bind(this)); -}); - -// Make sure an overlay isn't closed (even temporarily) when another overlay is -// opened on top. -TEST_F('OptionsWebUIExtendedTest', 'OverlayAboveNoReset', function() { - // Open a layer-1 overlay. - PageManager.showPageByName('languages', true); - this.verifyOpenPages_(['settings', 'languages']); - - // Open a layer-2 overlay on top. This should not close 'languages'. - this.prohibitChangesToOverlay_(options.LanguageOptions.getInstance()); - PageManager.showPageByName('addLanguage', true); - this.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - testDone(); -}); - -TEST_F('OptionsWebUIExtendedTest', 'OverlayTabNavigation', function() { - // Open a layer-1 overlay, then a layer-2 overlay on top of it. - PageManager.showPageByName('languages', true); - PageManager.showPageByName('addLanguage', true); - var self = this; - - // Go back twice, then forward twice. - self.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - self.verifyHistory_(['', 'languages', 'addLanguage'], function() { - window.history.back(); - waitForPopstate(function() { - self.verifyOpenPages_(['settings', 'languages']); - self.verifyHistory_(['', 'languages'], function() { - window.history.back(); - waitForPopstate(function() { - self.verifyOpenPages_(['settings'], ''); - self.verifyHistory_([''], function() { - window.history.forward(); - waitForPopstate(function() { - self.verifyOpenPages_(['settings', 'languages']); - self.verifyHistory_(['', 'languages'], function() { - window.history.forward(); - waitForPopstate(function() { - self.verifyOpenPages_( - ['settings', 'languages', 'addLanguage']); - self.verifyHistory_( - ['', 'languages', 'addLanguage'], testDone); - }); - }); - }); - }); - }); - }); - }); - }); -}); - -// Going "back" to an overlay that's a child of the current overlay shouldn't -// close the current one. -TEST_F('OptionsWebUIExtendedTest', 'OverlayBackToChild', function() { - // Open a layer-1 overlay, then a layer-2 overlay on top of it. - PageManager.showPageByName('languages', true); - PageManager.showPageByName('addLanguage', true); - var self = this; - - self.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - self.verifyHistory_(['', 'languages', 'addLanguage'], function() { - // Close the top overlay, then go back to it. - PageManager.closeOverlay(); - self.verifyOpenPages_(['settings', 'languages']); - self.verifyHistory_( - ['', 'languages', 'addLanguage', 'languages'], - function() { - // Going back to the 'addLanguage' page should not close 'languages'. - self.prohibitChangesToOverlay_(options.LanguageOptions.getInstance()); - window.history.back(); - waitForPopstate(function() { - self.verifyOpenPages_(['settings', 'languages', 'addLanguage']); - self.verifyHistory_(['', 'languages', 'addLanguage'], - testDone); - }); - }); - }); -}); - -// Going back to an unrelated overlay should close the overlay and its parent. -TEST_F('OptionsWebUIExtendedTest', 'OverlayBackToUnrelated', function() { - // Open a layer-1 overlay, then an unrelated layer-2 overlay. - PageManager.showPageByName('languages', true); - PageManager.showPageByName('cookies', true); - var self = this; - self.verifyOpenPages_(['settings', 'content', 'cookies']); - self.verifyHistory_(['', 'languages', 'cookies'], function() { - window.history.back(); - waitForPopstate(function() { - self.verifyOpenPages_(['settings', 'languages']); - testDone(); - }); - }); -}); - -// Verify history changes properly while the page is loading. -TEST_F('OptionsWebUIExtendedTest', 'HistoryUpdatedAfterLoading', function() { - var loc = location.href; - - document.documentElement.classList.add('loading'); - assertTrue(PageManager.isLoading()); - PageManager.showPageByName('searchEngines'); - expectNotEquals(loc, location.href); - - document.documentElement.classList.remove('loading'); - assertFalse(PageManager.isLoading()); - PageManager.showDefaultPage(); - expectEquals(loc, location.href); - - testDone(); -}); - -// A tip should be shown or hidden depending on whether this profile manages any -// supervised users. -TEST_F('OptionsWebUIExtendedTest', 'SupervisingUsers', function() { - // We start managing no supervised users. - assertTrue($('profiles-supervised-dashboard-tip').hidden); - - // Remove all supervised users, then add some, watching for the pref change - // notifications and UI updates in each case. Any non-empty pref dictionary - // is interpreted as having supervised users. - chrome.send('optionsTestSetPref', [SUPERVISED_USERS_PREF, {key: 'value'}]); - waitForResponse(BrowserOptions, 'updateManagesSupervisedUsers', function() { - assertFalse($('profiles-supervised-dashboard-tip').hidden); - chrome.send('optionsTestSetPref', [SUPERVISED_USERS_PREF, {}]); - waitForResponse(BrowserOptions, 'updateManagesSupervisedUsers', function() { - assertTrue($('profiles-supervised-dashboard-tip').hidden); - testDone(); - }); - }); -}); - -/** - * TestFixture that loads the options page at a bogus URL. - * @extends {OptionsWebUIExtendedTest} - * @constructor - */ -function OptionsWebUIRedirectTest() { - OptionsWebUIExtendedTest.call(this); -} - -OptionsWebUIRedirectTest.prototype = { - __proto__: OptionsWebUIExtendedTest.prototype, - - /** @override */ - browsePreload: 'chrome://settings-frame/nonexistantPage', -}; - -TEST_F('OptionsWebUIRedirectTest', 'TestURL', function() { - assertEquals('chrome://settings-frame/', document.location.href); - this.verifyHistory_([''], testDone); -});
diff --git a/chrome/browser/ui/webui/options/options_browsertest_base.js b/chrome/browser/ui/webui/options/options_browsertest_base.js deleted file mode 100644 index 073c7dc..0000000 --- a/chrome/browser/ui/webui/options/options_browsertest_base.js +++ /dev/null
@@ -1,86 +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. - -/** - * @constructor - * @extends {testing.Test} - */ -function OptionsBrowsertestBase() {} - -OptionsBrowsertestBase.prototype = { - __proto__: testing.Test.prototype, - - /** @override */ - runAccessibilityChecks: true, - - /** @override */ - accessibilityIssuesAreErrors: true, - - /** @override */ - setUp: function() { - testing.Test.prototype.setUp.call(this); - - var requiredOwnedAriaRoleMissingSelectors = [ - '#address-list', - '#creditcard-list', - '#home-page-overlay > .autocomplete-suggestions', - '#language-options-list', - '#manage-profile-icon-grid', - '#create-profile-icon-grid', - '#saved-passwords-list', - '#password-exceptions-list', - '#extension-keyword-list', - '#startup-overlay > .autocomplete-suggestions', - '#content-settings-exceptions-area > .content-area > *', - '#cookies-list', - '#handlers-list', - '#ignored-handlers-list', - '#supervised-user-list', - '#select-avatar-grid', - '#language-dictionary-overlay-word-list', - // Selectors below only affect ChromeOS tests. - '#bluetooth-unpaired-devices-list', - '#ignored-host-list', - '#remembered-network-list', - '#bluetooth-paired-devices-list', - ]; - - // Enable when failure is resolved. - // AX_ARIA_08: http://crbug.com/559265 - this.accessibilityAuditConfig.ignoreSelectors( - 'requiredOwnedAriaRoleMissing', - requiredOwnedAriaRoleMissingSelectors); - - var tabIndexGreaterThanZeroSelectors = [ - '#user-image-grid', - '#discard-photo', - '#take-photo', - '#flip-photo', - '#change-picture-overlay-confirm', - ]; - - // Enable when failure is resolved. - // AX_FOCUS_03: http://crbug.com/560910 - this.accessibilityAuditConfig.ignoreSelectors( - 'tabIndexGreaterThanZero', - tabIndexGreaterThanZeroSelectors); - - // Enable when audit has improved performance. - // AX_HTML_02: - // https://github.com/GoogleChrome/accessibility-developer-tools/issues/263 - this.accessibilityAuditConfig.auditRulesToIgnore.push( - 'duplicateId'); - - // Enable when failure is resolved. - // AX_ARIA_02: http://crbug.com/591547 - this.accessibilityAuditConfig.ignoreSelectors( - 'nonExistentAriaRelatedElement', '#input'); - - // Enable when failure is resolved. - // AX_ARIA_04: http://crbug.com/591550 - this.accessibilityAuditConfig.ignoreSelectors( - 'badAriaAttributeValue', '#input'); - - }, -};
diff --git a/chrome/browser/ui/webui/options/password_manager_browsertest.js b/chrome/browser/ui/webui/options/password_manager_browsertest.js deleted file mode 100644 index e94a72b9..0000000 --- a/chrome/browser/ui/webui/options/password_manager_browsertest.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. - -/** - * TestFixture for password manager WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function PasswordManagerWebUITest() {} - -PasswordManagerWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** - * Browse to the password manager. - */ - browsePreload: 'chrome://settings-frame/passwords', -}; - -// Test opening the password manager has correct location. -// Fails on Linux and Windows. http://crbug.com/467916 -TEST_F('PasswordManagerWebUITest', 'DISABLED_testOpenPasswordManager', - function() { - assertEquals(this.browsePreload, document.location.href); - });
diff --git a/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc b/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc deleted file mode 100644 index bdd275e..0000000 --- a/chrome/browser/ui/webui/options/password_manager_handler_unittest.cc +++ /dev/null
@@ -1,244 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/webui/options/password_manager_handler.h" - -#include "base/memory/ptr_util.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/statistics_recorder.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/password_manager/password_store_factory.h" -#include "chrome/browser/ui/passwords/password_manager_presenter.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "chrome/test/base/testing_profile.h" -#include "components/password_manager/core/browser/mock_password_store.h" -#include "components/password_manager/core/browser/password_manager_test_utils.h" -#include "content/public/test/test_web_ui.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/shell_dialogs/select_file_dialog.h" -#include "ui/shell_dialogs/select_file_dialog_factory.h" -#include "ui/shell_dialogs/select_file_policy.h" - -using password_manager::MockPasswordStore; - -namespace { - -class TestSelectFileDialogFactory final : public ui::SelectFileDialogFactory { - public: - TestSelectFileDialogFactory() {} - ~TestSelectFileDialogFactory() override {} - ui::SelectFileDialog* Create(ui::SelectFileDialog::Listener* listener, - ui::SelectFilePolicy* policy) override { - delete policy; // Ignore the policy, replace it with a test one. - return new TestSelectFileDialog(listener, new TestSelectFilePolicy); - } - - private: - class TestSelectFilePolicy : public ui::SelectFilePolicy { - public: - bool CanOpenSelectFileDialog() override { return true; } - void SelectFileDenied() override {} - }; - - class TestSelectFileDialog : public ui::SelectFileDialog { - public: - TestSelectFileDialog(Listener* listener, ui::SelectFilePolicy* policy) - : ui::SelectFileDialog(listener, policy) {} - - protected: - void SelectFileImpl(Type type, - const base::string16& title, - const base::FilePath& default_path, - const FileTypeInfo* file_types, - int file_type_index, - const base::FilePath::StringType& default_extension, - gfx::NativeWindow owning_window, - void* params) override { - listener_->FileSelected(default_path, file_type_index, params); - } - bool IsRunning(gfx::NativeWindow owning_window) const override { - return false; - } - void ListenerDestroyed() override {} - bool HasMultipleFileTypeChoicesImpl() override { return false; } - ~TestSelectFileDialog() override {} - }; -}; - -class CallbackTestWebUI : public content::TestWebUI { - public: - CallbackTestWebUI() {} - ~CallbackTestWebUI() override {} - void RegisterMessageCallback(const std::string& message, - const MessageCallback& callback) override; - void ProcessWebUIMessage(const GURL& source_url, - const std::string& message, - const base::ListValue& args) override; - - MOCK_CONST_METHOD0(GetWebContents, content::WebContents*()); - - private: - std::map<std::string, MessageCallback> message_callbacks_; -}; - -void CallbackTestWebUI::RegisterMessageCallback( - const std::string& message, - const MessageCallback& callback) { - message_callbacks_.insert(std::make_pair(message, callback)); -} - -void CallbackTestWebUI::ProcessWebUIMessage(const GURL& source_url, - const std::string& message, - const base::ListValue& args) { - std::map<std::string, MessageCallback>::const_iterator callback = - message_callbacks_.find(message); - if (callback != message_callbacks_.end()) { - callback->second.Run(&args); - } -} - -class TestPasswordManagerHandler : public options::PasswordManagerHandler { - public: - TestPasswordManagerHandler( - std::unique_ptr<PasswordManagerPresenter> presenter, - CallbackTestWebUI* web_ui) - : PasswordManagerHandler(std::move(presenter)) { - set_web_ui(web_ui); - } - ~TestPasswordManagerHandler() override {} -#if !defined(OS_ANDROID) - gfx::NativeWindow GetNativeWindow() const override; -#endif - - MOCK_METHOD3(FileSelected, void(const base::FilePath& path, int, void*)); -}; -#if !defined(OS_ANDROID) -gfx::NativeWindow TestPasswordManagerHandler::GetNativeWindow() const { - return NULL; -} -#endif - -class MockPasswordManagerPresenter : public PasswordManagerPresenter { - public: - explicit MockPasswordManagerPresenter(PasswordUIView* handler) - : PasswordManagerPresenter(handler) {} - ~MockPasswordManagerPresenter() override {} - - MOCK_METHOD0(IsUserAuthenticated, bool()); - - private: - DISALLOW_COPY_AND_ASSIGN(MockPasswordManagerPresenter); -}; - -class DummyPasswordManagerHandler : public PasswordUIView { - public: - explicit DummyPasswordManagerHandler(Profile* profile) - : profile_(profile), password_manager_presenter_(this) { - password_manager_presenter_.Initialize(); - } - ~DummyPasswordManagerHandler() override {} - Profile* GetProfile() override; - - void ShowPassword(size_t, - const std::string&, - const std::string&, - const base::string16&) override {} - void SetPasswordList( - const std::vector<std::unique_ptr<autofill::PasswordForm>>&) override {} - void SetPasswordExceptionList( - const std::vector<std::unique_ptr<autofill::PasswordForm>>&) override {} - -#if !defined(OS_ANDROID) - gfx::NativeWindow GetNativeWindow() const override; -#endif - private: - Profile* profile_; - PasswordManagerPresenter password_manager_presenter_; - - DISALLOW_COPY_AND_ASSIGN(DummyPasswordManagerHandler); -}; - -#if !defined(OS_ANDROID) -gfx::NativeWindow DummyPasswordManagerHandler::GetNativeWindow() const { - return NULL; -} -#endif - -Profile* DummyPasswordManagerHandler::GetProfile() { - return profile_; -} - -} // namespace - -class PasswordManagerHandlerTest : public ChromeRenderViewHostTestHarness { - protected: - PasswordManagerHandlerTest() {} - ~PasswordManagerHandlerTest() override {} - - void SetUp() override { - ChromeRenderViewHostTestHarness::SetUp(); - dummy_handler_.reset(new DummyPasswordManagerHandler(profile())); - presenter_raw_ = new MockPasswordManagerPresenter(dummy_handler_.get()); - handler_.reset(new TestPasswordManagerHandler( - base::WrapUnique(presenter_raw_), &web_ui_)); - handler_->RegisterMessages(); - ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactory); - handler_->InitializeHandler(); - web_ui_.set_web_contents(web_contents()); - } - - void TearDown() override { - handler_.reset(); - dummy_handler_.reset(); - ChromeRenderViewHostTestHarness::TearDown(); - } - - void ExportPassword() { - base::ListValue tmp; - web_ui_.ProcessWebUIMessage(GURL(), "exportPassword", tmp); - } - - void ImportPassword() { - base::ListValue tmp; - web_ui_.ProcessWebUIMessage(GURL(), "importPassword", tmp); - } - - PasswordManagerPresenter* presenter_raw_; - CallbackTestWebUI web_ui_; - std::unique_ptr<DummyPasswordManagerHandler> dummy_handler_; - std::unique_ptr<TestPasswordManagerHandler> handler_; - - private: - DISALLOW_COPY_AND_ASSIGN(PasswordManagerHandlerTest); -}; - -MATCHER(IsEmptyPath, "") { - return arg.empty(); -} - -TEST_F(PasswordManagerHandlerTest, PasswordImport) { - EXPECT_CALL(web_ui_, GetWebContents()) - .WillRepeatedly(testing::Return(web_contents())); - EXPECT_CALL( - *handler_, - FileSelected(IsEmptyPath(), 1, - reinterpret_cast<void*>( - TestPasswordManagerHandler::IMPORT_FILE_SELECTED))); - ImportPassword(); -} - -TEST_F(PasswordManagerHandlerTest, PasswordExport) { - const base::FilePath file_path; - EXPECT_CALL(*(static_cast<MockPasswordManagerPresenter*>(presenter_raw_)), - IsUserAuthenticated()) - .Times(testing::AtLeast(1)) - .WillRepeatedly(testing::Return(true)); - EXPECT_CALL( - *handler_, - FileSelected(IsEmptyPath(), 1, - reinterpret_cast<void*>( - TestPasswordManagerHandler::EXPORT_FILE_SELECTED))); - ExportPassword(); -}
diff --git a/chrome/browser/ui/webui/options/pepper_flash_content_settings_utils_unittest.cc b/chrome/browser/ui/webui/options/pepper_flash_content_settings_utils_unittest.cc deleted file mode 100644 index dd1317c..0000000 --- a/chrome/browser/ui/webui/options/pepper_flash_content_settings_utils_unittest.cc +++ /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. - -#include "chrome/browser/ui/webui/options/pepper_flash_content_settings_utils.h" - -#include <stddef.h> - -#include "base/macros.h" -#include "testing/gtest/include/gtest/gtest.h" - -using options::MediaException; -using options::MediaExceptions; -using options::PepperFlashContentSettingsUtils; - -namespace { - -MediaExceptions ConvertAndSort(const MediaException* items, size_t count) { - MediaExceptions result(items, items + count); - PepperFlashContentSettingsUtils::SortMediaExceptions(&result); - return result; -} - -} // namespace - -TEST(PepperFlashContentSettingsUtilsTest, SortMediaExceptions) { - MediaException entry_1(ContentSettingsPattern::FromString("www.google.com"), - CONTENT_SETTING_ALLOW); - MediaException entry_2(ContentSettingsPattern::FromString("www.youtube.com"), - CONTENT_SETTING_BLOCK); - MediaException entry_3(ContentSettingsPattern::Wildcard(), - CONTENT_SETTING_ASK); - MediaException entry_4(ContentSettingsPattern(), - CONTENT_SETTING_SESSION_ONLY); - - MediaExceptions list_1; - list_1.push_back(entry_1); - list_1.push_back(entry_2); - list_1.push_back(entry_3); - list_1.push_back(entry_4); - - MediaExceptions list_2; - list_2.push_back(entry_1); - list_2.push_back(entry_3); - list_2.push_back(entry_2); - list_2.push_back(entry_4); - - MediaExceptions list_3; - list_3.push_back(entry_4); - list_3.push_back(entry_1); - list_3.push_back(entry_2); - list_3.push_back(entry_3); - - EXPECT_NE(list_1, list_2); - EXPECT_NE(list_2, list_3); - EXPECT_NE(list_3, list_1); - - PepperFlashContentSettingsUtils::SortMediaExceptions(&list_1); - PepperFlashContentSettingsUtils::SortMediaExceptions(&list_2); - PepperFlashContentSettingsUtils::SortMediaExceptions(&list_3); - - EXPECT_EQ(list_1, list_2); - EXPECT_EQ(list_2, list_3); -} - -TEST(PepperFlashContentSettingsUtilsTest, AreMediaExceptionsEqual) { - { - // Empty lists are equal. - // Default settings are not compared directly, so it is possible to return - // true when they are different. - EXPECT_TRUE(PepperFlashContentSettingsUtils::AreMediaExceptionsEqual( - CONTENT_SETTING_BLOCK, - MediaExceptions(), - CONTENT_SETTING_ASK, - MediaExceptions())); - } - - { - MediaException exceptions_1[] = { - MediaException(ContentSettingsPattern::FromString("www.google.com"), - CONTENT_SETTING_ALLOW), - MediaException(ContentSettingsPattern::FromString("www.youtube.com"), - CONTENT_SETTING_ASK) - }; - - MediaException exceptions_2[] = { - MediaException(ContentSettingsPattern::FromString("www.google.com"), - CONTENT_SETTING_ALLOW) - }; - - // The exception of "www.youtube.com" in |exceptions_1| should not affect - // the result, because it has the same settings as |default_setting_2|. - EXPECT_TRUE(PepperFlashContentSettingsUtils::AreMediaExceptionsEqual( - CONTENT_SETTING_ALLOW, - ConvertAndSort(exceptions_1, arraysize(exceptions_1)), - CONTENT_SETTING_ASK, - ConvertAndSort(exceptions_2, arraysize(exceptions_2)))); - EXPECT_TRUE(PepperFlashContentSettingsUtils::AreMediaExceptionsEqual( - CONTENT_SETTING_ASK, - ConvertAndSort(exceptions_2, arraysize(exceptions_2)), - CONTENT_SETTING_ALLOW, - ConvertAndSort(exceptions_1, arraysize(exceptions_1)))); - // Changing |default_setting_2| should change the result. - EXPECT_FALSE(PepperFlashContentSettingsUtils::AreMediaExceptionsEqual( - CONTENT_SETTING_ALLOW, - ConvertAndSort(exceptions_1, arraysize(exceptions_1)), - CONTENT_SETTING_ALLOW, - ConvertAndSort(exceptions_2, arraysize(exceptions_2)))); - } - - { - // Similar to the previous block, but reoder the exceptions. The outcome - // should be the same. - MediaException exceptions_1[] = { - MediaException(ContentSettingsPattern::FromString("www.youtube.com"), - CONTENT_SETTING_ASK), - MediaException(ContentSettingsPattern::FromString("www.google.com"), - CONTENT_SETTING_ALLOW) - }; - - MediaException exceptions_2[] = { - MediaException(ContentSettingsPattern::FromString("www.google.com"), - CONTENT_SETTING_ALLOW) - }; - - EXPECT_TRUE(PepperFlashContentSettingsUtils::AreMediaExceptionsEqual( - CONTENT_SETTING_ALLOW, - ConvertAndSort(exceptions_1, arraysize(exceptions_1)), - CONTENT_SETTING_ASK, - ConvertAndSort(exceptions_2, arraysize(exceptions_2)))); - EXPECT_FALSE(PepperFlashContentSettingsUtils::AreMediaExceptionsEqual( - CONTENT_SETTING_ALLOW, - ConvertAndSort(exceptions_1, arraysize(exceptions_1)), - CONTENT_SETTING_ALLOW, - ConvertAndSort(exceptions_2, arraysize(exceptions_2)))); - } -}
diff --git a/chrome/browser/ui/webui/options/preferences_browsertest.cc b/chrome/browser/ui/webui/options/preferences_browsertest.cc deleted file mode 100644 index 3cc4c0b..0000000 --- a/chrome/browser/ui/webui/options/preferences_browsertest.cc +++ /dev/null
@@ -1,1106 +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 "chrome/browser/ui/webui/options/preferences_browsertest.h" - -#include <stddef.h> - -#include <iostream> -#include <memory> -#include <sstream> -#include <utility> - -#include "base/callback.h" -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/memory/ptr_util.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/url_constants.h" -#include "chrome/test/base/ui_test_utils.h" -#include "components/policy/core/browser/browser_policy_connector.h" -#include "components/policy/core/common/external_data_fetcher.h" -#include "components/policy/core/common/policy_map.h" -#include "components/policy/core/common/policy_types.h" -#include "components/policy/policy_constants.h" -#include "components/prefs/pref_service.h" -#include "content/public/browser/notification_details.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/browser_test_utils.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -#if defined(OS_CHROMEOS) -#include "base/strings/stringprintf.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/proxy_cros_settings_parser.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/chromeos/settings/stub_install_attributes.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/shill_profile_client.h" -#include "chromeos/dbus/shill_service_client.h" -#include "chromeos/network/network_state.h" -#include "chromeos/network/network_state_handler.h" -#include "chromeos/network/proxy/proxy_config_handler.h" -#include "chromeos/settings/cros_settings_names.h" -#include "components/onc/onc_pref_names.h" -#include "components/proxy_config/proxy_config_dictionary.h" -#include "components/proxy_config/proxy_config_pref_names.h" -#include "content/public/test/test_utils.h" -#include "third_party/cros_system_api/dbus/service_constants.h" -#endif - -using testing::AllOf; -using testing::Mock; -using testing::Property; -using testing::Return; -using testing::_; - -namespace base { - -// Helper for pretty-printing the contents of base::Value in case of failures. -void PrintTo(const base::Value& value, std::ostream* stream) { - std::string json; - JSONWriter::Write(value, &json); - *stream << json; -} - -} // namespace base - -// Googlemock matcher for base::Value. -MATCHER_P(EqualsValue, expected, "") { - return arg && arg->Equals(expected); -} - -PreferencesBrowserTest::PreferencesBrowserTest() { -} - -PreferencesBrowserTest::~PreferencesBrowserTest() { -} - -PrefService* PreferencesBrowserTest::pref_service() { - DCHECK(pref_change_registrar_); - return pref_change_registrar_->prefs(); -} - -// Navigates to the settings page, causing the JavaScript pref handling code to -// load and injects JavaScript testing code. -void PreferencesBrowserTest::SetUpOnMainThread() { - ui_test_utils::NavigateToURL(browser(), - GURL(chrome::kChromeUISettingsFrameURL)); - SetUpPrefs(); -} - -void PreferencesBrowserTest::TearDownOnMainThread() { - pref_change_registrar_.reset(); -} - -void PreferencesBrowserTest::SetUpPrefs() { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(web_contents); - render_view_host_ = web_contents->GetRenderViewHost(); - ASSERT_TRUE(render_view_host_); - - DCHECK(!pref_change_registrar_); - pref_change_registrar_.reset(new PrefChangeRegistrar); - pref_change_registrar_->Init(browser()->profile()->GetPrefs()); - - ASSERT_TRUE(content::ExecuteScript(render_view_host_, - "function TestEnv() {" - " this.sentinelName_ = 'download.prompt_for_download';" - " this.prefs_ = [];" - " TestEnv.instance_ = this;" - "}" - "" - "TestEnv.handleEvent = function(event) {" - " var env = TestEnv.instance_;" - " var name = event.type;" - " env.removePrefListener_(name);" - " if (name == TestEnv.sentinelName_)" - " env.sentinelValue_ = event.value.value;" - " else" - " env.reply_[name] = event.value;" - " if (env.fetching_ && !--env.fetching_ ||" - " !env.fetching_ && name == env.sentinelName_) {" - " env.removePrefListeners_();" - " window.domAutomationController.send(JSON.stringify(env.reply_));" - " delete env.reply_;" - " }" - "};" - "" - "TestEnv.prototype = {" - " addPrefListener_: function(name) {" - " Preferences.getInstance().addEventListener(name," - " TestEnv.handleEvent);" - " }," - "" - " addPrefListeners_: function() {" - " for (var i in this.prefs_)" - " this.addPrefListener_(this.prefs_[i]);" - " }," - "" - " removePrefListener_: function(name) {" - " Preferences.getInstance().removeEventListener(name," - " TestEnv.handleEvent);" - " }," - "" - " removePrefListeners_: function() {" - " for (var i in this.prefs_)" - " this.removePrefListener_(this.prefs_[i]);" - " }," - "" - "" - " addPref: function(name) {" - " this.prefs_.push(name);" - " }," - "" - " setupAndReply: function() {" - " this.reply_ = {};" - " Preferences.instance_ = new Preferences();" - " this.addPref(this.sentinelName_);" - " this.fetching_ = this.prefs_.length;" - " this.addPrefListeners_();" - " Preferences.getInstance().initialize();" - " }," - "" - " runAndReply: function(test) {" - " this.reply_ = {};" - " this.addPrefListeners_();" - " test();" - " this.sentinelValue_ = !this.sentinelValue_;" - " Preferences.setBooleanPref(this.sentinelName_, this.sentinelValue_," - " true);" - " }," - "" - " startObserving: function() {" - " this.reply_ = {};" - " this.addPrefListeners_();" - " }," - "" - " finishObservingAndReply: function() {" - " this.sentinelValue_ = !this.sentinelValue_;" - " Preferences.setBooleanPref(this.sentinelName_, this.sentinelValue_," - " true);" - " }" - "};")); -} - -// Forwards notifications received when pref values change in the backend. -void PreferencesBrowserTest::OnPreferenceChanged(const std::string& pref_name) { - OnCommit(pref_service()->FindPreference(pref_name.c_str())); -} - -void PreferencesBrowserTest::SetUpInProcessBrowserTestFixture() { - // Sets up a mock policy provider for user and device policies. - EXPECT_CALL(policy_provider_, IsInitializationComplete(_)) - .WillRepeatedly(Return(true)); - policy::BrowserPolicyConnector::SetPolicyProviderForTesting( - &policy_provider_); -} - -void PreferencesBrowserTest::SetUserPolicies( - const std::vector<std::string>& names, - const std::vector<std::unique_ptr<base::Value>>& values, - policy::PolicyLevel level) { - policy::PolicyMap map; - for (size_t i = 0; i < names.size(); ++i) { - map.Set(names[i], level, policy::POLICY_SCOPE_USER, - policy::POLICY_SOURCE_CLOUD, values[i]->CreateDeepCopy(), nullptr); - } - policy_provider_.UpdateChromePolicy(map); -} - -void PreferencesBrowserTest::ClearUserPolicies() { - policy::PolicyMap empty_policy_map; - policy_provider_.UpdateChromePolicy(empty_policy_map); -} - -void PreferencesBrowserTest::SetUserValues( - const std::vector<std::string>& names, - const std::vector<std::unique_ptr<base::Value>>& values) { - for (size_t i = 0; i < names.size(); ++i) { - pref_service()->Set(names[i].c_str(), *values[i]); - } -} - -void PreferencesBrowserTest::VerifyKeyValue(const base::DictionaryValue& dict, - const std::string& key, - const base::Value& expected) { - const base::Value* actual = NULL; - EXPECT_TRUE(dict.Get(key, &actual)) << "Was checking key: " << key; - if (actual) - EXPECT_EQ(expected, *actual) << "Was checking key: " << key; -} - -void PreferencesBrowserTest::VerifyPref( - const base::DictionaryValue* prefs, - const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy, - bool disabled, - bool uncommitted) { - const base::Value* pref = NULL; - const base::DictionaryValue* dict = NULL; - ASSERT_TRUE(prefs->GetWithoutPathExpansion(name, &pref)); - ASSERT_TRUE(pref->GetAsDictionary(&dict)); - VerifyKeyValue(*dict, "value", *value); - if (!controlledBy.empty()) - VerifyKeyValue(*dict, "controlledBy", base::Value(controlledBy)); - else - EXPECT_FALSE(dict->HasKey("controlledBy")); - - if (disabled) - VerifyKeyValue(*dict, "disabled", base::Value(true)); - else if (dict->HasKey("disabled")) - VerifyKeyValue(*dict, "disabled", base::Value(false)); - - if (uncommitted) - VerifyKeyValue(*dict, "uncommitted", base::Value(true)); - else if (dict->HasKey("uncommitted")) - VerifyKeyValue(*dict, "uncommitted", base::Value(false)); -} - -void PreferencesBrowserTest::VerifyObservedPref( - const std::string& json, - const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy, - bool disabled, - bool uncommitted) { - std::unique_ptr<base::Value> observed_value_ptr = - base::JSONReader::Read(json); - const base::DictionaryValue* observed_dict; - ASSERT_TRUE(observed_value_ptr.get()); - ASSERT_TRUE(observed_value_ptr->GetAsDictionary(&observed_dict)); - VerifyPref(observed_dict, name, value, controlledBy, disabled, uncommitted); -} - -void PreferencesBrowserTest::VerifyObservedPrefs( - const std::string& json, - const std::vector<std::string>& names, - const std::vector<std::unique_ptr<base::Value>>& values, - const std::string& controlledBy, - bool disabled, - bool uncommitted) { - std::unique_ptr<base::Value> observed_value_ptr = - base::JSONReader::Read(json); - const base::DictionaryValue* observed_dict; - ASSERT_TRUE(observed_value_ptr.get()); - ASSERT_TRUE(observed_value_ptr->GetAsDictionary(&observed_dict)); - for (size_t i = 0; i < names.size(); ++i) { - VerifyPref(observed_dict, names[i], values[i], controlledBy, disabled, - uncommitted); - } -} - -void PreferencesBrowserTest::ExpectNoCommit(const std::string& name) { - pref_change_registrar_->Add( - name.c_str(), - base::Bind(&PreferencesBrowserTest::OnPreferenceChanged, - base::Unretained(this))); - EXPECT_CALL(*this, OnCommit(Property(&PrefService::Preference::name, name))) - .Times(0); -} - -void PreferencesBrowserTest::ExpectSetCommit( - const std::string& name, - const std::unique_ptr<base::Value>& value) { - pref_change_registrar_->Add( - name.c_str(), - base::Bind(&PreferencesBrowserTest::OnPreferenceChanged, - base::Unretained(this))); - EXPECT_CALL( - *this, - OnCommit(AllOf(Property(&PrefService::Preference::name, name), - Property(&PrefService::Preference::IsUserControlled, true), - Property(&PrefService::Preference::GetValue, - EqualsValue(value.get()))))); -} - -void PreferencesBrowserTest::ExpectClearCommit(const std::string& name) { - pref_change_registrar_->Add( - name.c_str(), - base::Bind(&PreferencesBrowserTest::OnPreferenceChanged, - base::Unretained(this))); - EXPECT_CALL(*this, OnCommit(AllOf( - Property(&PrefService::Preference::name, name), - Property(&PrefService::Preference::IsUserControlled, false)))); -} - -void PreferencesBrowserTest::VerifyAndClearExpectations() { - Mock::VerifyAndClearExpectations(this); - pref_change_registrar_->RemoveAll(); -} - -void PreferencesBrowserTest::SetupJavaScriptTestEnvironment( - const std::vector<std::string>& pref_names, - std::string* observed_json) const { - std::stringstream javascript; - javascript << "var testEnv = new TestEnv();"; - for (const auto& name : pref_names) { - javascript << "testEnv.addPref('" << name.c_str() << "');"; - } - javascript << "testEnv.setupAndReply();"; - std::string temp_observed_json; - if (!observed_json) - observed_json = &temp_observed_json; - ASSERT_TRUE(content::ExecuteScriptAndExtractString( - render_view_host_, javascript.str(), observed_json)); -} - -void PreferencesBrowserTest::SetPref(const std::string& name, - const std::string& type, - const std::unique_ptr<base::Value>& value, - bool commit, - std::string* observed_json) { - std::unique_ptr<base::Value> commit_ptr(new base::Value(commit)); - std::stringstream javascript; - javascript << "testEnv.runAndReply(function() {" - << " Preferences.set" << type << "Pref(" - << " '" << name << "'," - << " " << *value << "," - << " " << *commit_ptr << ");" - << "});"; - ASSERT_TRUE(content::ExecuteScriptAndExtractString( - render_view_host_, javascript.str(), observed_json)); -} - -void PreferencesBrowserTest::VerifySetPref( - const std::string& name, - const std::string& type, - const std::unique_ptr<base::Value>& value, - bool commit) { - if (commit) - ExpectSetCommit(name, value); - else - ExpectNoCommit(name); - std::string observed_json; - SetPref(name, type, value, commit, &observed_json); - VerifyObservedPref(observed_json, name, value, std::string(), false, !commit); - VerifyAndClearExpectations(); -} - -void PreferencesBrowserTest::VerifyClearPref( - const std::string& name, - const std::unique_ptr<base::Value>& value, - bool commit) { - if (commit) - ExpectClearCommit(name); - else - ExpectNoCommit(name); - std::string commit_json; - base::JSONWriter::Write(base::Value(commit), &commit_json); - std::stringstream javascript; - javascript << "testEnv.runAndReply(function() {" - << " Preferences.clearPref(" - << " '" << name.c_str() << "'," - << " " << commit_json.c_str() << ");});"; - std::string observed_json; - ASSERT_TRUE(content::ExecuteScriptAndExtractString( - render_view_host_, javascript.str(), &observed_json)); - VerifyObservedPref(observed_json, name, value, "recommended", false, !commit); - VerifyAndClearExpectations(); -} - -void PreferencesBrowserTest::VerifyCommit( - const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy) { - std::stringstream javascript; - javascript << "testEnv.runAndReply(function() {" - << " Preferences.getInstance().commitPref(" - << " '" << name.c_str() << "');});"; - std::string observed_json; - ASSERT_TRUE(content::ExecuteScriptAndExtractString( - render_view_host_, javascript.str(), &observed_json)); - VerifyObservedPref(observed_json, name, value, controlledBy, false, false); -} - -void PreferencesBrowserTest::VerifySetCommit( - const std::string& name, - const std::unique_ptr<base::Value>& value) { - ExpectSetCommit(name, value); - VerifyCommit(name, value, std::string()); - VerifyAndClearExpectations(); -} - -void PreferencesBrowserTest::VerifyClearCommit( - const std::string& name, - const std::unique_ptr<base::Value>& value) { - ExpectClearCommit(name); - VerifyCommit(name, value, "recommended"); - VerifyAndClearExpectations(); -} - -void PreferencesBrowserTest::VerifyRollback( - const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy) { - ExpectNoCommit(name); - std::stringstream javascript; - javascript << "testEnv.runAndReply(function() {" - << " Preferences.getInstance().rollbackPref(" - << " '" << name.c_str() << "');});"; - std::string observed_json; - ASSERT_TRUE(content::ExecuteScriptAndExtractString( - render_view_host_, javascript.str(), &observed_json)); - VerifyObservedPref(observed_json, name, value, controlledBy, false, true); - VerifyAndClearExpectations(); -} - -void PreferencesBrowserTest::StartObserving() { - ASSERT_TRUE(content::ExecuteScript( - render_view_host_, "testEnv.startObserving();")); -} - -void PreferencesBrowserTest::FinishObserving(std::string* observed_json) { - ASSERT_TRUE(content::ExecuteScriptAndExtractString( - render_view_host_, - "testEnv.finishObservingAndReply();", - observed_json)); -} - -void PreferencesBrowserTest::UseDefaultTestPrefs(bool includeListPref) { - // Boolean pref. - types_.push_back("Boolean"); - pref_names_.push_back(prefs::kAlternateErrorPagesEnabled); - policy_names_.push_back(policy::key::kAlternateErrorPagesEnabled); - non_default_values_.push_back(base::MakeUnique<base::Value>(false)); - - // Integer pref. - types_.push_back("Integer"); - pref_names_.push_back(prefs::kRestoreOnStartup); - policy_names_.push_back(policy::key::kRestoreOnStartup); - non_default_values_.push_back(base::MakeUnique<base::Value>(4)); - - // List pref. - if (includeListPref) { - types_.push_back("List"); - pref_names_.push_back(prefs::kURLsToRestoreOnStartup); - policy_names_.push_back(policy::key::kRestoreOnStartupURLs); - auto list = base::MakeUnique<base::ListValue>(); - list->AppendString("http://www.example.com"); - list->AppendString("http://example.com"); - non_default_values_.push_back(std::move(list)); - } - - // Retrieve default values. - for (const auto& name : pref_names_) { - default_values_.push_back( - pref_service()->GetDefaultPrefValue(name.c_str())->CreateDeepCopy()); - } -} - -// Verifies that initializing the JavaScript Preferences class fires the correct -// notifications in JavaScript. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, FetchPrefs) { - UseDefaultTestPrefs(true); - std::string observed_json; - - // Verify notifications when default values are in effect. - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, default_values_, - std::string(), false, false); - - // Verify notifications when recommended values are in effect. - SetUserPolicies(policy_names_, non_default_values_, - policy::POLICY_LEVEL_RECOMMENDED); - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, - "recommended", false, false); - - // Verify notifications when mandatory values are in effect. - SetUserPolicies(policy_names_, non_default_values_, - policy::POLICY_LEVEL_MANDATORY); - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "policy", - true, false); - - // Verify notifications when user-modified values are in effect. - ClearUserPolicies(); - SetUserValues(pref_names_, non_default_values_); - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, - std::string(), false, false); -} - -// Verifies that setting a user-modified pref value through the JavaScript -// Preferences class fires the correct notification in JavaScript and causes the -// change to be committed to the C++ backend. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, SetPrefs) { - UseDefaultTestPrefs(false); - - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - for (size_t i = 0; i < pref_names_.size(); ++i) { - VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], true); - } -} - -// Verifies that clearing a user-modified pref value through the JavaScript -// Preferences class fires the correct notification in JavaScript and causes the -// change to be committed to the C++ backend. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ClearPrefs) { - UseDefaultTestPrefs(false); - - SetUserPolicies(policy_names_, default_values_, - policy::POLICY_LEVEL_RECOMMENDED); - SetUserValues(pref_names_, non_default_values_); - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - for (size_t i = 0; i < pref_names_.size(); ++i) { - VerifyClearPref(pref_names_[i], default_values_[i], true); - } -} - -// Verifies that when the user-modified value of a dialog pref is set and the -// change then committed through the JavaScript Preferences class, the correct -// notifications fire and a commit to the C++ backend occurs in the latter step -// only. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsSetCommit) { - UseDefaultTestPrefs(false); - - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - for (size_t i = 0; i < pref_names_.size(); ++i) { - VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false); - VerifySetCommit(pref_names_[i], non_default_values_[i]); - } -} - -// Verifies that when the user-modified value of a dialog pref is set and the -// change then rolled back through the JavaScript Preferences class, the correct -// notifications fire and no commit to the C++ backend occurs. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsSetRollback) { - UseDefaultTestPrefs(false); - - // Verify behavior when default values are in effect. - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - for (size_t i = 0; i < pref_names_.size(); ++i) { - VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false); - VerifyRollback(pref_names_[i], default_values_[i], std::string()); - } - - // Verify behavior when recommended values are in effect. - SetUserPolicies(policy_names_, default_values_, - policy::POLICY_LEVEL_RECOMMENDED); - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - for (size_t i = 0; i < pref_names_.size(); ++i) { - VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false); - VerifyRollback(pref_names_[i], default_values_[i], "recommended"); - } -} - -// Verifies that when the user-modified value of a dialog pref is cleared and -// the change then committed through the JavaScript Preferences class, the -// correct notifications fire and a commit to the C++ backend occurs in the -// latter step only. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsClearCommit) { - UseDefaultTestPrefs(false); - - SetUserPolicies(policy_names_, default_values_, - policy::POLICY_LEVEL_RECOMMENDED); - SetUserValues(pref_names_, non_default_values_); - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - for (size_t i = 0; i < pref_names_.size(); ++i) { - VerifyClearPref(pref_names_[i], default_values_[i], false); - VerifyClearCommit(pref_names_[i], default_values_[i]); - } -} - -// Verifies that when the user-modified value of a dialog pref is cleared and -// the change then rolled back through the JavaScript Preferences class, the -// correct notifications fire and no commit to the C++ backend occurs. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsClearRollback) { - UseDefaultTestPrefs(false); - - SetUserPolicies(policy_names_, default_values_, - policy::POLICY_LEVEL_RECOMMENDED); - SetUserValues(pref_names_, non_default_values_); - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - for (size_t i = 0; i < pref_names_.size(); ++i) { - VerifyClearPref(pref_names_[i], default_values_[i], false); - VerifyRollback(pref_names_[i], non_default_values_[i], std::string()); - } -} - -// Verifies that when preference values change in the C++ backend, the correct -// notifications fire in JavaScript. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, NotificationsOnBackendChanges) { - UseDefaultTestPrefs(false); - std::string observed_json; - - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - - // Verify notifications when recommended values come into effect. - StartObserving(); - SetUserPolicies(policy_names_, non_default_values_, - policy::POLICY_LEVEL_RECOMMENDED); - FinishObserving(&observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, - "recommended", false, false); - - // Verify notifications when mandatory values come into effect. - StartObserving(); - SetUserPolicies(policy_names_, non_default_values_, - policy::POLICY_LEVEL_MANDATORY); - FinishObserving(&observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "policy", - true, false); - - // Verify notifications when default values come into effect. - StartObserving(); - ClearUserPolicies(); - FinishObserving(&observed_json); - VerifyObservedPrefs(observed_json, pref_names_, default_values_, - std::string(), false, false); - - // Verify notifications when user-modified values come into effect. - StartObserving(); - SetUserValues(pref_names_, non_default_values_); - FinishObserving(&observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, - std::string(), false, false); -} - -#if defined(OS_CHROMEOS) - -// Verifies that initializing the JavaScript Preferences class fires the correct -// notifications in JavaScript for pref values handled by the -// CoreChromeOSOptionsHandler class. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ChromeOSDeviceFetchPrefs) { - std::string observed_json; - - // Boolean pref. - pref_names_.push_back(chromeos::kAccountsPrefAllowGuest); - default_values_.push_back(base::MakeUnique<base::Value>(true)); - - // String pref. - pref_names_.push_back(chromeos::kReleaseChannel); - default_values_.push_back(base::MakeUnique<base::Value>("")); - - // List pref. - pref_names_.push_back(chromeos::kAccountsPrefUsers); - default_values_.push_back(base::MakeUnique<base::ListValue>()); - - // Verify notifications when default values are in effect. - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, default_values_, "owner", - true, false); -} - -// Verifies that initializing the JavaScript Preferences class fires the correct -// notifications in JavaScript for non-privileged pref values handled by the -// CoreChromeOSOptionsHandler class. -IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, - ChromeOSDeviceFetchNonPrivilegedPrefs) { - std::vector<std::unique_ptr<base::Value>> decorated_non_default_values; - std::string observed_json; - - // Non-privileged string pref. - pref_names_.push_back(chromeos::kSystemTimezone); - default_values_.push_back( - base::MakeUnique<base::Value>("America/Los_Angeles")); - non_default_values_.push_back( - base::MakeUnique<base::Value>("America/New_York")); - decorated_non_default_values.push_back( - non_default_values_.back()->CreateDeepCopy()); - - // Verify notifications when default values are in effect. - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, default_values_, - std::string(), false, false); - - chromeos::CrosSettings* cros_settings = chromeos::CrosSettings::Get(); - cros_settings->Set(pref_names_[0], *non_default_values_[0]); - - // Verify notifications when non-default values are in effect. - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, decorated_non_default_values, - std::string(), false, false); -} - -class ManagedPreferencesBrowserTest : public PreferencesBrowserTest { - protected: - // PreferencesBrowserTest implementation: - void SetUpInProcessBrowserTestFixture() override { - // Set up fake install attributes. - std::unique_ptr<chromeos::StubInstallAttributes> attributes = - base::MakeUnique<chromeos::StubInstallAttributes>(); - attributes->SetCloudManaged("example.com", "fake-id"); - policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting( - attributes.release()); - - PreferencesBrowserTest::SetUpInProcessBrowserTestFixture(); - } -}; - -// Verifies that initializing the JavaScript Preferences class fires the correct -// notifications in JavaScript for pref values handled by the -// CoreChromeOSOptionsHandler class for a managed device. -IN_PROC_BROWSER_TEST_F(ManagedPreferencesBrowserTest, - ChromeOSDeviceFetchPrefs) { - std::vector<std::unique_ptr<base::Value>> decorated_non_default_values; - std::string observed_json; - - // Boolean pref. - pref_names_.push_back(chromeos::kAccountsPrefAllowGuest); - non_default_values_.push_back(base::MakeUnique<base::Value>(false)); - decorated_non_default_values.push_back( - non_default_values_.back()->CreateDeepCopy()); - - // String pref. - pref_names_.push_back(chromeos::kReleaseChannel); - non_default_values_.push_back( - base::MakeUnique<base::Value>("stable-channel")); - decorated_non_default_values.push_back( - non_default_values_.back()->CreateDeepCopy()); - - // List pref. - pref_names_.push_back(chromeos::kAccountsPrefUsers); - auto list = base::MakeUnique<base::ListValue>(); - list->AppendString("me@google.com"); - list->AppendString("you@google.com"); - non_default_values_.push_back(std::move(list)); - list = base::MakeUnique<base::ListValue>(); - auto dict = base::MakeUnique<base::DictionaryValue>(); - dict->SetString("username", "me@google.com"); - dict->SetString("name", "me@google.com"); - dict->SetString("email", ""); - dict->SetBoolean("owner", false); - list->Append(std::move(dict)); - dict = base::MakeUnique<base::DictionaryValue>(); - dict->SetString("username", "you@google.com"); - dict->SetString("name", "you@google.com"); - dict->SetString("email", ""); - dict->SetBoolean("owner", false); - list->Append(std::move(dict)); - decorated_non_default_values.push_back(std::move(list)); - - chromeos::CrosSettings* cros_settings = chromeos::CrosSettings::Get(); - for (size_t i = 0; i < pref_names_.size(); ++i) { - cros_settings->Set(pref_names_[i], *non_default_values_[i]); - } - - // Verify notifications when mandatory values are in effect. - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, decorated_non_default_values, - "policy", true, false); -} - -// Verifies that initializing the JavaScript Preferences class fires the correct -// notifications in JavaScript for non-privileged pref values handled by the -// CoreChromeOSOptionsHandler class for a managed device. -IN_PROC_BROWSER_TEST_F(ManagedPreferencesBrowserTest, - ChromeOSDeviceFetchNonPrivilegedPrefs) { - std::vector<std::unique_ptr<base::Value>> decorated_non_default_values; - std::string observed_json; - - // Non-privileged string pref. - pref_names_.push_back(chromeos::kSystemTimezone); - non_default_values_.push_back( - base::MakeUnique<base::Value>("America/New_York")); - decorated_non_default_values.push_back( - non_default_values_.back()->CreateDeepCopy()); - - // Verify notifications when mandatory values are in effect. - chromeos::CrosSettings* cros_settings = chromeos::CrosSettings::Get(); - cros_settings->Set(pref_names_[0], *non_default_values_[0]); - - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, decorated_non_default_values, - std::string(), false, false); -} - -namespace { - -const char* kUserProfilePath = "user_profile"; - -} // namespace - -class ProxyPreferencesBrowserTest : public PreferencesBrowserTest { - public: - void SetUpOnMainThread() override { - SetupNetworkEnvironment(); - content::RunAllPendingInMessageLoop(); - - std::unique_ptr<base::DictionaryValue> proxy_config_dict( - ProxyConfigDictionary::CreateFixedServers("127.0.0.1:8080", - "*.google.com, 1.2.3.4:22")); - - ProxyConfigDictionary proxy_config(std::move(proxy_config_dict)); - - const chromeos::NetworkState* network = GetDefaultNetwork(); - ASSERT_TRUE(network); - chromeos::proxy_config::SetProxyConfigForNetwork(proxy_config, *network); - - std::string url = base::StringPrintf("%s?network=%s", - chrome::kChromeUIProxySettingsURL, - network->guid().c_str()); - - ui_test_utils::NavigateToURL(browser(), GURL(url)); - SetUpPrefs(); - } - - protected: - void SetupNetworkEnvironment() { - chromeos::ShillProfileClient::TestInterface* profile_test = - chromeos::DBusThreadManager::Get()->GetShillProfileClient() - ->GetTestInterface(); - chromeos::ShillServiceClient::TestInterface* service_test = - chromeos::DBusThreadManager::Get()->GetShillServiceClient() - ->GetTestInterface(); - - profile_test->AddProfile(kUserProfilePath, "user"); - - service_test->ClearServices(); - service_test->AddService("stub_ethernet", - "stub_ethernet_guid", - "eth0", - shill::kTypeEthernet, - shill::kStateOnline, - true /* add_to_visible */ ); - service_test->SetServiceProperty("stub_ethernet", shill::kProfileProperty, - base::Value(kUserProfilePath)); - profile_test->AddService(kUserProfilePath, "stub_wifi2"); - } - - void SetONCPolicy(const char* policy_name, policy::PolicyScope scope) { - std::string onc_policy = - "{ \"NetworkConfigurations\": [" - " { \"GUID\": \"stub_ethernet_guid\"," - " \"Type\": \"Ethernet\"," - " \"Name\": \"My Ethernet\"," - " \"Ethernet\": {" - " \"Authentication\": \"None\" }," - " \"ProxySettings\": {" - " \"PAC\": \"http://domain.com/x\"," - " \"Type\": \"PAC\" }" - " }" - " ]," - " \"Type\": \"UnencryptedConfiguration\"" - "}"; - - policy::PolicyMap map; - map.Set(policy_name, policy::POLICY_LEVEL_MANDATORY, scope, - policy::POLICY_SOURCE_CLOUD, - base::MakeUnique<base::Value>(onc_policy), nullptr); - policy_provider_.UpdateChromePolicy(map); - - content::RunAllPendingInMessageLoop(); - } - - const chromeos::NetworkState* GetDefaultNetwork() { - chromeos::NetworkStateHandler* handler = - chromeos::NetworkHandler::Get()->network_state_handler(); - return handler->DefaultNetwork(); - } - - void SetProxyPref(const std::string& name, const base::Value& value) { - std::string type; - switch (value.GetType()) { - case base::Value::Type::BOOLEAN: - type = "Boolean"; - break; - case base::Value::Type::INTEGER: - type = "Integer"; - break; - case base::Value::Type::STRING: - type = "String"; - break; - default: - ASSERT_TRUE(false); - } - - std::string observed_json; - SetPref(name, type, value.CreateDeepCopy(), true, &observed_json); - } - - void VerifyCurrentProxyServer(const std::string& expected_server, - onc::ONCSource expected_source) { - const chromeos::NetworkState* network = GetDefaultNetwork(); - ASSERT_TRUE(network); - onc::ONCSource actual_source; - std::unique_ptr<ProxyConfigDictionary> proxy_dict = - chromeos::proxy_config::GetProxyConfigForNetwork( - g_browser_process->local_state(), pref_service(), *network, - &actual_source); - ASSERT_TRUE(proxy_dict); - std::string actual_proxy_server; - EXPECT_TRUE(proxy_dict->GetProxyServer(&actual_proxy_server)); - EXPECT_EQ(expected_server, actual_proxy_server); - EXPECT_EQ(expected_source, actual_source); - } -}; - -// Verifies that proxy settings are correctly pushed to JavaScript during -// initialization of the proxy settings page. -IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSInitializeProxy) { - // Boolean pref. - pref_names_.push_back(chromeos::proxy_cros_settings_parser::kProxySingle); - non_default_values_.push_back(base::MakeUnique<base::Value>(true)); - - // Integer prefs. - pref_names_.push_back( - chromeos::proxy_cros_settings_parser::kProxySingleHttpPort); - non_default_values_.push_back(base::MakeUnique<base::Value>(8080)); - - // String pref. - pref_names_.push_back(chromeos::proxy_cros_settings_parser::kProxySingleHttp); - non_default_values_.push_back(base::MakeUnique<base::Value>("127.0.0.1")); - - // List pref. - pref_names_.push_back(chromeos::proxy_cros_settings_parser::kProxyIgnoreList); - auto list = base::MakeUnique<base::ListValue>(); - list->AppendString("*.google.com"); - list->AppendString("1.2.3.4:22"); - non_default_values_.push_back(std::move(list)); - - // Verify that no policy is presented to the UI. This must be verified on the - // kProxyType and the kUseSharedProxies prefs. - pref_names_.push_back(chromeos::proxy_cros_settings_parser::kProxyType); - non_default_values_.push_back(base::MakeUnique<base::Value>(2)); - - pref_names_.push_back(proxy_config::prefs::kUseSharedProxies); - non_default_values_.push_back(base::MakeUnique<base::Value>(false)); - - std::string observed_json; - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "", - false, false); -} - -IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ONCPolicy) { - SetONCPolicy(policy::key::kOpenNetworkConfiguration, - policy::POLICY_SCOPE_USER); - - // Verify that per-network policy is presented to the UI. This must be - // verified on the kProxyType. - pref_names_.push_back(chromeos::proxy_cros_settings_parser::kProxyType); - non_default_values_.push_back(base::MakeUnique<base::Value>(3)); - - std::string observed_json; - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "policy", - true, false); - - // Verify that 'use-shared-proxies' is not affected by per-network policy. - pref_names_.clear(); - non_default_values_.clear(); - pref_names_.push_back(proxy_config::prefs::kUseSharedProxies); - non_default_values_.push_back(base::MakeUnique<base::Value>(false)); - - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "", - false, false); -} - -IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, DeviceONCPolicy) { - SetONCPolicy(policy::key::kDeviceOpenNetworkConfiguration, - policy::POLICY_SCOPE_MACHINE); - - // Verify that the policy is presented to the UI. This verification must be - // done on the kProxyType pref. - pref_names_.push_back(chromeos::proxy_cros_settings_parser::kProxyType); - non_default_values_.push_back(base::MakeUnique<base::Value>(3)); - - std::string observed_json; - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "policy", - true, false); - - // Verify that 'use-shared-proxies' is not affected by per-network policy. - pref_names_.clear(); - non_default_values_.clear(); - pref_names_.push_back(proxy_config::prefs::kUseSharedProxies); - non_default_values_.push_back(base::MakeUnique<base::Value>(false)); - - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "", - false, false); -} - -IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, UserProxyPolicy) { - policy_names_.push_back(policy::key::kProxyMode); - default_values_.push_back( - base::MakeUnique<base::Value>(ProxyPrefs::kAutoDetectProxyModeName)); - SetUserPolicies(policy_names_, default_values_, - policy::POLICY_LEVEL_MANDATORY); - content::RunAllPendingInMessageLoop(); - - // Verify that the policy is presented to the UI. This verification must be - // done on the kProxyType pref. - pref_names_.push_back(chromeos::proxy_cros_settings_parser::kProxyType); - non_default_values_.push_back(base::MakeUnique<base::Value>(3)); - - // Verify that 'use-shared-proxies' is controlled by the policy. - pref_names_.push_back(proxy_config::prefs::kUseSharedProxies); - non_default_values_.push_back(base::MakeUnique<base::Value>(false)); - - std::string observed_json; - SetupJavaScriptTestEnvironment(pref_names_, &observed_json); - VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, "policy", - true, false); -} - -// Verifies that modifications to the proxy settings are correctly pushed from -// JavaScript to the ProxyConfig property stored in the network configuration. -IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSSetProxy) { - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxySingleHttpPort, - base::Value(123)); - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxySingleHttp, - base::Value("www.adomain.xy")); - - VerifyCurrentProxyServer("www.adomain.xy:123", - onc::ONC_SOURCE_NONE); -} - -// Verify that default proxy ports are used and that ports can be updated -// without affecting the previously set hosts. -IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSProxyDefaultPorts) { - ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); - - // Set to manual, per scheme proxy. - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxySingle, - base::Value(false)); - - // Set hosts but no ports. - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxyHttpUrl, - base::Value("a.com")); - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxyHttpsUrl, - base::Value("4.3.2.1")); - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxyFtpUrl, - base::Value("c.com")); - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxySocks, - base::Value("d.com")); - - // Verify default ports. - VerifyCurrentProxyServer( - "http=a.com:80;https=4.3.2.1:80;ftp=c.com:80;socks=socks4://d.com:1080", - onc::ONC_SOURCE_NONE); - - // Set and verify the ports. - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxyHttpPort, - base::Value(1)); - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxyHttpsPort, - base::Value(2)); - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxyFtpPort, - base::Value(3)); - SetProxyPref(chromeos::proxy_cros_settings_parser::kProxySocksPort, - base::Value(4)); - - VerifyCurrentProxyServer( - "http=a.com:1;https=4.3.2.1:2;ftp=c.com:3;socks=socks4://d.com:4", - onc::ONC_SOURCE_NONE); -} - -#endif
diff --git a/chrome/browser/ui/webui/options/preferences_browsertest.h b/chrome/browser/ui/webui/options/preferences_browsertest.h deleted file mode 100644 index d2136d3..0000000 --- a/chrome/browser/ui/webui/options/preferences_browsertest.h +++ /dev/null
@@ -1,196 +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. - -#ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_PREFERENCES_BROWSERTEST_H_ -#define CHROME_BROWSER_UI_WEBUI_OPTIONS_PREFERENCES_BROWSERTEST_H_ - -#include <memory> -#include <string> -#include <vector> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "chrome/test/base/in_process_browser_test.h" -#include "components/policy/core/common/mock_configuration_policy_provider.h" -#include "components/policy/core/common/policy_types.h" -#include "components/prefs/pref_change_registrar.h" -#include "components/prefs/pref_service.h" -#include "content/public/browser/notification_observer.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace base { -class DictionaryValue; -class Value; -} - -namespace content { -class RenderViewHost; -} - -// Tests verifying that the JavaScript Preferences class, the underlying C++ -// CoreOptionsHandler and the specialized classes handling Chrome OS device and -// proxy prefs behave correctly. -class PreferencesBrowserTest : public InProcessBrowserTest { - public: - PreferencesBrowserTest(); - ~PreferencesBrowserTest() override; - - // InProcessBrowserTest implementation: - void SetUpOnMainThread() override; - void TearDownOnMainThread() override; - - void OnPreferenceChanged(const std::string& pref_name); - - protected: - MOCK_METHOD1(OnCommit, void(const PrefService::Preference*)); - - // The pref service that holds the current pref values in the C++ backend. - PrefService* pref_service(); - - void SetUpPrefs(); - - // InProcessBrowserTest implementation: - void SetUpInProcessBrowserTestFixture() override; - - // Sets user policies through the mock policy provider. - void SetUserPolicies(const std::vector<std::string>& names, - const std::vector<std::unique_ptr<base::Value>>& values, - policy::PolicyLevel level); - // Clears user policies. - void ClearUserPolicies(); - // Set user-modified pref values directly in the C++ backend. - void SetUserValues(const std::vector<std::string>& names, - const std::vector<std::unique_ptr<base::Value>>& values); - - // Verifies that a dictionary contains a (key, value) pair. Takes ownership of - // |expected|. - void VerifyKeyValue(const base::DictionaryValue& dict, - const std::string& key, - const base::Value& expected); - // Verifies that a dictionary contains a given pref and that its value has - // been decorated correctly. - void VerifyPref(const base::DictionaryValue* prefs, - const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy, - bool disabled, - bool uncommitted); - // Verifies that a notification received from the JavaScript Preferences - // class contains a given pref and that its value has been decorated - // correctly. - void VerifyObservedPref(const std::string& observed_json, - const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy, - bool disabled, - bool uncommitted); - // Verifies that notifications received from the JavaScript Preferences class - // contain the given prefs and that their values have been decorated - // correctly. - void VerifyObservedPrefs( - const std::string& observed_json, - const std::vector<std::string>& names, - const std::vector<std::unique_ptr<base::Value>>& values, - const std::string& controlledBy, - bool disabled, - bool uncommitted); - - // Sets up the expectation that the JavaScript Preferences class will make no - // change to a user-modified pref value in the C++ backend. - void ExpectNoCommit(const std::string& name); - // Sets up the expectation that the JavaScript Preferences class will set a - // user-modified pref value in the C++ backend. - void ExpectSetCommit(const std::string& name, - const std::unique_ptr<base::Value>& value); - // Sets up the expectation that the JavaScript Preferences class will clear a - // user-modified pref value in the C++ backend. - void ExpectClearCommit(const std::string& name); - // Verifies that previously set expectations are met and clears them. - void VerifyAndClearExpectations(); - - // Sets up the JavaScript part of the test environment. - void SetupJavaScriptTestEnvironment( - const std::vector<std::string>& pref_names, - std::string* observed_json) const; - - // Sets a value through the JavaScript Preferences class as if the user had - // modified it. Returns the observation which can be verified using the - // VerifyObserved* methods. - void SetPref(const std::string& name, - const std::string& type, - const std::unique_ptr<base::Value>& value, - bool commit, - std::string* observed_json); - - // Verifies that setting a user-modified pref value through the JavaScript - // Preferences class fires the correct notification in JavaScript and commits - // the change to C++ if |commit| is true. - void VerifySetPref(const std::string& name, - const std::string& type, - const std::unique_ptr<base::Value>& value, - bool commit); - // Verifies that clearing a user-modified pref value through the JavaScript - // Preferences class fires the correct notification in JavaScript and does - // respectively does not cause the change to be committed to the C++ backend. - void VerifyClearPref(const std::string& name, - const std::unique_ptr<base::Value>& value, - bool commit); - // Verifies that committing a previously made change of a user-modified pref - // value through the JavaScript Preferences class fires the correct - // notification in JavaScript. - void VerifyCommit(const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy); - // Verifies that committing a previously set user-modified pref value through - // the JavaScript Preferences class fires the correct notification in - // JavaScript and causes the change to be committed to the C++ backend. - void VerifySetCommit(const std::string& name, - const std::unique_ptr<base::Value>& value); - // Verifies that committing the previously cleared user-modified pref value - // through the JavaScript Preferences class fires the correct notification in - // JavaScript and causes the change to be committed to the C++ backend. - void VerifyClearCommit(const std::string& name, - const std::unique_ptr<base::Value>& value); - // Verifies that rolling back a previously made change of a user-modified pref - // value through the JavaScript Preferences class fires the correct - // notification in JavaScript and does not cause the change to be committed to - // the C++ backend. - void VerifyRollback(const std::string& name, - const std::unique_ptr<base::Value>& value, - const std::string& controlledBy); - // Start observing notifications sent by the JavaScript Preferences class for - // pref values changes. - void StartObserving(); - // Change the value of a sentinel pref in the C++ backend and finish observing - // notifications sent by the JavaScript Preferences class when the - // notification for this pref is received. - void FinishObserving(std::string* observed_json); - - // Populate the lists of test prefs and corresponding policies with default - // values used by most tests. - void UseDefaultTestPrefs(bool includeListPref); - - // The current tab's render view host, required to inject JavaScript code into - // the tab. - content::RenderViewHost* render_view_host_; - - // Mock policy provider for both user and device policies. - policy::MockConfigurationPolicyProvider policy_provider_; - - // Pref change registrar that detects changes to user-modified pref values - // made in the C++ backend by the JavaScript Preferences class. - std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; - - // The prefs and corresponding policies used by the current test. - std::vector<std::string> types_; - std::vector<std::string> pref_names_; - std::vector<std::string> policy_names_; - std::vector<std::unique_ptr<base::Value>> default_values_; - std::vector<std::unique_ptr<base::Value>> non_default_values_; - - private: - DISALLOW_COPY_AND_ASSIGN(PreferencesBrowserTest); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_OPTIONS_PREFERENCES_BROWSERTEST_H_
diff --git a/chrome/browser/ui/webui/options/profile_settings_reset_browsertest.js b/chrome/browser/ui/webui/options/profile_settings_reset_browsertest.js deleted file mode 100644 index 2bd7a05..0000000 --- a/chrome/browser/ui/webui/options/profile_settings_reset_browsertest.js +++ /dev/null
@@ -1,38 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for profile settings reset WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function ProfileSettingsResetWebUITest() {} - -ProfileSettingsResetWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Browse to the reset profile settings page. - */ - browsePreload: 'chrome://settings-frame/resetProfileSettings', - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/570551 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#reset-profile-settings-overlay > .action-area > .hbox.stretch > A'); - }, -}; - -// Test opening the profile settings reset has correct location. -TEST_F('ProfileSettingsResetWebUITest', 'testOpenProfileSettingsReset', - function() { - assertEquals(this.browsePreload, document.location.href); - });
diff --git a/chrome/browser/ui/webui/options/search_engine_manager_browsertest.js b/chrome/browser/ui/webui/options/search_engine_manager_browsertest.js deleted file mode 100644 index 88b4a27..0000000 --- a/chrome/browser/ui/webui/options/search_engine_manager_browsertest.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. - -/** - * TestFixture for search engine manager WebUI testing. - * @extends {testing.Test} - * @constructor - */ -function SearchEngineManagerWebUITest() {} - -SearchEngineManagerWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** - * Browse to the search engine manager. - */ - browsePreload: 'chrome://settings-frame/searchEngines', -}; - -// Disabled due to flaky timeouts; see crbug.com/205693 . -// Test opening the search engine manager has correct location. -TEST_F('SearchEngineManagerWebUITest', 'DISABLED_testOpenSearchEngineManager', - function() { - assertEquals(this.browsePreload, document.location.href); - });
diff --git a/chrome/browser/ui/webui/options/settings_format_browsertest.js b/chrome/browser/ui/webui/options/settings_format_browsertest.js deleted file mode 100644 index a84873f..0000000 --- a/chrome/browser/ui/webui/options/settings_format_browsertest.js +++ /dev/null
@@ -1,176 +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. - -GEN_INCLUDE(['options_browsertest_base.js']); - -/** - * TestFixture for testing the formatting of settings pages. - * @extends {testing.Test} - * @constructor - */ -function SettingsFormatWebUITest() {} - -/** - * Map of rule exemptions grouped by test. - * @const - */ -SettingsFormatWebUITest.Filters = { - /** - * Exemption for checkboxes that do not require an id or pref property. - * Input methods use inputMethodId instead of id for unique identification. - */ - 'pref': ['language-options-input-method-template', - 'language-options-input-method-list'] -}; - -/** - * Collection of error messages. - * @const - */ -SettingsFormatWebUITest.Messages = { - MISSING_CHECK_WRAPPER: 'Element $1 should be enclosed in <div class="$2">', - MISSING_ID_OR_PREF: 'Missing id or pref preoperty for checkbox $1.', - MISSING_RADIO_BUTTON_NAME: 'Radio button $1 is missing the name property', - MISSING_RADIO_BUTTON_VALUE: 'Radio button $1 is missing the value property', -}; - -SettingsFormatWebUITest.prototype = { - __proto__: OptionsBrowsertestBase.prototype, - - /** - * Navigate to browser settings. - */ - browsePreload: 'chrome://settings-frame/', - - /** - * List of errors generated during a test. Used instead of expect* functions - * to suppress verbosity. The implementation of errorsToMessage in the - * testing API generates a call stack for each error produced which greatly - * reduces readability. - * @type {Array<string>} - */ - errors: null, - - /** @override */ - setUp: function() { - OptionsBrowsertestBase.prototype.setUp.call(this); - - this.errors = []; - - // Enable when failure is resolved. - // AX_TEXT_04: http://crbug.com/570727 - this.accessibilityAuditConfig.ignoreSelectors( - 'linkWithUnclearPurpose', - '#sync-overview > A'); - - // Enable when failure is resolved. - // AX_ARIA_10: http://crbug.com/570725 - this.accessibilityAuditConfig.ignoreSelectors( - 'unsupportedAriaAttribute', - '#profiles-list'); - }, - - tearDown: function() { - assertTrue(this.errors.length == 0, '\n' + this.errors.join('\n')); - }, - - /** - * Generates a failure message. During tear down of the test, the accumulation - * of pending messages triggers a test failure. - * @param {string} key Label of the message formatting string. - * @param {!Element} element The element that triggered the failure. - * @param {...string} args Additional arguments for formatting the message. - */ - fail: function(key, element, args) { - var subs = [this.getLabel(element)].concat( - Array.prototype.slice.call(arguments, 2)); - var message = SettingsFormatWebUITest.Messages[key].replace( - /\$\d/g, - function(m) { - return subs[m[1] - 1] || '$' + m[1]; - }); - assertFalse(/\$\d/.test(message), 'found unreplaced subs'); - this.errors.push(message); - }, - - /** - * String for identifying a node within an error message. - * @param {!Element} element The target element to identify. - * @return {string} Name to facilitate tracking down the element. - */ - getLabel: function(element) { - if (element.id) - return element.id; - - if (element.pref) - return element.pref; - - if (element.name && element.value) - return element.name + '-' + element.value; - - return this.getLabel(element.parentNode); - }, - - - /** - * Checks if the node is exempt from following the formatting rule. - * @param {!Element} element The candidate element. - * @param {Array<string>} filters List of exemptions. - * @return {boolean} True if the element is exempt. - */ - isExempt: function(element, filters) { - var target = this.getLabel(element); - for (var i = 0; i < filters.length; i++) { - if (filters[i] == target) - return true; - } - return false; - } -}; - -/** - * Ensure that radio and checkbox buttons have consistent layout. - */ -TEST_F('SettingsFormatWebUITest', 'RadioCheckboxStyleCheck', function() { - var settings = $('settings'); - assertTrue(settings != null, 'Unable to access settings'); - var query = 'input[type=checkbox], input[type=radio]'; - var elements = document.querySelectorAll(query); - assertTrue(elements.length > 0); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - if (!findAncestorByClass(element, element.type)) - this.fail('MISSING_CHECK_WRAPPER', element, element.type); - } -}); - -/** - * Each checkbox requires an id or pref property. - */ -// Flaky crashes on all platforms; http://crbug.com/613034. -TEST_F('SettingsFormatWebUITest', 'DISABLED_CheckboxIdOrPrefCheck', function() { - var query = - 'input[type=checkbox]:not([pref]):not([id]):not(.spacer-checkbox)'; - var elements = document.querySelectorAll(query); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - if (!this.isExempt(element, SettingsFormatWebUITest.Filters['pref'])) - this.fail('MISSING_ID_OR_PREF', element); - } -}); - -/** - * Each radio button requires name and value properties. - */ -TEST_F('SettingsFormatWebUITest', 'RadioButtonNameValueCheck', function() { - var elements = document.querySelectorAll('input[type=radio]'); - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - if (!element.name) - this.fail('MISSING_RADIO_BUTTON_NAME', element); - - if (!element.getAttribute('value')) - this.fail('MISSING_RADIO_BUTTON_VALUE', element); - } -});
diff --git a/chrome/browser/ui/webui/options/startup_page_list_browsertest.js b/chrome/browser/ui/webui/options/startup_page_list_browsertest.js deleted file mode 100644 index 1df6e28..0000000 --- a/chrome/browser/ui/webui/options/startup_page_list_browsertest.js +++ /dev/null
@@ -1,151 +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. - -/** - * Fixture for startup pages WebUI tests. - * @extends {testing.Test} - * @constructor - */ -function StartupPageListWebUITest() {} - -StartupPageListWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** - * Browse to the options page & call our preLoad(). - * @override - */ - browsePreload: 'chrome://settings-frame/startup', - - /** @override */ - setUp: function() { - StartupOverlay.updateStartupPages(this.fakeStartupList); - // 1 item for entering data, 1+ from |this.fakeStartupList|. - assertGE(this.getList().items.length, 2); - }, - - /** - * Returns the list to be tested. - * @return {Element} The start-up pages list. - * @protected - */ - getList: function() { - return $('startupPagesList'); - }, - - /** - * Register a mock handler to ensure expectations are met and options pages - * behave correctly. - * @override - */ - preLoad: function() { - this.makeAndRegisterMockHandler(['addStartupPage', - 'dragDropStartupPage']); - }, - - /** - * A fake list of startup pages to send to the overlay. - * @protected - */ - fakeStartupList: [ - { - title: 'Yahoo!', - url: 'http://yahoo.com', - tooltip: 'Yahoo! homepage', - modelIndex: 0 - }, - { - title: 'Facebook', - url: 'http://facebook.com', - tooltip: 'Facebook :: Sign In', - modelIndex: 1 - } - ], -}; - -(function() { - -/** - * A mock data transfer object for drag/drop events. - * @constructor - */ -function MockDataTransfer() { - /** - * The data this dataTransfer object knows about. - * @type {!Object<string>} - * @private - */ - this.data_ = {}; -} - -/** - * Installs a lazily created MockDataTransfer on event#dataTransfer. - * @param {!Event} event An event to modify. - */ -MockDataTransfer.install = function(event) { - event.__defineGetter__('dataTransfer', function() { - event.dataTransfer_ = event.dataTransfer_ || new MockDataTransfer; - return event.dataTransfer_; - }); -}; - -MockDataTransfer.prototype = { - /** - * The URL data in this mock drop event. - * @param {string} type The text of data being set. - * @param {*} val The data to set. Will be stringified. - */ - setData: function(type, val) { - this.data_[type] = String(val); - }, - - /** - * Gets data associated with this fake data transfer. - * @param {string} type The type of data to get. - * @return {string} The requested type of data or '' if not set. - */ - getData: function(type) { - return this.data_[type] || ''; - }, -}; - -/** - * Creates a fake bubbling, cancelable mouse event with a mock data transfer - * installed. - * @param {string} type A type of mouse event (e.g. 'drop'). - * @return {!Event} A fake mouse event. - */ -function createMouseEvent(type) { - var event = new MouseEvent(type, {bubbles: true, cancelable: true}); - MockDataTransfer.install(event); - return event; -} - -// Disabled due to: crbug.com/419370 -TEST_F('StartupPageListWebUITest', 'DISABLED_testDropFromOutsideSource', - function() { - /** @const */ var NEW_PAGE = 'http://google.com'; - - var mockDropEvent = createMouseEvent('drop'); - mockDropEvent.dataTransfer.setData('url', NEW_PAGE); - - this.mockHandler.expects(once()).addStartupPage([NEW_PAGE, 0]); - - this.getList().items[0].dispatchEvent(mockDropEvent); - - expectTrue(mockDropEvent.defaultPrevented); -}); - -// Disabled due to: crbug.com/419370 -TEST_F('StartupPageListWebUITest', 'DISABLED_testDropToReorder', function() { - // TODO(dbeam): mock4js doesn't handle complex arguments well. Fix this. - this.mockHandler.expects(once()).dragDropStartupPage([0, [1].join()]); - - this.getList().selectionModel.selectedIndex = 1; - expectEquals(1, this.getList().selectionModel.selectedIndexes.length); - - this.getList().items[0].dispatchEvent(createMouseEvent('drop')); -}); - -}());
diff --git a/chrome/browser/ui/webui/options/sync_setup_handler_unittest.cc b/chrome/browser/ui/webui/options/sync_setup_handler_unittest.cc deleted file mode 100644 index e24b055d..0000000 --- a/chrome/browser/ui/webui/options/sync_setup_handler_unittest.cc +++ /dev/null
@@ -1,951 +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 "chrome/browser/ui/webui/options/sync_setup_handler.h" - -#include <memory> -#include <string> -#include <vector> - -#include "base/command_line.h" -#include "base/json/json_writer.h" -#include "base/macros.h" -#include "base/stl_util.h" -#include "base/values.h" -#include "build/build_config.h" -#include "chrome/browser/signin/fake_signin_manager_builder.h" -#include "chrome/browser/signin/signin_error_controller_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" -#include "chrome/browser/sync/profile_sync_test_util.h" -#include "chrome/browser/ui/webui/signin/login_ui_service.h" -#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" -#include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile.h" -#include "components/prefs/pref_service.h" -#include "components/signin/core/browser/fake_auth_status_provider.h" -#include "components/signin/core/browser/signin_manager.h" -#include "components/sync/base/sync_prefs.h" -#include "content/public/browser/web_ui.h" -#include "content/public/test/test_browser_thread.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "content/public/test/test_web_ui.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/layout.h" - -using ::testing::_; -using ::testing::Mock; -using ::testing::Return; -using ::testing::ReturnRef; -using ::testing::Values; -using browser_sync::ProfileSyncService; -using browser_sync::ProfileSyncServiceMock; - -typedef GoogleServiceAuthError AuthError; - -namespace { - -MATCHER_P(ModelTypeSetMatches, value, "") { - return arg == value; -} - -const char kTestUser[] = "chrome.p13n.test@gmail.com"; - -// Returns a ModelTypeSet with all user selectable types set. -syncer::ModelTypeSet GetAllTypes() { - return syncer::UserSelectableTypes(); -} - -enum SyncAllDataConfig { - SYNC_ALL_DATA, - CHOOSE_WHAT_TO_SYNC -}; - -enum EncryptAllConfig { - ENCRYPT_ALL_DATA, - ENCRYPT_PASSWORDS -}; - -enum PaymentsIntegrationConfig { - PAYMENTS_INTEGRATION_ENABLED, - PAYMENTS_INTEGRATION_DISABLED -}; - -// Create a json-format string with the key/value pairs appropriate for a call -// to HandleConfigure(). If |extra_values| is non-null, then the values from -// the passed dictionary are added to the json. -std::string GetConfiguration(const base::DictionaryValue* extra_values, - SyncAllDataConfig sync_all, - syncer::ModelTypeSet types, - const std::string& passphrase, - EncryptAllConfig encrypt_all, - PaymentsIntegrationConfig payments_integration) { - base::DictionaryValue result; - if (extra_values) - result.MergeDictionary(extra_values); - result.SetBoolean("syncAllDataTypes", sync_all == SYNC_ALL_DATA); - result.SetBoolean("encryptAllData", encrypt_all == ENCRYPT_ALL_DATA); - result.SetBoolean("usePassphrase", !passphrase.empty()); - if (!passphrase.empty()) - result.SetString("passphrase", passphrase); - // Add all of our data types. - result.SetBoolean("appsSynced", types.Has(syncer::APPS)); - result.SetBoolean("autofillSynced", types.Has(syncer::AUTOFILL)); - result.SetBoolean("bookmarksSynced", types.Has(syncer::BOOKMARKS)); - result.SetBoolean("extensionsSynced", types.Has(syncer::EXTENSIONS)); - result.SetBoolean("passwordsSynced", types.Has(syncer::PASSWORDS)); - result.SetBoolean("preferencesSynced", types.Has(syncer::PREFERENCES)); - result.SetBoolean("tabsSynced", types.Has(syncer::PROXY_TABS)); - result.SetBoolean("themesSynced", types.Has(syncer::THEMES)); - result.SetBoolean("typedUrlsSynced", types.Has(syncer::TYPED_URLS)); - result.SetBoolean("paymentsIntegrationEnabled", - payments_integration == PAYMENTS_INTEGRATION_ENABLED); - std::string args; - base::JSONWriter::Write(result, &args); - return args; -} - -// Checks whether the passed |dictionary| contains a |key| with the given -// |expected_value|. If |omit_if_false| is true, then the value should only -// be present if |expected_value| is true. -void CheckBool(const base::DictionaryValue* dictionary, - const std::string& key, - bool expected_value, - bool omit_if_false) { - if (omit_if_false && !expected_value) { - EXPECT_FALSE(dictionary->HasKey(key)) << - "Did not expect to find value for " << key; - } else { - bool actual_value; - EXPECT_TRUE(dictionary->GetBoolean(key, &actual_value)) << - "No value found for " << key; - EXPECT_EQ(expected_value, actual_value) << - "Mismatch found for " << key; - } -} - -void CheckBool(const base::DictionaryValue* dictionary, - const std::string& key, - bool expected_value) { - return CheckBool(dictionary, key, expected_value, false); -} - -// Checks to make sure that the values stored in |dictionary| match the values -// expected by the showSyncSetupPage() JS function for a given set of data -// types. -void CheckConfigDataTypeArguments(const base::DictionaryValue* dictionary, - SyncAllDataConfig config, - syncer::ModelTypeSet types) { - CheckBool(dictionary, "syncAllDataTypes", config == SYNC_ALL_DATA); - CheckBool(dictionary, "appsSynced", types.Has(syncer::APPS)); - CheckBool(dictionary, "autofillSynced", types.Has(syncer::AUTOFILL)); - CheckBool(dictionary, "bookmarksSynced", types.Has(syncer::BOOKMARKS)); - CheckBool(dictionary, "extensionsSynced", types.Has(syncer::EXTENSIONS)); - CheckBool(dictionary, "passwordsSynced", types.Has(syncer::PASSWORDS)); - CheckBool(dictionary, "preferencesSynced", types.Has(syncer::PREFERENCES)); - CheckBool(dictionary, "tabsSynced", types.Has(syncer::PROXY_TABS)); - CheckBool(dictionary, "themesSynced", types.Has(syncer::THEMES)); - CheckBool(dictionary, "typedUrlsSynced", types.Has(syncer::TYPED_URLS)); -} - - -} // namespace - -class TestingSyncSetupHandler : public SyncSetupHandler { - public: - TestingSyncSetupHandler(content::WebUI* web_ui, Profile* profile) - : profile_(profile) { - set_web_ui(web_ui); - } - ~TestingSyncSetupHandler() override { set_web_ui(NULL); } - - void FocusUI() override {} - - Profile* GetProfile() const override { return profile_; } - - using SyncSetupHandler::is_configuring_sync; - - private: -#if !defined(OS_CHROMEOS) - void DisplayGaiaLoginInNewTabOrWindow( - signin_metrics::AccessPoint access_point) override {} -#endif - - // Weak pointer to parent profile. - Profile* profile_; - DISALLOW_COPY_AND_ASSIGN(TestingSyncSetupHandler); -}; - -// The boolean parameter indicates whether the test is run with ClientOAuth -// or not. The test parameter is a bool: whether or not to test with/ -// /ClientLogin enabled or not. -class SyncSetupHandlerTest : public testing::Test { - public: - SyncSetupHandlerTest() : error_(GoogleServiceAuthError::NONE) {} - void SetUp() override { - error_ = GoogleServiceAuthError::AuthErrorNone(); - - TestingProfile::Builder builder; - builder.AddTestingFactory(SigninManagerFactory::GetInstance(), - BuildFakeSigninManagerBase); - profile_ = builder.Build(); - - // Sign in the user. - mock_signin_ = static_cast<SigninManagerBase*>( - SigninManagerFactory::GetForProfile(profile_.get())); - std::string username = GetTestUser(); - if (!username.empty()) - mock_signin_->SetAuthenticatedAccountInfo(username, username); - - mock_pss_ = static_cast<ProfileSyncServiceMock*>( - ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( - profile_.get(), BuildMockProfileSyncService)); - EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_)); - ON_CALL(*mock_pss_, GetPassphraseType()) - .WillByDefault(Return(syncer::PassphraseType::IMPLICIT_PASSPHRASE)); - ON_CALL(*mock_pss_, GetExplicitPassphraseTime()).WillByDefault( - Return(base::Time())); - ON_CALL(*mock_pss_, GetRegisteredDataTypes()) - .WillByDefault(Return(syncer::ModelTypeSet())); - - mock_pss_->Initialize(); - - handler_.reset(new TestingSyncSetupHandler(&web_ui_, profile_.get())); - } - - // Setup the expectations for calls made when displaying the config page. - void SetDefaultExpectationsForConfigPage() { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, GetRegisteredDataTypes()) - .WillRepeatedly(Return(GetAllTypes())); - EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()) - .WillRepeatedly(Return(GetAllTypes())); - EXPECT_CALL(*mock_pss_, GetActiveDataTypes()) - .WillRepeatedly(Return(GetAllTypes())); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingEnabled()) - .WillRepeatedly(Return(false)); - } - - void SetupInitializedProfileSyncService() { - // An initialized ProfileSyncService will have already completed sync setup - // and will have an initialized sync engine. - ASSERT_TRUE(mock_signin_->IsInitialized()); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(true)); - } - - void ExpectConfig() { - ASSERT_EQ(1U, web_ui_.call_data().size()); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name()); - std::string page; - ASSERT_TRUE(data.arg1()->GetAsString(&page)); - EXPECT_EQ(page, "configure"); - } - - void ExpectDone() { - ASSERT_EQ(1U, web_ui_.call_data().size()); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name()); - std::string page; - ASSERT_TRUE(data.arg1()->GetAsString(&page)); - EXPECT_EQ(page, "done"); - } - - void ExpectSpinnerAndClose() { - // We expect a call to SyncSetupOverlay.showSyncSetupPage. - EXPECT_EQ(1U, web_ui_.call_data().size()); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name()); - - std::string page; - ASSERT_TRUE(data.arg1()->GetAsString(&page)); - EXPECT_EQ(page, "spinner"); - // Cancelling the spinner dialog will cause CloseSyncSetup(). - handler_->CloseSyncSetup(); - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); - } - - // It's difficult to notify sync listeners when using a ProfileSyncServiceMock - // so this helper routine dispatches an OnStateChanged() notification to the - // SyncStartupTracker. - void NotifySyncListeners() { - if (handler_->sync_startup_tracker_) - handler_->sync_startup_tracker_->OnStateChanged(mock_pss_); - } - - virtual std::string GetTestUser() { - return std::string(kTestUser); - } - - content::TestBrowserThreadBundle thread_bundle_; - std::unique_ptr<Profile> profile_; - ProfileSyncServiceMock* mock_pss_; - GoogleServiceAuthError error_; - SigninManagerBase* mock_signin_; - content::TestWebUI web_ui_; - std::unique_ptr<TestingSyncSetupHandler> handler_; -}; - -class SyncSetupHandlerFirstSigninTest : public SyncSetupHandlerTest { - std::string GetTestUser() override { return std::string(); } -}; - -TEST_F(SyncSetupHandlerTest, Basic) { -} - -#if !defined(OS_CHROMEOS) -TEST_F(SyncSetupHandlerFirstSigninTest, DisplayBasicLogin) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - // Ensure that the user is not signed in before calling |HandleStartSignin()|. - SigninManager* manager = static_cast<SigninManager*>(mock_signin_); - manager->SignOut(signin_metrics::SIGNOUT_TEST, - signin_metrics::SignoutDelete::IGNORE_METRIC); - base::ListValue list_args; - handler_->HandleStartSignin(&list_args); - - // Sync setup hands off control to the gaia login tab. - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); - - ASSERT_FALSE(handler_->is_configuring_sync()); - - handler_->CloseSyncSetup(); - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); -} - -TEST_F(SyncSetupHandlerTest, ShowSyncSetupWhenNotSignedIn) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - handler_->HandleShowSetupUI(NULL); - - // We expect a call to SyncSetupOverlay.showSyncSetupPage. - ASSERT_EQ(1U, web_ui_.call_data().size()); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name()); - - ASSERT_FALSE(handler_->is_configuring_sync()); - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); -} -#endif // !defined(OS_CHROMEOS) - -// Verifies that the sync setup is terminated correctly when the -// sync is disabled. -TEST_F(SyncSetupHandlerTest, HandleSetupUIWhenSyncDisabled) { - EXPECT_CALL(*mock_pss_, IsManaged()).WillRepeatedly(Return(true)); - handler_->HandleShowSetupUI(NULL); - - // Sync setup is closed when sync is disabled. - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); - ASSERT_FALSE(handler_->is_configuring_sync()); -} - -// Verifies that the handler correctly handles a cancellation when -// it is displaying the spinner to the user. -TEST_F(SyncSetupHandlerTest, DisplayConfigureWithEngineDisabledAndCancel) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); - - // We're simulating a user setting up sync, which would cause the engine to - // kick off initialization, but not download user data types. The sync - // engine will try to download control data types (e.g encryption info), but - // that won't finish for this test as we're simulating cancelling while the - // spinner is showing. - handler_->HandleShowSetupUI(NULL); - - EXPECT_EQ(handler_.get(), - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); - - ExpectSpinnerAndClose(); -} - -// Verifies that the handler correctly transitions from showing the spinner -// to showing a configuration page when sync setup completes successfully. -TEST_F(SyncSetupHandlerTest, - DisplayConfigureWithEngineDisabledAndSyncStartupCompleted) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - error_ = GoogleServiceAuthError::AuthErrorNone(); - // Sync engine is stopped initially, and will start up. - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); - SetDefaultExpectationsForConfigPage(); - - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - // We expect a call to SyncSetupOverlay.showSyncSetupPage. - EXPECT_EQ(1U, web_ui_.call_data().size()); - - const content::TestWebUI::CallData& data0 = *web_ui_.call_data()[0]; - EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data0.function_name()); - std::string page; - ASSERT_TRUE(data0.arg1()->GetAsString(&page)); - EXPECT_EQ(page, "spinner"); - - Mock::VerifyAndClearExpectations(mock_pss_); - // Now, act as if the ProfileSyncService has started up. - SetDefaultExpectationsForConfigPage(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(true)); - error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_)); - NotifySyncListeners(); - - // We expect a second call to SyncSetupOverlay.showSyncSetupPage. - EXPECT_EQ(2U, web_ui_.call_data().size()); - const content::TestWebUI::CallData& data1 = *web_ui_.call_data().back(); - EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data1.function_name()); - ASSERT_TRUE(data1.arg1()->GetAsString(&page)); - EXPECT_EQ(page, "configure"); - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data1.arg2()->GetAsDictionary(&dictionary)); - CheckBool(dictionary, "passphraseFailed", false); - CheckBool(dictionary, "syncAllDataTypes", true); - CheckBool(dictionary, "encryptAllDataAllowed", true); - CheckBool(dictionary, "encryptAllData", false); - CheckBool(dictionary, "usePassphrase", false); -} - -// Verifies the case where the user cancels after the sync engine has -// initialized (meaning it already transitioned from the spinner to a proper -// configuration page, tested by -// DisplayConfigureWithEngineDisabledAndSyncStartupCompleted), but before the -// user has continued on. -TEST_F(SyncSetupHandlerTest, - DisplayConfigureWithEngineDisabledAndCancelAfterSigninSuccess) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()) - .WillOnce(Return(false)) - .WillRepeatedly(Return(true)); - SetDefaultExpectationsForConfigPage(); - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - // It's important to tell sync the user cancelled the setup flow before we - // tell it we're through with the setup progress. - testing::InSequence seq; - EXPECT_CALL(*mock_pss_, RequestStop(ProfileSyncService::CLEAR_DATA)); - EXPECT_CALL(*mock_pss_, OnSetupInProgressHandleDestroyed()); - - handler_->CloseSyncSetup(); - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); -} - -TEST_F(SyncSetupHandlerTest, - DisplayConfigureWithEngineDisabledAndSigninFailed) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); - - handler_->OpenSyncSetup(false /* creating_supervised_user */); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - EXPECT_EQ("SyncSetupOverlay.showSyncSetupPage", data.function_name()); - std::string page; - ASSERT_TRUE(data.arg1()->GetAsString(&page)); - EXPECT_EQ(page, "spinner"); - Mock::VerifyAndClearExpectations(mock_pss_); - error_ = GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); - EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_)); - NotifySyncListeners(); - - // On failure, the dialog will be closed. - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); -} - -#if !defined(OS_CHROMEOS) - -class SyncSetupHandlerNonCrosTest : public SyncSetupHandlerTest { - public: - SyncSetupHandlerNonCrosTest() {} -}; - -TEST_F(SyncSetupHandlerNonCrosTest, HandleGaiaAuthFailure) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, HasUnrecoverableError()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - // Open the web UI. - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ASSERT_FALSE(handler_->is_configuring_sync()); -} - -// TODO(kochi): We need equivalent tests for ChromeOS. -TEST_F(SyncSetupHandlerNonCrosTest, UnrecoverableErrorInitializingSync) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - // Open the web UI. - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ASSERT_FALSE(handler_->is_configuring_sync()); -} - -TEST_F(SyncSetupHandlerNonCrosTest, GaiaErrorInitializingSync) { - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - // Open the web UI. - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ASSERT_FALSE(handler_->is_configuring_sync()); -} - -#endif // #if !defined(OS_CHROMEOS) - -TEST_F(SyncSetupHandlerTest, TestSyncEverything) { - std::string args = - GetConfiguration(NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), - ENCRYPT_PASSWORDS, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _)); - handler_->HandleConfigure(&list_args); - - // Ensure that we navigated to the "done" state since we don't need a - // passphrase. - ExpectDone(); -} - -TEST_F(SyncSetupHandlerTest, TurnOnEncryptAll) { - std::string args = - GetConfiguration(NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), - ENCRYPT_ALL_DATA, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed()) - .WillRepeatedly(Return(true)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, EnableEncryptEverything()); - EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _)); - handler_->HandleConfigure(&list_args); - - // Ensure that we navigated to the "done" state since we don't need a - // passphrase. - ExpectDone(); -} - -TEST_F(SyncSetupHandlerTest, TestPassphraseStillRequired) { - std::string args = - GetConfiguration(NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), - ENCRYPT_PASSWORDS, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _)); - SetDefaultExpectationsForConfigPage(); - - // We should navigate back to the configure page since we need a passphrase. - handler_->HandleConfigure(&list_args); - - ExpectConfig(); -} - -TEST_F(SyncSetupHandlerTest, SuccessfullySetPassphrase) { - base::DictionaryValue dict; - dict.SetBoolean("isGooglePassphrase", true); - std::string args = - GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(), "gaiaPassphrase", - ENCRYPT_PASSWORDS, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - // Act as if an encryption passphrase is required the first time, then never - // again after that. - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()).WillOnce(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _)); - EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("gaiaPassphrase")). - WillOnce(Return(true)); - - handler_->HandleConfigure(&list_args); - // We should navigate to "done" page since we finished configuring. - ExpectDone(); -} - -TEST_F(SyncSetupHandlerTest, SelectCustomEncryption) { - base::DictionaryValue dict; - dict.SetBoolean("isGooglePassphrase", false); - std::string args = - GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(), "custom_passphrase", - ENCRYPT_PASSWORDS, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _)); - EXPECT_CALL(*mock_pss_, - SetEncryptionPassphrase("custom_passphrase", - ProfileSyncService::EXPLICIT)); - - handler_->HandleConfigure(&list_args); - // We should navigate to "done" page since we finished configuring. - ExpectDone(); -} - -TEST_F(SyncSetupHandlerTest, UnsuccessfullySetPassphrase) { - base::DictionaryValue dict; - dict.SetBoolean("isGooglePassphrase", true); - std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(), - "invalid_passphrase", ENCRYPT_PASSWORDS, - PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(_, _)); - EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("invalid_passphrase")). - WillOnce(Return(false)); - - SetDefaultExpectationsForConfigPage(); - // We should navigate back to the configure page since we need a passphrase. - handler_->HandleConfigure(&list_args); - - ExpectConfig(); - - // Make sure we display an error message to the user due to the failed - // passphrase. - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckBool(dictionary, "passphraseFailed", true); -} - -// Walks through each user selectable type, and tries to sync just that single -// data type. -TEST_F(SyncSetupHandlerTest, TestSyncIndividualTypes) { - syncer::ModelTypeSet user_selectable_types = GetAllTypes(); - syncer::ModelTypeSet::Iterator it; - for (it = user_selectable_types.First(); it.Good(); it.Inc()) { - syncer::ModelTypeSet type_to_set; - type_to_set.Put(it.Get()); - std::string args = - GetConfiguration(NULL, CHOOSE_WHAT_TO_SYNC, type_to_set, std::string(), - ENCRYPT_PASSWORDS, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, - OnUserChoseDatatypes(false, ModelTypeSetMatches(type_to_set))); - handler_->HandleConfigure(&list_args); - - ExpectDone(); - Mock::VerifyAndClearExpectations(mock_pss_); - web_ui_.ClearTrackedCalls(); - } -} - -TEST_F(SyncSetupHandlerTest, TestSyncAllManually) { - std::string args = - GetConfiguration(NULL, CHOOSE_WHAT_TO_SYNC, GetAllTypes(), std::string(), - ENCRYPT_PASSWORDS, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, - OnUserChoseDatatypes(false, ModelTypeSetMatches(GetAllTypes()))); - handler_->HandleConfigure(&list_args); - - ExpectDone(); -} - -TEST_F(SyncSetupHandlerTest, ShowSyncSetup) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - // This should display the sync setup dialog (not login). - SetDefaultExpectationsForConfigPage(); - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); -} - -// We do not display signin on chromeos in the case of auth error. -TEST_F(SyncSetupHandlerTest, ShowSigninOnAuthError) { - // Initialize the system to a signed in state, but with an auth error. - error_ = GoogleServiceAuthError( - GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); - - SetupInitializedProfileSyncService(); - mock_signin_->SetAuthenticatedAccountInfo(kTestUser, kTestUser); - FakeAuthStatusProvider provider( - SigninErrorControllerFactory::GetForProfile(profile_.get())); - provider.SetAuthError(kTestUser, error_); - EXPECT_CALL(*mock_pss_, CanSyncStart()).WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); - -#if defined(OS_CHROMEOS) - // On ChromeOS, auth errors are ignored - instead we just try to start the - // sync engine (which will fail due to the auth error). This should only - // happen if the user manually navigates to chrome://settings/syncSetup - - // clicking on the button in the UI will sign the user out rather than - // displaying a spinner. Should be no visible UI on ChromeOS in this case. - EXPECT_EQ(NULL, LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); -#else - - // On ChromeOS, this should display the spinner while we try to startup the - // sync engine, and on desktop this displays the login dialog. - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - // Sync setup is closed when re-auth is in progress. - EXPECT_EQ(NULL, - LoginUIServiceFactory::GetForProfile( - profile_.get())->current_login_ui()); - - ASSERT_FALSE(handler_->is_configuring_sync()); -#endif -} - -TEST_F(SyncSetupHandlerTest, ShowSetupSyncEverything) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - SetDefaultExpectationsForConfigPage(); - // This should display the sync setup dialog (not login). - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckBool(dictionary, "syncAllDataTypes", true); - CheckBool(dictionary, "appsRegistered", true); - CheckBool(dictionary, "autofillRegistered", true); - CheckBool(dictionary, "bookmarksRegistered", true); - CheckBool(dictionary, "extensionsRegistered", true); - CheckBool(dictionary, "passwordsRegistered", true); - CheckBool(dictionary, "preferencesRegistered", true); - CheckBool(dictionary, "tabsRegistered", true); - CheckBool(dictionary, "themesRegistered", true); - CheckBool(dictionary, "typedUrlsRegistered", true); - CheckBool(dictionary, "paymentsIntegrationEnabled", true); - CheckBool(dictionary, "showPassphrase", false); - CheckBool(dictionary, "usePassphrase", false); - CheckBool(dictionary, "passphraseFailed", false); - CheckBool(dictionary, "encryptAllData", false); - CheckConfigDataTypeArguments(dictionary, SYNC_ALL_DATA, GetAllTypes()); -} - -TEST_F(SyncSetupHandlerTest, ShowSetupManuallySyncAll) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - syncer::SyncPrefs sync_prefs(profile_->GetPrefs()); - sync_prefs.SetKeepEverythingSynced(false); - SetDefaultExpectationsForConfigPage(); - // This should display the sync setup dialog (not login). - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, GetAllTypes()); -} - -TEST_F(SyncSetupHandlerTest, ShowSetupSyncForAllTypesIndividually) { - syncer::ModelTypeSet user_selectable_types = GetAllTypes(); - syncer::ModelTypeSet::Iterator it; - for (it = user_selectable_types.First(); it.Good(); it.Inc()) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - syncer::SyncPrefs sync_prefs(profile_->GetPrefs()); - sync_prefs.SetKeepEverythingSynced(false); - SetDefaultExpectationsForConfigPage(); - syncer::ModelTypeSet types; - types.Put(it.Get()); - EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()). - WillRepeatedly(Return(types)); - - // This should display the sync setup dialog (not login). - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); - // Close the config overlay. - LoginUIServiceFactory::GetForProfile(profile_.get())->LoginUIClosed( - handler_.get()); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, types); - Mock::VerifyAndClearExpectations(mock_pss_); - // Clean up so we can loop back to display the dialog again. - web_ui_.ClearTrackedCalls(); - } -} - -TEST_F(SyncSetupHandlerTest, ShowSetupGaiaPassphraseRequired) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - SetDefaultExpectationsForConfigPage(); - - // This should display the sync setup dialog (not login). - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckBool(dictionary, "showPassphrase", true); - CheckBool(dictionary, "usePassphrase", false); - CheckBool(dictionary, "passphraseFailed", false); -} - -TEST_F(SyncSetupHandlerTest, ShowSetupCustomPassphraseRequired) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, GetPassphraseType()) - .WillRepeatedly(Return(syncer::PassphraseType::CUSTOM_PASSPHRASE)); - SetupInitializedProfileSyncService(); - SetDefaultExpectationsForConfigPage(); - - // This should display the sync setup dialog (not login). - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckBool(dictionary, "showPassphrase", true); - CheckBool(dictionary, "usePassphrase", true); - CheckBool(dictionary, "passphraseFailed", false); -} - -TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAll) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - SetDefaultExpectationsForConfigPage(); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingEnabled()) - .WillRepeatedly(Return(true)); - - // This should display the sync setup dialog (not login). - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckBool(dictionary, "encryptAllData", true); -} - -TEST_F(SyncSetupHandlerTest, ShowSetupEncryptAllDisallowed) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - SetDefaultExpectationsForConfigPage(); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed()) - .WillRepeatedly(Return(false)); - - // This should display the sync setup dialog (not login). - handler_->OpenSyncSetup(false /* creating_supervised_user */); - - ExpectConfig(); - const content::TestWebUI::CallData& data = *web_ui_.call_data()[0]; - const base::DictionaryValue* dictionary = nullptr; - ASSERT_TRUE(data.arg2()->GetAsDictionary(&dictionary)); - CheckBool(dictionary, "encryptAllData", false); - CheckBool(dictionary, "encryptAllDataAllowed", false); -} - -TEST_F(SyncSetupHandlerTest, TurnOnEncryptAllDisallowed) { - std::string args = - GetConfiguration(NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), - ENCRYPT_ALL_DATA, PAYMENTS_INTEGRATION_ENABLED); - base::ListValue list_args; - list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, EnableEncryptEverything()).Times(0); - EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _)); - handler_->HandleConfigure(&list_args); - - // Ensure that we navigated to the "done" state since we don't need a - // passphrase. - ExpectDone(); -}
diff --git a/chrome/browser/ui/webui/plural_string_handler.cc b/chrome/browser/ui/webui/plural_string_handler.cc new file mode 100644 index 0000000..4693d19 --- /dev/null +++ b/chrome/browser/ui/webui/plural_string_handler.cc
@@ -0,0 +1,45 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/plural_string_handler.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/values.h" +#include "content/public/browser/web_ui.h" +#include "ui/base/l10n/l10n_util.h" + +PluralStringHandler::PluralStringHandler() {} + +PluralStringHandler::~PluralStringHandler() {} + +void PluralStringHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "getPluralString", base::Bind(&PluralStringHandler::HandleGetPluralString, + base::Unretained(this))); +} + +void PluralStringHandler::AddLocalizedString(const std::string& name, int id) { + name_to_id_[name] = id; +} + +void PluralStringHandler::HandleGetPluralString(const base::ListValue* args) { + AllowJavascript(); + CHECK_EQ(3U, args->GetSize()); + const base::Value* callback_id; + CHECK(args->Get(0, &callback_id)); + + std::string message_name; + CHECK(args->GetString(1, &message_name)); + + int count; + CHECK(args->GetInteger(2, &count)); + + auto message_id_it = name_to_id_.find(message_name); + CHECK(name_to_id_.end() != message_id_it); + + ResolveJavascriptCallback(*callback_id, + base::Value(l10n_util::GetPluralStringFUTF8( + message_id_it->second, count))); +}
diff --git a/chrome/browser/ui/webui/plural_string_handler.h b/chrome/browser/ui/webui/plural_string_handler.h new file mode 100644 index 0000000..c953524 --- /dev/null +++ b/chrome/browser/ui/webui/plural_string_handler.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_PLURAL_STRING_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_PLURAL_STRING_HANDLER_H_ + +#include "base/macros.h" +#include "content/public/browser/web_ui_message_handler.h" + +// A handler which provides pluralized strings. +class PluralStringHandler : public content::WebUIMessageHandler { + public: + PluralStringHandler(); + ~PluralStringHandler() override; + + void AddLocalizedString(const std::string& name, int id); + + // WebUIMessageHandler: + void RegisterMessages() override; + + private: + void HandleGetPluralString(const base::ListValue* args); + + std::map<std::string, int> name_to_id_; + + DISALLOW_COPY_AND_ASSIGN(PluralStringHandler); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_PLURAL_STRING_HANDLER_H_
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 2222d7e79..b1a7c44 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -611,6 +611,7 @@ "//base/third_party/dynamic_annotations", "//components/bookmarks/common", "//components/nacl/common:switches", + "//components/offline_pages/features", "//media:cdm_paths", # Needed by chrome_paths.cc. "//media:media_features", "//ppapi/features",
diff --git a/chrome/common/DEPS b/chrome/common/DEPS index bc3c673..63fb8e2 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS
@@ -19,7 +19,7 @@ "+components/metrics/metrics_pref_names.h", "+components/nacl/common", "+components/ntp_tiles", - "+components/offline_pages/offline_page_feature.h", + "+components/offline_pages/features", "+components/password_manager/core/common", "+components/policy/core/common", "+components/printing/common",
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 7b2eb7f..15adf88 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2556,4 +2556,8 @@ const char kClipboardLastModifiedTime[] = "ui.clipboard.last_modified_time"; #endif +#if BUILDFLAG(ENABLE_OFFLINE_PAGES) +const char kOfflinePrefetchBackoff[] = "offline_prefetch.backoff"; +#endif + } // namespace prefs
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index d6b5718..8343198 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -11,6 +11,7 @@ #include "build/build_config.h" #include "chrome/common/features.h" +#include "components/offline_pages/features/features.h" #include "extensions/features/features.h" #include "media/media_features.h" #include "ppapi/features/features.h" @@ -921,6 +922,10 @@ extern const char kClipboardLastModifiedTime[]; #endif +#if BUILDFLAG(ENABLE_OFFLINE_PAGES) +extern const char kOfflinePrefetchBackoff[]; +#endif + } // namespace prefs #endif // CHROME_COMMON_PREF_NAMES_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 07f4346..99331b11 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1714,12 +1714,6 @@ "../browser/ui/webui/net_internals/net_internals_ui_browsertest.cc", "../browser/ui/webui/net_internals/net_internals_ui_browsertest.h", "../browser/ui/webui/ntp/new_tab_ui_browsertest.cc", - "../browser/ui/webui/options/multilanguage_options_browsertest.cc", - "../browser/ui/webui/options/multilanguage_options_browsertest.h", - "../browser/ui/webui/options/options_browsertest.cc", - "../browser/ui/webui/options/options_browsertest.h", - "../browser/ui/webui/options/preferences_browsertest.cc", - "../browser/ui/webui/options/preferences_browsertest.h", "../browser/ui/webui/password_manager_internals/password_manager_internals_ui_browsertest.cc", "../browser/ui/webui/policy_ui_browsertest.cc", "../browser/ui/webui/prefs_internals_browsertest.cc", @@ -2275,8 +2269,6 @@ "../browser/ui/views/arc_app_dialog_view_browsertest.cc", "../browser/ui/views/frame/browser_frame_ash_browsertest.cc", "../browser/ui/webui/chromeos/keyboard_overlay_ui_browsertest.cc", - "../browser/ui/webui/options/chromeos/accounts_options_browsertest.cc", - "../browser/ui/webui/options/chromeos/shared_options_browsertest.cc", ] sources -= [ "../../apps/load_and_launch_browsertest.cc", @@ -3644,12 +3636,6 @@ "../browser/ui/webui/help/version_updater_chromeos_unittest.cc", "../browser/ui/webui/md_downloads/downloads_list_tracker_unittest.cc", "../browser/ui/webui/md_downloads/md_downloads_dom_handler_unittest.cc", - "../browser/ui/webui/options/autofill_options_handler_unittest.cc", - "../browser/ui/webui/options/font_settings_utils_unittest.cc", - "../browser/ui/webui/options/language_options_handler_unittest.cc", - "../browser/ui/webui/options/password_manager_handler_unittest.cc", - "../browser/ui/webui/options/pepper_flash_content_settings_utils_unittest.cc", - "../browser/ui/webui/options/sync_setup_handler_unittest.cc", "../browser/ui/webui/settings/downloads_handler_unittest.cc", "../browser/ui/webui/settings/md_settings_ui_unittest.cc", "../browser/ui/webui/settings/metrics_reporting_handler_unittest.cc",
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 7e1fb87..aae34597 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -42,29 +42,6 @@ "../../../browser/ui/webui/extensions/extension_settings_browsertest.js", "../../../browser/ui/webui/help/help_browsertest.js", "../../../browser/ui/webui/identity_internals_ui_browsertest.js", - "../../../browser/ui/webui/options/autofill_options_browsertest.js", - "../../../browser/ui/webui/options/browser_options_browsertest.js", - "../../../browser/ui/webui/options/certificate_manager_browsertest.js", - "../../../browser/ui/webui/options/chromeos/accounts_options_browsertest.js", - "../../../browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js", - "../../../browser/ui/webui/options/chromeos/date_time_options_browsertest.js", - "../../../browser/ui/webui/options/chromeos/power_overlay_browsertest.js", - "../../../browser/ui/webui/options/content_options_browsertest.js", - "../../../browser/ui/webui/options/content_settings_exception_area_browsertest.js", - "../../../browser/ui/webui/options/cookies_view_browsertest.js", - "../../../browser/ui/webui/options/edit_dictionary_browsertest.js", - "../../../browser/ui/webui/options/font_settings_browsertest.js", - "../../../browser/ui/webui/options/language_options_browsertest.js", - "../../../browser/ui/webui/options/language_options_dictionary_download_browsertest.js", - "../../../browser/ui/webui/options/manage_profile_browsertest.js", - "../../../browser/ui/webui/options/multilanguage_options_webui_browsertest.js", - "../../../browser/ui/webui/options/options_browsertest.js", - "../../../browser/ui/webui/options/options_browsertest_base.js", - "../../../browser/ui/webui/options/password_manager_browsertest.js", - "../../../browser/ui/webui/options/profile_settings_reset_browsertest.js", - "../../../browser/ui/webui/options/search_engine_manager_browsertest.js", - "../../../browser/ui/webui/options/settings_format_browsertest.js", - "../../../browser/ui/webui/options/startup_page_list_browsertest.js", "../../../browser/ui/webui/sync_internals_browsertest.js", "../../../browser/ui/webui/sync_setup_browsertest.js", "../chromeos/oobe_webui_browsertest.js", @@ -130,18 +107,6 @@ } else { sources -= [ "md_user_manager/user_manager_browsertest.js" ] } - if (is_mac) { - sources -= [ - # TODO(rouslan): This test depends on the custom dictionary UI, - # which is disabled on Mac. - "../../../browser/ui/webui/options/edit_dictionary_browsertest.js", - - # TODO(rouslan): This test depends on hunspell and we cannot run it - # on Mac, which does not use hunspell by default. - "../../../browser/ui/webui/options/language_options_dictionary_download_browsertest.js", - "../../../browser/ui/webui/options/multilanguage_options_webui_browsertest.js", - ] - } if (!enable_app_list) { sources -= [ "../../../browser/ui/webui/app_list/start_page_browsertest.js" ]
diff --git a/chrome/test/data/webui/inline_editable_list_test.html b/chrome/test/data/webui/inline_editable_list_test.html deleted file mode 100644 index fe1181d..0000000 --- a/chrome/test/data/webui/inline_editable_list_test.html +++ /dev/null
@@ -1,152 +0,0 @@ -<!DOCTYPE html> -<html> -<body> - -<script> - -function setUp() { - loadTimeData.data = { - 'deletableItemDeleteButtonTitle': 'test_deletable_button_title' - }; - - cr.define('options', function() { - /** @const */ var InlineEditableItemList = options.InlineEditableItemList; - /** @const */ var InlineEditableItem = options.InlineEditableItem; - - /** - * Creates a test list item. - * @param {string} name This item's name. - * @constructor - * @extends {options.InlineEditableItem} - */ - function TestItem(name) { - var el = cr.doc.createElement('div'); - el.name_ = name; - TestItem.decorate(el); - return el; - } - - /** - * Decorates an element as a test list item. - * @param {!HTMLElement} el The element to decorate. - */ - TestItem.decorate = function(el) { - el.__proto__ = TestItem.prototype; - el.decorate(); - }; - - TestItem.prototype = { - __proto__: InlineEditableItem.prototype, - - /** - * Item name. Used to set the item's text fields. - * @type {string} - * @private - */ - name_: null, - - /** @override */ - decorate: function() { - InlineEditableItem.prototype.decorate.call(this); - - var fieldEl = this.createEditableTextCell(this.name_); - this.contentElement.appendChild(fieldEl); - - fieldEl = this.createEditableTextCell(this.name_ + '_two'); - this.contentElement.appendChild(fieldEl); - }, - }; - - /** - * @constructor - * @extends {options.InlineEditableItemList} - */ - var TestItemList = cr.ui.define('list'); - - TestItemList.prototype = { - __proto__: InlineEditableItemList.prototype, - - /** - * @override - * @param {string} name - */ - createItem: function(name) { - return new TestItem(name); - }, - - /** - * @param {!Element} el - * @return {boolean} True if |el| or any of its children are focusable. - * @private - */ - hasFocusableElement_: function(el) { - return el.querySelectorAll('[tabindex="0"]').length > 0; - }, - - /** - * @param {number} itemIndex - * @return {boolean} True if item at |itemIndex| has a focusable element - * and no other items have focusable elements. - */ - hasExactlyOneItemFocusable: function(itemIndex) { - var length = this.items.length; - for(var i = 0; i < length; ++i) { - if (this.hasFocusableElement_(this.items[i]) != (i == itemIndex)) - return false; - } - return true; - }, - }; - - // Export. - return { - TestItemList: TestItemList - }; - - }) -} - -/** - * @param {!EventTarget} target Where to send the event. - * @param {!string} key Which key to send. - */ -function sendKeyDownEvent(target, key) { - var event = new KeyboardEvent('keydown', - {bubbles: true, cancelable: true, key: key}); - target.dispatchEvent(event); -} - -/** - * Test that exactly one item in the list is focusable after navigating the - * list using up and down arrow keys. - */ -function testUpDownFocus() { - var list = document.createElement('ul'); - list.style.position = 'absolute'; - list.style.width = '800px'; - list.style.height = '800px'; - options.TestItemList.decorate(list); - document.body.appendChild(list); - - var model = new cr.ui.ArrayDataModel(['itemA', 'itemB', 'itemC']); - list.dataModel = model; - list.selectionModel.setIndexSelected(0, true); - list.selectionModel.leadIndex = 0; - - assertTrue(list.hasExactlyOneItemFocusable(0)); - sendKeyDownEvent(list, 'ArrowDown'); - assertTrue(list.hasExactlyOneItemFocusable(1)); - sendKeyDownEvent(list, 'ArrowDown'); - assertTrue(list.hasExactlyOneItemFocusable(2)); - sendKeyDownEvent(list, 'ArrowUp'); - assertTrue(list.hasExactlyOneItemFocusable(1)); - sendKeyDownEvent(list, 'ArrowUp'); - assertTrue(list.hasExactlyOneItemFocusable(0)); - sendKeyDownEvent(list, 'ArrowDown'); - assertTrue(list.hasExactlyOneItemFocusable(1)); -} - -</script> - -</body> -</html>
diff --git a/chrome/test/data/webui/md_bookmarks/command_manager_test.js b/chrome/test/data/webui/md_bookmarks/command_manager_test.js index 2eab6fea..a616a69 100644 --- a/chrome/test/data/webui/md_bookmarks/command_manager_test.js +++ b/chrome/test/data/webui/md_bookmarks/command_manager_test.js
@@ -43,6 +43,8 @@ commandManager = new TestCommandManager(); replaceBody(commandManager); + document.body.appendChild( + document.createElement('bookmarks-toast-manager')); Polymer.dom.flush(); });
diff --git a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js index 7b89786..524b1be 100644 --- a/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js +++ b/chrome/test/data/webui/md_bookmarks/md_bookmarks_browsertest.js
@@ -172,6 +172,20 @@ mocha.run(); }); +function MaterialBookmarksToastManagerTest() {} + +MaterialBookmarksToastManagerTest.prototype = { + __proto__: MaterialBookmarksBrowserTest.prototype, + + extraLibraries: MaterialBookmarksBrowserTest.prototype.extraLibraries.concat([ + 'toast_manager_test.js', + ]), +}; + +TEST_F('MaterialBookmarksToastManagerTest', 'All', function() { + mocha.run(); +}); + function MaterialBookmarksPolicyTest() {} MaterialBookmarksPolicyTest.prototype = {
diff --git a/chrome/test/data/webui/md_bookmarks/md_bookmarks_focus_test.js b/chrome/test/data/webui/md_bookmarks/md_bookmarks_focus_test.js index f19ebf5..5c186542 100644 --- a/chrome/test/data/webui/md_bookmarks/md_bookmarks_focus_test.js +++ b/chrome/test/data/webui/md_bookmarks/md_bookmarks_focus_test.js
@@ -280,14 +280,16 @@ }); test('shift selection', function() { - // TODO(calamity): Make the first item the anchor index when a new folder - // is selected. var focusedItem = items[0]; focusedItem.focus(); - keydown(focusedItem, 'ArrowDown'); + keydown(focusedItem, 'ArrowDown', 'shift'); focusedItem = items[1]; - assertDeepEquals(['3'], normalizeSet(store.data.selection.items)); + assertDeepEquals(['2', '3'], normalizeSet(store.data.selection.items)); + + keydown(focusedItem, 'Escape'); + focusedItem = items[1]; + assertDeepEquals([], normalizeSet(store.data.selection.items)); keydown(focusedItem, 'ArrowUp', 'shift'); focusedItem = items[0];
diff --git a/chrome/test/data/webui/md_bookmarks/toast_manager_test.js b/chrome/test/data/webui/md_bookmarks/toast_manager_test.js new file mode 100644 index 0000000..8830c8b2 --- /dev/null +++ b/chrome/test/data/webui/md_bookmarks/toast_manager_test.js
@@ -0,0 +1,59 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +suite('<bookmarks-toast-manager>', function() { + var toastManager; + var store; + + setup(function() { + toastManager = document.createElement('bookmarks-toast-manager'); + replaceBody(toastManager); + }); + + test('simple show/hide', function() { + toastManager.show('test', false); + assertTrue(toastManager.open_); + assertEquals('test', toastManager.$.content.textContent); + assertTrue(toastManager.$$('paper-button').hidden); + + toastManager.hide(); + assertFalse(toastManager.open_); + + toastManager.show('test', true); + assertFalse(toastManager.$$('paper-button').hidden); + }); + + test('auto hide', function() { + toastManager.duration = 100; + + var timeoutFunc = null; + var timeoutCounter = 0; + var clearedTimeout = null; + toastManager.setTimeout_ = function(f) { + timeoutFunc = f; + return timeoutCounter++; + }; + toastManager.clearTimeout_ = function(n) { + clearedTimeout = n; + }; + + toastManager.show('test', false); + assertEquals(0, toastManager.hideTimeout_); + assertTrue(toastManager.open_); + + timeoutFunc(); + assertEquals(null, toastManager.hideTimeout_); + assertFalse(toastManager.open_); + + // Check that multiple shows reset the timeout. + toastManager.show('test', false); + assertEquals(1, toastManager.hideTimeout_); + assertTrue(toastManager.open_); + + toastManager.show('test2', false); + assertEquals(1, clearedTimeout); + assertEquals(2, toastManager.hideTimeout_); + assertTrue(toastManager.open_); + }); +});
diff --git a/chrome/test/data/webui/webui_resource_browsertest.cc b/chrome/test/data/webui/webui_resource_browsertest.cc index 8ad1818..b83d4ed 100644 --- a/chrome/test/data/webui/webui_resource_browsertest.cc +++ b/chrome/test/data/webui/webui_resource_browsertest.cc
@@ -7,7 +7,6 @@ #include "base/path_service.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/grit/options_test_resources.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "chrome/test/data/grit/webui_test_resources.h" @@ -149,22 +148,6 @@ "list_single_selection_model_test.html"))); } -IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, InlineEditableListTest) { - AddLibrary(IDR_WEBUI_JS_CR); - AddLibrary(IDR_WEBUI_JS_CR_EVENT_TARGET); - AddLibrary(IDR_WEBUI_JS_CR_UI); - AddLibrary(IDR_WEBUI_JS_CR_UI_ARRAY_DATA_MODEL); - AddLibrary(IDR_WEBUI_JS_CR_UI_LIST_ITEM); - AddLibrary(IDR_WEBUI_JS_CR_UI_LIST_SELECTION_CONTROLLER); - AddLibrary(IDR_WEBUI_JS_CR_UI_LIST_SELECTION_MODEL); - AddLibrary(IDR_WEBUI_JS_CR_UI_LIST); - AddLibrary(IDR_WEBUI_JS_LOAD_TIME_DATA); - AddLibrary(IDR_OPTIONS_DELETABLE_ITEM_LIST); - AddLibrary(IDR_OPTIONS_INLINE_EDITABLE_LIST); - LoadFile(base::FilePath(FILE_PATH_LITERAL( - "inline_editable_list_test.html"))); -} - IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, MenuTest) { AddLibrary(IDR_WEBUI_JS_ASSERT); AddLibrary(IDR_WEBUI_JS_CR);
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java index bf85375..f78859a 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskScheduler.java
@@ -11,6 +11,7 @@ import org.chromium.base.Log; import org.chromium.base.ThreadUtils; +import org.chromium.base.VisibleForTesting; import java.lang.reflect.Constructor; import java.util.Set; @@ -60,7 +61,9 @@ private final BackgroundTaskSchedulerDelegate mSchedulerDelegate; - BackgroundTaskScheduler(BackgroundTaskSchedulerDelegate schedulerDelegate) { + /** Public constructor that allows null delegate, for testing only */ + @VisibleForTesting + public BackgroundTaskScheduler(BackgroundTaskSchedulerDelegate schedulerDelegate) { assert schedulerDelegate != null; mSchedulerDelegate = schedulerDelegate; }
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java index 87538f9..9ab0bee 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java
@@ -11,7 +11,7 @@ * system APIs ({@link android.app.job.JobScheduler} on newer platforms and GCM * ({@link com.google.android.gms.gcm.GcmNetworkManager}) on older platforms. */ -interface BackgroundTaskSchedulerDelegate { +public interface BackgroundTaskSchedulerDelegate { /** * Schedules a background task. See {@link TaskInfo} for information on what types of tasks that * can be scheduled.
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher.h b/components/offline_pages/core/prefetch/prefetch_dispatcher.h index b8d68de..37403f1a 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher.h
@@ -29,9 +29,9 @@ ScopedBackgroundTask() = default; virtual ~ScopedBackgroundTask() = default; - // Used on destruction to inform the system about whether rescheduling is - // required. - virtual void SetNeedsReschedule(bool reschedule) = 0; + // Used on destruction to inform the system about whether rescheduling with + // or without backoff is required. + virtual void SetNeedsReschedule(bool reschedule, bool backoff) = 0; }; virtual ~PrefetchDispatcher() = default; @@ -65,7 +65,10 @@ // Called when a task must stop immediately due to system constraints. After // this call completes, the system will reschedule the task based on whether // SetNeedsReschedule has been called. - virtual void StopBackgroundTask(ScopedBackgroundTask* task) = 0; + virtual void StopBackgroundTask() = 0; + + // Used by the test to signal the completion of the background task. + virtual void RequestFinishBackgroundTaskForTest() = 0; }; } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc index bad8687..5952f2b 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.cc
@@ -4,13 +4,23 @@ #include "components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h" +#include "base/bind.h" #include "base/memory/ptr_util.h" +#include "base/task_runner.h" +#include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/prefetch/add_unique_urls_task.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" #include "url/gurl.h" namespace offline_pages { +namespace { +void DeleteBackgroundTaskHelper( + std::unique_ptr<PrefetchDispatcher::ScopedBackgroundTask> task) { + task.reset(); +} +} // namespace + PrefetchDispatcherImpl::PrefetchDispatcherImpl() = default; PrefetchDispatcherImpl::~PrefetchDispatcherImpl() = default; @@ -39,11 +49,23 @@ void PrefetchDispatcherImpl::BeginBackgroundTask( std::unique_ptr<ScopedBackgroundTask> task) { - NOTIMPLEMENTED(); + task_ = std::move(task); } -void PrefetchDispatcherImpl::StopBackgroundTask(ScopedBackgroundTask* task) { - NOTIMPLEMENTED(); +void PrefetchDispatcherImpl::StopBackgroundTask() { + DisposeTask(); +} + +void PrefetchDispatcherImpl::RequestFinishBackgroundTaskForTest() { + DisposeTask(); +} + +void PrefetchDispatcherImpl::DisposeTask() { + DCHECK(task_); + // Delay the deletion till the caller finishes. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&DeleteBackgroundTaskHelper, base::Passed(std::move(task_)))); } } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h index 3764a5b..d303dcf 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl.h
@@ -26,13 +26,17 @@ void RemoveAllUnprocessedPrefetchURLs(const std::string& name_space) override; void RemovePrefetchURLsByClientId(const ClientId& client_id) override; void BeginBackgroundTask(std::unique_ptr<ScopedBackgroundTask> task) override; - void StopBackgroundTask(ScopedBackgroundTask* task) override; + void StopBackgroundTask() override; + void RequestFinishBackgroundTaskForTest() override; private: friend class PrefetchDispatcherTest; + void DisposeTask(); + PrefetchService* service_; TaskQueue task_queue_; + std::unique_ptr<ScopedBackgroundTask> task_; DISALLOW_COPY_AND_ASSIGN(PrefetchDispatcherImpl); };
diff --git a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc index 6ed4c1b..de04af6 100644 --- a/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc +++ b/components/offline_pages/core/prefetch/suggested_articles_observer_unittest.cc
@@ -55,7 +55,8 @@ void BeginBackgroundTask( std::unique_ptr<ScopedBackgroundTask> task) override {} - void StopBackgroundTask(ScopedBackgroundTask* task) override {} + void StopBackgroundTask() override {} + void RequestFinishBackgroundTaskForTest() override {} std::vector<PrefetchURL> latest_prefetch_urls; ClientId last_removed_client_id;
diff --git a/components/translate/ios/browser/ios_translate_driver.h b/components/translate/ios/browser/ios_translate_driver.h index e9c0f08..7043de1 100644 --- a/components/translate/ios/browser/ios_translate_driver.h +++ b/components/translate/ios/browser/ios_translate_driver.h
@@ -25,6 +25,7 @@ namespace translate { class TranslateManager; +class LanguageModel; // Content implementation of TranslateDriver. class IOSTranslateDriver : public TranslateDriver, @@ -33,7 +34,8 @@ public: IOSTranslateDriver(web::WebState* web_state, web::NavigationManager* navigation_manager, - TranslateManager* translate_manager); + TranslateManager* translate_manager, + LanguageModel* language_model); ~IOSTranslateDriver() override; LanguageDetectionController* language_detection_controller() { @@ -98,6 +100,9 @@ // The navigation manager of the tab we are associated with. web::NavigationManager* navigation_manager_; + // Model to be notified about detected language of every page visited. + translate::LanguageModel* language_model_; + base::WeakPtr<TranslateManager> translate_manager_; std::unique_ptr<TranslateController> translate_controller_; std::unique_ptr<LanguageDetectionController> language_detection_controller_;
diff --git a/components/translate/ios/browser/ios_translate_driver.mm b/components/translate/ios/browser/ios_translate_driver.mm index dc5a9203..e2d79467 100644 --- a/components/translate/ios/browser/ios_translate_driver.mm +++ b/components/translate/ios/browser/ios_translate_driver.mm
@@ -9,6 +9,7 @@ #include "base/strings/sys_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "components/translate/core/browser/language_model.h" #include "components/translate/core/browser/translate_client.h" #include "components/translate/core/browser/translate_manager.h" #include "components/translate/core/common/translate_constants.h" @@ -49,9 +50,11 @@ IOSTranslateDriver::IOSTranslateDriver( web::WebState* web_state, web::NavigationManager* navigation_manager, - TranslateManager* translate_manager) + TranslateManager* translate_manager, + LanguageModel* language_model) : web::WebStateObserver(web_state), navigation_manager_(navigation_manager), + language_model_(language_model), translate_manager_(translate_manager->GetWeakPtr()), page_seq_no_(0), pending_page_seq_no_(0), @@ -92,6 +95,11 @@ translate_manager_->GetLanguageState().LanguageDetermined( details.adopted_language, true); + // Update language model. + if (language_model_ && details.is_cld_reliable) { + language_model_->OnPageVisited(details.cld_language); + } + if (web_state()) translate_manager_->InitiateTranslation(details.adopted_language); }
diff --git a/components/translate/ios/browser/language_detection_controller.h b/components/translate/ios/browser/language_detection_controller.h index c3271e82..f4c3936 100644 --- a/components/translate/ios/browser/language_detection_controller.h +++ b/components/translate/ios/browser/language_detection_controller.h
@@ -34,7 +34,14 @@ class LanguageDetectionController : public web::WebStateObserver { public: // Language detection details, passed to language detection callbacks. + // TODO(crbug.com/715447): Investigate if we can use the existing + // detection_details under + // components/translate/core/common/language_detection_details.h. struct DetectionDetails { + DetectionDetails(); + DetectionDetails(const DetectionDetails& other); + ~DetectionDetails(); + // The language detected by the content (Content-Language). std::string content_language; @@ -43,6 +50,12 @@ // The adopted language. std::string adopted_language; + + // The language detected by CLD. + std::string cld_language; + + // Whether the CLD detection is reliable or not. + bool is_cld_reliable; }; LanguageDetectionController(web::WebState* web_state,
diff --git a/components/translate/ios/browser/language_detection_controller.mm b/components/translate/ios/browser/language_detection_controller.mm index 4c23553..642377ae 100644 --- a/components/translate/ios/browser/language_detection_controller.mm +++ b/components/translate/ios/browser/language_detection_controller.mm
@@ -52,6 +52,14 @@ LanguageDetectionController::~LanguageDetectionController() { } +LanguageDetectionController::DetectionDetails::DetectionDetails() + : is_cld_reliable(false) {} + +LanguageDetectionController::DetectionDetails::DetectionDetails( + const DetectionDetails& other) = default; + +LanguageDetectionController::DetectionDetails::~DetectionDetails() = default; + std::unique_ptr<LanguageDetectionController::CallbackList::Subscription> LanguageDetectionController::RegisterLanguageDetectionCallback( const Callback& callback) { @@ -115,11 +123,13 @@ const std::string& http_content_language, const std::string& html_lang, const base::string16& text_content) { + std::string cld_language; + bool is_cld_reliable; std::string language = translate::DeterminePageLanguage( http_content_language, html_lang, GetStringByClippingLastWord(text_content, language_detection::kMaxIndexChars), - nullptr /* cld_language */, nullptr /* is_cld_reliable */); + &cld_language, &is_cld_reliable); if (language.empty()) return; // No language detected. @@ -127,6 +137,8 @@ details.content_language = http_content_language; details.html_root_language = html_lang; details.adopted_language = language; + details.cld_language = cld_language; + details.is_cld_reliable = is_cld_reliable; language_detection_callbacks_.Notify(details); }
diff --git a/components/translate/ios/browser/language_detection_controller_unittest.mm b/components/translate/ios/browser/language_detection_controller_unittest.mm index 0593ba8..c74861b4 100644 --- a/components/translate/ios/browser/language_detection_controller_unittest.mm +++ b/components/translate/ios/browser/language_detection_controller_unittest.mm
@@ -59,6 +59,7 @@ TEST_F(LanguageDetectionControllerTest, OnTextCaptured) { const std::string kRootLanguage("en"); const std::string kContentLanguage("fr"); + const std::string kUndefined("und"); __block bool block_was_called = false; auto subscription = @@ -67,6 +68,8 @@ block_was_called = true; EXPECT_EQ(kRootLanguage, details.html_root_language); EXPECT_EQ(kContentLanguage, details.content_language); + EXPECT_FALSE(details.is_cld_reliable); + EXPECT_EQ(kUndefined, details.cld_language); })); base::DictionaryValue command;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index a249d77f..b16b295c 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1595,12 +1595,6 @@ "tracing/power_tracing_agent.h", ] } - if (is_chromeos) { - sources += [ - "tracing/arc_tracing_agent.cc", - "tracing/arc_tracing_agent.h", - ] - } if (enable_webrtc) { sources += [
diff --git a/content/browser/blob_storage/blob_url_loader_factory.cc b/content/browser/blob_storage/blob_url_loader_factory.cc index 8267654e..1dbcb19 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.cc +++ b/content/browser/blob_storage/blob_url_loader_factory.cc
@@ -359,15 +359,12 @@ std::move(blob_storage_context_getter))); } -mojom::URLLoaderFactoryPtr BlobURLLoaderFactory::CreateFactory() { +void BlobURLLoaderFactory::HandleRequest( + mojom::URLLoaderFactoryRequest request) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - mojom::URLLoaderFactoryPtr factory; - mojom::URLLoaderFactoryRequest request = mojo::MakeRequest(&factory); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::BindOnce(&BlobURLLoaderFactory::BindOnIO, this, std::move(request))); - - return factory; } BlobURLLoaderFactory::~BlobURLLoaderFactory() {}
diff --git a/content/browser/blob_storage/blob_url_loader_factory.h b/content/browser/blob_storage/blob_url_loader_factory.h index cea4f06..edfa7f3 100644 --- a/content/browser/blob_storage/blob_url_loader_factory.h +++ b/content/browser/blob_storage/blob_url_loader_factory.h
@@ -35,7 +35,7 @@ // Creates a URLLoaderFactory interface pointer for serving blob requests. // Called on the UI thread. - mojom::URLLoaderFactoryPtr CreateFactory(); + void HandleRequest(mojom::URLLoaderFactoryRequest request); // mojom::URLLoaderFactory implementation: void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest loader,
diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc index 2b37721a..b557e43 100644 --- a/content/browser/loader/navigation_url_loader_network_service.cc +++ b/content/browser/loader/navigation_url_loader_network_service.cc
@@ -59,11 +59,10 @@ // Kept around during the lifetime of the navigation request, and is // responsible for dispatching a ResourceRequest to the appropriate -// URLLoaderFactory. In order to get the right URLLoaderFactory it -// builds a vector of URLLoaderRequestHandler's and successively calls -// MaybeCreateLoaderFactory on each until the request is successfully -// handled. The same sequence may be performed multiple times when -// redirects happen. +// URLLoader. In order to get the right URLLoader it builds a vector +// of URLLoaderRequestHandler's and successively calls MaybeCreateLoader +// on each until the request is successfully handled. The same sequence +// may be performed multiple times when redirects happen. class NavigationURLLoaderNetworkService::URLLoaderRequestController { public: URLLoaderRequestController( @@ -143,35 +142,38 @@ url_loader_request_ = std::move(url_loader_request); url_loader_client_ptr_ = std::move(url_loader_client_ptr); handler_index_ = 0; - MaybeStartLoader(nullptr); + MaybeStartLoader(StartLoaderCallback()); } - void MaybeStartLoader(mojom::URLLoaderFactory* factory) { + void MaybeStartLoader(StartLoaderCallback start_loader_callback) { DCHECK(url_loader_client_ptr_.is_bound()); - if (factory) { - factory->CreateLoaderAndStart( - std::move(url_loader_request_), 0 /* routing_id? */, - 0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo, - *resource_request_, std::move(url_loader_client_ptr_)); + if (start_loader_callback) { + std::move(start_loader_callback) + .Run(std::move(url_loader_request_), + std::move(url_loader_client_ptr_)); return; } if (handler_index_ < handlers_.size()) { - handlers_[handler_index_++]->MaybeCreateLoaderFactory( + handlers_[handler_index_++]->MaybeCreateLoader( *resource_request_, resource_context_, base::BindOnce(&URLLoaderRequestController::MaybeStartLoader, base::Unretained(this))); return; } + mojom::URLLoaderFactory* factory = nullptr; DCHECK_EQ(handlers_.size(), handler_index_); if (resource_request_->url.SchemeIs(url::kBlobScheme)) { factory = url_loader_factory_getter_->GetBlobFactory()->get(); } else { factory = url_loader_factory_getter_->GetNetworkFactory()->get(); } - MaybeStartLoader(factory); + factory->CreateLoaderAndStart( + std::move(url_loader_request_), 0 /* routing_id? */, + 0 /* request_id? */, mojom::kURLLoadOptionSendSSLInfo, + *resource_request_, std::move(url_loader_client_ptr_)); } private:
diff --git a/content/browser/loader/url_loader_request_handler.h b/content/browser/loader/url_loader_request_handler.h index f72cc2a..d2b4684 100644 --- a/content/browser/loader/url_loader_request_handler.h +++ b/content/browser/loader/url_loader_request_handler.h
@@ -5,17 +5,21 @@ #ifndef CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_ #define CONTENT_BROWSER_LOADER_URL_LOADER_REQUEST_HANDLER_H_ +#include <memory> #include "base/callback_forward.h" #include "base/macros.h" -#include "content/common/url_loader_factory.mojom.h" +#include "content/common/url_loader.mojom.h" namespace content { class ResourceContext; struct ResourceRequest; -using LoaderFactoryCallback = - base::OnceCallback<void(mojom::URLLoaderFactory*)>; +using StartLoaderCallback = + base::OnceCallback<void(mojom::URLLoaderAssociatedRequest request, + mojom::URLLoaderClientPtr client)>; + +using LoaderCallback = base::OnceCallback<void(StartLoaderCallback)>; // An instance of this class is a per-request object and kept around during // the lifetime of a request (including multiple redirect legs) on IO thread. @@ -24,21 +28,11 @@ URLLoaderRequestHandler() = default; virtual ~URLLoaderRequestHandler() = default; - // Calls |callback| with non-null factory if this handler can handle - // the request, calls it with nullptr otherwise. - // Some implementation notes: - // 1) The returned pointer needs to be valid only until a single - // CreateLoaderAndStart call is made, and it is okay to do CHECK(false) for - // any subsequent calls. - // 2) The implementor is not supposed to set up and return URLLoaderFactory - // until it finds out that the handler is really going to handle the - // request. (For example ServiceWorker's request handler would not need to - // call the callback until it gets response from SW, and it may still - // call the callback with nullptr if it turns out that it needs to fallback - // to the network.) - virtual void MaybeCreateLoaderFactory(const ResourceRequest& resource_request, - ResourceContext* resource_context, - LoaderFactoryCallback callback) = 0; + // Calls |callback| with a non-null StartLoaderCallback if this handler + // can handle the request, calls it with null callback otherwise. + virtual void MaybeCreateLoader(const ResourceRequest& resource_request, + ResourceContext* resource_context, + LoaderCallback callback) = 0; }; } // 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 5dc4d9f..7c98454 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -61,6 +61,7 @@ #include "content/browser/background_sync/background_sync_service_impl.h" #include "content/browser/bad_message.h" #include "content/browser/blob_storage/blob_dispatcher_host.h" +#include "content/browser/blob_storage/blob_url_loader_factory.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/broadcast_channel/broadcast_channel_provider.h" #include "content/browser/browser_child_process_host_impl.h" @@ -948,6 +949,7 @@ never_signaled_(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED), #endif + renderer_host_binding_(this), instance_weak_factory_( new base::WeakPtrFactory<RenderProcessHostImpl>(this)), frame_sink_provider_(id_), @@ -1563,6 +1565,10 @@ ->AddInterface(base::Bind(&RenderProcessHostImpl::BindRouteProvider, base::Unretained(this))); + AddUIThreadInterface(registry.get(), + base::Bind(&RenderProcessHostImpl::CreateRendererHost, + base::Unretained(this))); + if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableNetworkService)) { AddUIThreadInterface( @@ -1606,6 +1612,17 @@ listener->OnAssociatedInterfaceRequest(name, request.PassHandle()); } +void RenderProcessHostImpl::GetBlobURLLoaderFactory( + mojom::URLLoaderFactoryRequest request) { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNetworkService)) { + NOTREACHED(); + return; + } + storage_partition_impl_->GetBlobURLLoaderFactory()->HandleRequest( + std::move(request)); +} + void RenderProcessHostImpl::CreateMusGpuRequest( const service_manager::BindSourceInfo& source_info, ui::mojom::GpuRequest request) { @@ -1643,6 +1660,12 @@ } } +void RenderProcessHostImpl::CreateRendererHost( + const service_manager::BindSourceInfo& source_info, + mojom::RendererHostRequest request) { + renderer_host_binding_.Bind(std::move(request)); +} + void RenderProcessHostImpl::CreateURLLoaderFactory( const service_manager::BindSourceInfo& source_info, mojom::URLLoaderFactoryRequest request) {
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index 871a6e8..9690094 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -33,6 +33,7 @@ #include "content/common/indexed_db/indexed_db.mojom.h" #include "content/common/media/renderer_audio_output_stream_factory.mojom.h" #include "content/common/renderer.mojom.h" +#include "content/common/renderer_host.mojom.h" #include "content/common/storage_partition_service.mojom.h" #include "content/common/url_loader_factory.mojom.h" #include "content/public/browser/render_process_host.h" @@ -110,7 +111,8 @@ public ChildProcessLauncher::Client, public ui::GpuSwitchingObserver, public NON_EXPORTED_BASE(mojom::RouteProvider), - public NON_EXPORTED_BASE(mojom::AssociatedInterfaceProvider) { + public NON_EXPORTED_BASE(mojom::AssociatedInterfaceProvider), + public NON_EXPORTED_BASE(mojom::RendererHost) { public: RenderProcessHostImpl(BrowserContext* browser_context, StoragePartitionImpl* storage_partition_impl, @@ -383,6 +385,9 @@ const std::string& name, mojom::AssociatedInterfaceAssociatedRequest request) override; + // mojom::RendererHost + void GetBlobURLLoaderFactory(mojom::URLLoaderFactoryRequest request) override; + void BindRouteProvider(mojom::RouteProviderAssociatedRequest request); void CreateMusGpuRequest(const service_manager::BindSourceInfo& source_info, @@ -395,6 +400,8 @@ void CreateStoragePartitionService( const service_manager::BindSourceInfo& source_info, mojom::StoragePartitionServiceRequest request); + void CreateRendererHost(const service_manager::BindSourceInfo& source_info, + mojom::RendererHostRequest request); void CreateURLLoaderFactory( const service_manager::BindSourceInfo& source_info, mojom::URLLoaderFactoryRequest request); @@ -682,6 +689,7 @@ mojom::RouteProviderAssociatedPtr remote_route_provider_; mojom::RendererAssociatedPtr renderer_interface_; + mojo::Binding<mojom::RendererHost> renderer_host_binding_; // Tracks active audio streams within the render process; used to determine if // if a process should be backgrounded.
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.cc b/content/browser/service_worker/service_worker_controllee_request_handler.cc index fd15aa2..2af53da 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -159,10 +159,10 @@ return job.release(); } -void ServiceWorkerControlleeRequestHandler::MaybeCreateLoaderFactory( +void ServiceWorkerControlleeRequestHandler::MaybeCreateLoader( const ResourceRequest& resource_request, ResourceContext* resource_context, - base::OnceCallback<void(mojom::URLLoaderFactory*)> factory_callback) { + LoaderCallback callback) { DCHECK(is_main_resource_load_); ClearJob(); @@ -171,7 +171,7 @@ if (!context_ || !provider_host_) { // We can't do anything other than to fall back to network. - std::move(factory_callback).Run(nullptr); + std::move(callback).Run(StartLoaderCallback()); return; } @@ -180,8 +180,7 @@ DCHECK(!use_network_); url_job_ = base::MakeUnique<ServiceWorkerURLJobWrapper>( - std::move(factory_callback), this, resource_request, - blob_storage_context_); + std::move(callback), this, resource_request, blob_storage_context_); resource_context_ = resource_context;
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler.h b/content/browser/service_worker/service_worker_controllee_request_handler.h index ee78639..e3bb52d 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler.h +++ b/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -68,10 +68,9 @@ // cases. (In fallback-to-network cases we basically forward the request // to the request to the next request handler) // URLLoaderRequestHandler overrides: - void MaybeCreateLoaderFactory( - const ResourceRequest& request, - ResourceContext* resource_context, - base::OnceCallback<void(mojom::URLLoaderFactory*)> callback) override; + void MaybeCreateLoader(const ResourceRequest& request, + ResourceContext* resource_context, + LoaderCallback callback) override; private: FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest,
diff --git a/content/browser/service_worker/service_worker_request_handler.cc b/content/browser/service_worker/service_worker_request_handler.cc index b1240cf..f27f2420 100644 --- a/content/browser/service_worker/service_worker_request_handler.cc +++ b/content/browser/service_worker/service_worker_request_handler.cc
@@ -237,12 +237,12 @@ return handler ? handler->provider_host_.get() : nullptr; } -void ServiceWorkerRequestHandler::MaybeCreateLoaderFactory( +void ServiceWorkerRequestHandler::MaybeCreateLoader( const ResourceRequest& request, ResourceContext* resource_context, - LoaderFactoryCallback callback) { + LoaderCallback callback) { NOTREACHED(); - std::move(callback).Run(nullptr); + std::move(callback).Run(StartLoaderCallback()); } void ServiceWorkerRequestHandler::PrepareForCrossSiteTransfer(
diff --git a/content/browser/service_worker/service_worker_request_handler.h b/content/browser/service_worker/service_worker_request_handler.h index b6adb61..d193eee5 100644 --- a/content/browser/service_worker/service_worker_request_handler.h +++ b/content/browser/service_worker/service_worker_request_handler.h
@@ -129,9 +129,9 @@ ResourceContext* context) = 0; // URLLoaderRequestHandler overrides. - void MaybeCreateLoaderFactory(const ResourceRequest& request, - ResourceContext* resource_context, - LoaderFactoryCallback callback) override; + void MaybeCreateLoader(const ResourceRequest& request, + ResourceContext* resource_context, + LoaderCallback callback) override; // Methods to support cross site navigations. void PrepareForCrossSiteTransfer(int old_process_id);
diff --git a/content/browser/service_worker/service_worker_url_job_wrapper.cc b/content/browser/service_worker/service_worker_url_job_wrapper.cc index 57ec426..342a01e 100644 --- a/content/browser/service_worker/service_worker_url_job_wrapper.cc +++ b/content/browser/service_worker/service_worker_url_job_wrapper.cc
@@ -22,6 +22,19 @@ class URLLoaderImpl : public mojom::URLLoader { public: + static void Start( + const ServiceWorkerResponse& response, + blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, + base::WeakPtr<storage::BlobStorageContext> blob_storage_context, + mojom::URLLoaderAssociatedRequest request, + mojom::URLLoaderClientPtr client) { + mojo::MakeStrongAssociatedBinding( + base::MakeUnique<URLLoaderImpl>(response, std::move(body_as_stream), + blob_storage_context, + std::move(client)), + std::move(request)); + } + URLLoaderImpl(const ServiceWorkerResponse& response, blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, base::WeakPtr<storage::BlobStorageContext> blob_storage_context, @@ -102,46 +115,6 @@ } // namespace -class ServiceWorkerURLJobWrapper::Factory : public mojom::URLLoaderFactory { - public: - Factory(const ServiceWorkerResponse& response, - blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, - base::WeakPtr<storage::BlobStorageContext> blob_storage_context) - : response_(response), - body_as_stream_(std::move(body_as_stream)), - blob_storage_context_(blob_storage_context) {} - - void CreateLoaderAndStart(mojom::URLLoaderAssociatedRequest request, - int32_t routing_id, - int32_t request_id, - uint32_t options, - const ResourceRequest& url_request, - mojom::URLLoaderClientPtr client) override { - // Note that url_request is ignored here, as we've already processed the - // fetch before even creating the factory. - // TODO(scottmg): Use options. - mojo::MakeStrongAssociatedBinding( - base::MakeUnique<URLLoaderImpl>(response_, std::move(body_as_stream_), - blob_storage_context_, - std::move(client)), - std::move(request)); - } - - void SyncLoad(int32_t routing_id, - int32_t request_id, - const ResourceRequest& url_request, - SyncLoadCallback callback) override { - NOTREACHED(); - } - - private: - ServiceWorkerResponse response_; - blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream_; - base::WeakPtr<storage::BlobStorageContext> blob_storage_context_; - - DISALLOW_COPY_AND_ASSIGN(Factory); -}; - ServiceWorkerURLJobWrapper::ServiceWorkerURLJobWrapper( base::WeakPtr<ServiceWorkerURLRequestJob> url_request_job) : job_type_(JobType::kURLRequest), @@ -149,12 +122,12 @@ weak_factory_(this) {} ServiceWorkerURLJobWrapper::ServiceWorkerURLJobWrapper( - LoaderFactoryCallback callback, + LoaderCallback callback, Delegate* delegate, const ResourceRequest& resource_request, base::WeakPtr<storage::BlobStorageContext> blob_storage_context) : job_type_(JobType::kURLLoader), - loader_factory_callback_(std::move(callback)), + loader_callback_(std::move(callback)), delegate_(delegate), resource_request_(resource_request), blob_storage_context_(blob_storage_context), @@ -173,8 +146,8 @@ // call this synchronously here and don't wait for a separate async // StartRequest cue like what URLRequestJob case does. // TODO(kinuko): Make sure this is ok or we need to make this async. - if (!loader_factory_callback_.is_null()) { - std::move(loader_factory_callback_).Run(nullptr); + if (!loader_callback_.is_null()) { + std::move(loader_callback_).Run(StartLoaderCallback()); } } else { url_request_job_->FallbackToNetwork(); @@ -240,7 +213,7 @@ bool ServiceWorkerURLJobWrapper::WasCanceled() const { if (job_type_ == JobType::kURLLoader) { - return loader_factory_callback_.is_null(); + return loader_callback_.is_null(); } else { return !url_request_job_; } @@ -302,14 +275,14 @@ blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, const scoped_refptr<ServiceWorkerVersion>& version) { if (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK) { - std::move(loader_factory_callback_).Run(nullptr); + std::move(loader_callback_).Run(StartLoaderCallback()); return; } DCHECK_EQ(fetch_result, SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE); - - factory_ = base::MakeUnique<Factory>(response, std::move(body_as_stream), - blob_storage_context_); - std::move(loader_factory_callback_).Run(factory_.get()); + std::move(loader_callback_) + .Run(base::Bind(&URLLoaderImpl::Start, response, + base::Passed(std::move(body_as_stream)), + blob_storage_context_)); } } // namespace content
diff --git a/content/browser/service_worker/service_worker_url_job_wrapper.h b/content/browser/service_worker/service_worker_url_job_wrapper.h index e090cd1..891d13d 100644 --- a/content/browser/service_worker/service_worker_url_job_wrapper.h +++ b/content/browser/service_worker/service_worker_url_job_wrapper.h
@@ -17,9 +17,9 @@ // This class is a helper to support having // ServiceWorkerControlleeRequestHandler work with both URLRequestJobs and -// mojom::URLLoaderFactorys (that is, both with and without -// --enable-network-service). It wraps either a ServiceWorkerURLRequestJob or a -// callback for URLLoaderFactory and forwards to the underlying implementation. +// mojom::URLLoaders (that is, both with and without --enable-network-service). +// It wraps either a ServiceWorkerURLRequestJob or a callback for +// URLLoader and forwards to the underlying implementation. class ServiceWorkerURLJobWrapper { public: class Delegate { @@ -38,7 +38,7 @@ // TODO(kinuko): Implement this as a separate job class rather // than in a wrapper. ServiceWorkerURLJobWrapper( - LoaderFactoryCallback loader_factory_callback, + LoaderCallback loader_callback, Delegate* delegate, const ResourceRequest& resource_request, base::WeakPtr<storage::BlobStorageContext> blob_storage_context); @@ -75,7 +75,6 @@ // Used only for URLLoader case. // For FORWARD_TO_SERVICE_WORKER case. - class Factory; void StartRequest(); void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version); @@ -94,12 +93,11 @@ JobType job_type_; ServiceWorkerResponseType response_type_ = NOT_DETERMINED; - LoaderFactoryCallback loader_factory_callback_; + LoaderCallback loader_callback_; base::WeakPtr<ServiceWorkerURLRequestJob> url_request_job_; Delegate* delegate_; - std::unique_ptr<Factory> factory_; ResourceRequest resource_request_; base::WeakPtr<storage::BlobStorageContext> blob_storage_context_; std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index f5c6e52..ca3cffe 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -50,7 +50,7 @@ #if defined(OS_CHROMEOS) #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/debug_daemon_client.h" -#include "content/browser/tracing/arc_tracing_agent.h" +#include "content/public/browser/arc_tracing_agent.h" #endif #if defined(OS_WIN)
diff --git a/content/browser/url_loader_factory_getter.cc b/content/browser/url_loader_factory_getter.cc index 9f16c054..4cf6d39 100644 --- a/content/browser/url_loader_factory_getter.cc +++ b/content/browser/url_loader_factory_getter.cc
@@ -18,8 +18,9 @@ partition->network_context()->CreateURLLoaderFactory( MakeRequest(&network_factory), 0); - mojom::URLLoaderFactoryPtr blob_factory = - partition->GetBlobURLLoaderFactory()->CreateFactory(); + mojom::URLLoaderFactoryPtr blob_factory; + partition->GetBlobURLLoaderFactory()->HandleRequest( + mojo::MakeRequest(&blob_factory)); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE,
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn index 5a37ace..ac802f9 100644 --- a/content/common/BUILD.gn +++ b/content/common/BUILD.gn
@@ -620,6 +620,7 @@ "render_message_filter.mojom", "render_widget_window_tree_client_factory.mojom", "renderer.mojom", + "renderer_host.mojom", "service_worker/embedded_worker.mojom", "service_worker/service_worker.mojom", "service_worker/service_worker_event_dispatcher.mojom",
diff --git a/content/common/renderer_host.mojom b/content/common/renderer_host.mojom new file mode 100644 index 0000000..b2a271a5 --- /dev/null +++ b/content/common/renderer_host.mojom
@@ -0,0 +1,14 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module content.mojom; + +import "content/common/url_loader_factory.mojom"; + +// The primordial interface implemented by a render process host. This should be +// used for implementing renderer-to-browser messages. +interface RendererHost { + // Requests a URLLoaderFactory for the blob scheme. + GetBlobURLLoaderFactory(URLLoaderFactory& loader); +};
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 4128f75..95311487 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -27,9 +27,10 @@ "blink::mojom::PermissionService", "blink::mojom::WebSocket", "content::mojom::FieldTrialRecorder", + "content::mojom::FrameSinkProvider", "content::mojom::MemoryCoordinatorHandle", "content::mojom::PushMessaging", - "content::mojom::FrameSinkProvider", + "content::mojom::RendererHost", "content::mojom::ServiceWorkerDispatcherHost", "content::mojom::StoragePartitionService", "content::mojom::URLLoaderFactory",
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 976f5d3..31b35c1 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -346,4 +346,11 @@ "zoom_level_delegate.h", ] } + + if (is_chromeos) { + sources += [ + "arc_tracing_agent.cc", + "arc_tracing_agent.h", + ] + } }
diff --git a/content/browser/tracing/arc_tracing_agent.cc b/content/public/browser/arc_tracing_agent.cc similarity index 98% rename from content/browser/tracing/arc_tracing_agent.cc rename to content/public/browser/arc_tracing_agent.cc index 0df2e2cc..8a2d1dd 100644 --- a/content/browser/tracing/arc_tracing_agent.cc +++ b/content/public/browser/arc_tracing_agent.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/tracing/arc_tracing_agent.h" +#include "content/public/browser/arc_tracing_agent.h" #include <memory> #include <string>
diff --git a/content/browser/tracing/arc_tracing_agent.h b/content/public/browser/arc_tracing_agent.h similarity index 91% rename from content/browser/tracing/arc_tracing_agent.h rename to content/public/browser/arc_tracing_agent.h index 297a74c..2607ee81 100644 --- a/content/browser/tracing/arc_tracing_agent.h +++ b/content/public/browser/arc_tracing_agent.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_TRACING_ARC_TRACING_AGENT_H_ -#define CONTENT_BROWSER_TRACING_ARC_TRACING_AGENT_H_ +#ifndef CONTENT_PUBLIC_BROWSER_ARC_TRACING_AGENT_H_ +#define CONTENT_PUBLIC_BROWSER_ARC_TRACING_AGENT_H_ #include "base/callback_forward.h" #include "base/files/scoped_file.h" @@ -57,4 +57,4 @@ } // namespace content -#endif // CONTENT_BROWSER_TRACING_ARC_TRACING_AGENT_H_ +#endif // CONTENT_PUBLIC_BROWSER_ARC_TRACING_AGENT_H_
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 98d81103..c36999d9 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4317,7 +4317,18 @@ } } - extra_data->set_url_loader_factory_override(url_loader_factory_.get()); + // TODO: generalize how non-network schemes are sent to the renderer and used. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNetworkService)) { + if (request.Url().ProtocolIs(url::kBlobScheme)) { + extra_data->set_url_loader_factory_override( + RenderThreadImpl::current()->GetBlobURLLoaderFactory()); + } + } + + if (!extra_data->url_loader_factory_override()) + extra_data->set_url_loader_factory_override(url_loader_factory_.get()); + // TODO(kinuko, yzshen): We need to set up throttles for some worker cases // that don't go through here. extra_data->set_url_loader_throttles(std::move(throttles));
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index fe54aff..6733690 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1084,6 +1084,22 @@ return storage_partition_service_.get(); } +mojom::RendererHost* RenderThreadImpl::GetRendererHost() { + if (!renderer_host_) { + GetConnector()->BindInterface(mojom::kBrowserServiceName, + mojo::MakeRequest(&renderer_host_)); + } + return renderer_host_.get(); +} + +mojom::URLLoaderFactory* RenderThreadImpl::GetBlobURLLoaderFactory() { + if (!blob_url_loader_factory_) { + GetRendererHost()->GetBlobURLLoaderFactory( + mojo::MakeRequest(&blob_url_loader_factory_)); + } + return blob_url_loader_factory_.get(); +} + int RenderThreadImpl::GenerateRoutingID() { int32_t routing_id = MSG_ROUTING_NONE; render_message_filter()->GenerateRoutingID(&routing_id);
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index ecf995c..7c12d95 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -40,7 +40,9 @@ #include "content/common/render_frame_message_filter.mojom.h" #include "content/common/render_message_filter.mojom.h" #include "content/common/renderer.mojom.h" +#include "content/common/renderer_host.mojom.h" #include "content/common/storage_partition_service.mojom.h" +#include "content/common/url_loader_factory.mojom.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/gpu/compositor_dependencies.h" #include "content/renderer/layout_test_dependencies.h" @@ -489,6 +491,8 @@ mojom::FrameHostInterfaceBrokerPtr host); mojom::StoragePartitionService* GetStoragePartitionService(); + mojom::RendererHost* GetRendererHost(); + mojom::URLLoaderFactory* GetBlobURLLoaderFactory(); // ChildMemoryCoordinatorDelegate implementation. void OnTrimMemoryImmediately() override; @@ -783,6 +787,8 @@ PendingFrameCreateMap pending_frame_creates_; mojom::StoragePartitionServicePtr storage_partition_service_; + mojom::RendererHostPtr renderer_host_; + mojom::URLLoaderFactoryPtr blob_url_loader_factory_; AssociatedInterfaceRegistryImpl associated_interfaces_;
diff --git a/ios/chrome/browser/browsing_data/BUILD.gn b/ios/chrome/browser/browsing_data/BUILD.gn index eb4b15e..ee16ec9d 100644 --- a/ios/chrome/browser/browsing_data/BUILD.gn +++ b/ios/chrome/browser/browsing_data/BUILD.gn
@@ -27,6 +27,7 @@ "//components/password_manager/core/browser", "//components/prefs", "//components/sessions", + "//components/translate/core/browser:browser", "//ios/chrome/browser", "//ios/chrome/browser/autofill", "//ios/chrome/browser/browser_state", @@ -37,6 +38,7 @@ "//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", + "//ios/chrome/browser/translate:translate", "//ios/net", "//ios/public/provider/chrome/browser", "//ios/web",
diff --git a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm index 1600961..a9f0d06 100644 --- a/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm +++ b/ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.mm
@@ -24,6 +24,7 @@ #include "components/prefs/pref_service.h" #include "components/search_engines/template_url_service.h" #include "components/sessions/core/tab_restore_service.h" +#include "components/translate/core/browser/language_model.h" #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" @@ -33,6 +34,7 @@ #include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" +#include "ios/chrome/browser/translate/language_model_factory.h" #include "ios/chrome/browser/web_data_service_factory.h" #include "ios/net/http_cache_helper.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" @@ -245,6 +247,12 @@ data_manager->Refresh(); } + // Remove language model history. + translate::LanguageModel* language_model = + LanguageModelFactory::GetForBrowserState(browser_state_); + if (language_model) { + language_model->ClearHistory(delete_begin_, delete_end_); + } } if (remove_mask & REMOVE_COOKIES) {
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index 3cda610..6539c99 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -32,6 +32,7 @@ #include "components/ssl_config/ssl_config_service_manager.h" #include "components/strings/grit/components_locale_settings.h" #include "components/sync/base/sync_prefs.h" +#include "components/translate/core/browser/language_model.h" #include "components/translate/core/browser/translate_pref_names.h" #include "components/translate/core/browser/translate_prefs.h" #include "components/update_client/update_client.h" @@ -113,6 +114,7 @@ PrefProxyConfigTrackerImpl::RegisterProfilePrefs(registry); syncer::SyncPrefs::RegisterProfilePrefs(registry); TemplateURLPrepopulateData::RegisterProfilePrefs(registry); + translate::LanguageModel::RegisterProfilePrefs(registry); translate::TranslatePrefs::RegisterProfilePrefs(registry); variations::VariationsService::RegisterProfilePrefs(registry); ZeroSuggestProvider::RegisterProfilePrefs(registry);
diff --git a/ios/chrome/browser/translate/BUILD.gn b/ios/chrome/browser/translate/BUILD.gn index 8f70c26..abc6ff6 100644 --- a/ios/chrome/browser/translate/BUILD.gn +++ b/ios/chrome/browser/translate/BUILD.gn
@@ -10,6 +10,8 @@ "before_translate_infobar_controller.mm", "chrome_ios_translate_client.h", "chrome_ios_translate_client.mm", + "language_model_factory.cc", + "language_model_factory.h", "never_translate_infobar_controller.h", "never_translate_infobar_controller.mm", "translate_accept_languages_factory.cc", @@ -48,6 +50,7 @@ "//ui/gfx", "//url", ] + allow_circular_includes_from = [ "//ios/chrome/browser/infobars" ] } @@ -56,6 +59,7 @@ testonly = true sources = [ "js_language_detection_manager_unittest.mm", + "language_model_factory_unittest.cc", "translate_service_ios_unittest.cc", ] deps = [ @@ -64,11 +68,13 @@ "//base/test:test_support", "//components/translate/ios/browser", "//ios/chrome/browser", + "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/web:test_support", "//ios/chrome/common", "//ios/public/provider/chrome/browser:test_support", "//ios/web", "//ios/web/public/test", + "//testing/gmock:gmock", "//testing/gtest", "//url", ]
diff --git a/ios/chrome/browser/translate/chrome_ios_translate_client.mm b/ios/chrome/browser/translate/chrome_ios_translate_client.mm index 85b3d34..b474a280 100644 --- a/ios/chrome/browser/translate/chrome_ios_translate_client.mm +++ b/ios/chrome/browser/translate/chrome_ios_translate_client.mm
@@ -24,6 +24,7 @@ #include "ios/chrome/browser/pref_names.h" #import "ios/chrome/browser/translate/after_translate_infobar_controller.h" #import "ios/chrome/browser/translate/before_translate_infobar_controller.h" +#include "ios/chrome/browser/translate/language_model_factory.h" #import "ios/chrome/browser/translate/never_translate_infobar_controller.h" #include "ios/chrome/browser/translate/translate_accept_languages_factory.h" #import "ios/chrome/browser/translate/translate_message_infobar_controller.h" @@ -46,7 +47,10 @@ prefs::kAcceptLanguages)), translate_driver_(web_state, web_state->GetNavigationManager(), - translate_manager_.get()) {} + translate_manager_.get(), + LanguageModelFactory::GetForBrowserState( + ios::ChromeBrowserState::FromBrowserState( + web_state->GetBrowserState()))) {} ChromeIOSTranslateClient::~ChromeIOSTranslateClient() { }
diff --git a/ios/chrome/browser/translate/language_model_factory.cc b/ios/chrome/browser/translate/language_model_factory.cc new file mode 100644 index 0000000..45b3ec28 --- /dev/null +++ b/ios/chrome/browser/translate/language_model_factory.cc
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/translate/language_model_factory.h" + +#include "base/memory/ptr_util.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/keyed_service/ios/browser_state_dependency_manager.h" +#include "components/translate/core/browser/language_model.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" + +// static +LanguageModelFactory* LanguageModelFactory::GetInstance() { + return base::Singleton<LanguageModelFactory>::get(); +} + +// static +translate::LanguageModel* LanguageModelFactory::GetForBrowserState( + ios::ChromeBrowserState* const state) { + return static_cast<translate::LanguageModel*>( + GetInstance()->GetServiceForBrowserState(state, true)); +} + +LanguageModelFactory::LanguageModelFactory() + : BrowserStateKeyedServiceFactory( + "LanguageModel", + BrowserStateDependencyManager::GetInstance()) {} + +LanguageModelFactory::~LanguageModelFactory() {} + +std::unique_ptr<KeyedService> LanguageModelFactory::BuildServiceInstanceFor( + web::BrowserState* context) const { + ios::ChromeBrowserState* browser_state = + ios::ChromeBrowserState::FromBrowserState(context); + return base::MakeUnique<translate::LanguageModel>(browser_state->GetPrefs()); +}
diff --git a/ios/chrome/browser/translate/language_model_factory.h b/ios/chrome/browser/translate/language_model_factory.h new file mode 100644 index 0000000..a128a98 --- /dev/null +++ b/ios/chrome/browser/translate/language_model_factory.h
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_MODEL_FACTORY_H +#define IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_MODEL_FACTORY_H + +#include <memory> + +#include "base/memory/singleton.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/keyed_service/ios/browser_state_keyed_service_factory.h" + +namespace ios { +class ChromeBrowserState; +} + +namespace translate { +class LanguageModel; +} + +class LanguageModelFactory : public BrowserStateKeyedServiceFactory { + public: + static LanguageModelFactory* GetInstance(); + static translate::LanguageModel* GetForBrowserState( + ios::ChromeBrowserState* browser_state); + + private: + friend struct base::DefaultSingletonTraits<LanguageModelFactory>; + + LanguageModelFactory(); + ~LanguageModelFactory() override; + + // BrowserStateKeyedServiceFactory implementation. + std::unique_ptr<KeyedService> BuildServiceInstanceFor( + web::BrowserState* context) const override; + + DISALLOW_COPY_AND_ASSIGN(LanguageModelFactory); +}; + +#endif // IOS_CHROME_BROWSER_TRANSLATE_LANGUAGE_MODEL_FACTORY_H
diff --git a/ios/chrome/browser/translate/language_model_factory_unittest.cc b/ios/chrome/browser/translate/language_model_factory_unittest.cc new file mode 100644 index 0000000..a5b84cd --- /dev/null +++ b/ios/chrome/browser/translate/language_model_factory_unittest.cc
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/translate/language_model_factory.h" + +#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#include "ios/web/public/test/test_web_thread_bundle.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::IsNull; +using testing::Not; + +class LanguageModelFactoryTest : public testing::Test { + public: + LanguageModelFactoryTest() { + TestChromeBrowserState::Builder browser_state_builder; + chrome_browser_state_ = browser_state_builder.Build(); + } + + ~LanguageModelFactoryTest() override { chrome_browser_state_.reset(); } + + ios::ChromeBrowserState* chrome_browser_state() { + return chrome_browser_state_.get(); + } + + private: + web::TestWebThreadBundle thread_bundle_; + std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; +}; + +TEST_F(LanguageModelFactoryTest, NotCreatedInIncognito) { + EXPECT_THAT(LanguageModelFactory::GetForBrowserState(chrome_browser_state()), + Not(IsNull())); + + ios::ChromeBrowserState* otr_browser_state = + chrome_browser_state()->GetOffTheRecordChromeBrowserState(); + translate::LanguageModel* language_model = + LanguageModelFactory::GetForBrowserState(otr_browser_state); + EXPECT_THAT(language_model, IsNull()); +}
diff --git a/ios/chrome/browser/ui/ntp/google_landing_mediator.mm b/ios/chrome/browser/ui/ntp/google_landing_mediator.mm index 47ae5c4..46028db3 100644 --- a/ios/chrome/browser/ui/ntp/google_landing_mediator.mm +++ b/ios/chrome/browser/ui/ntp/google_landing_mediator.mm
@@ -383,11 +383,7 @@ #pragma mark - Private - (void)useFreshData { - if (self.freshMostVisitedData.size() == 0) { - return; - } _mostVisitedData = self.freshMostVisitedData; - self.freshMostVisitedData.clear(); [self.consumer mostVisitedDataUpdated]; }
diff --git a/ios/web_view/internal/translate/web_view_translate_client.mm b/ios/web_view/internal/translate/web_view_translate_client.mm index 20af5637..ddc9bed 100644 --- a/ios/web_view/internal/translate/web_view_translate_client.mm +++ b/ios/web_view/internal/translate/web_view_translate_client.mm
@@ -34,6 +34,9 @@ namespace ios_web_view { +// TODO(crbug.com/729859): Support logging histogram data on detected language +// page, by passing a valid language_model, when histogram logging is available +// on ios/web_view. WebViewTranslateClient::WebViewTranslateClient(web::WebState* web_state) : web::WebStateObserver(web_state), translate_manager_(base::MakeUnique<translate::TranslateManager>( @@ -44,7 +47,8 @@ prefs::kAcceptLanguages)), translate_driver_(web_state, web_state->GetNavigationManager(), - translate_manager_.get()) {} + translate_manager_.get(), + nullptr /* language_model */) {} WebViewTranslateClient::~WebViewTranslateClient() = default;
diff --git a/mojo/edk/js/tests/BUILD.gn b/mojo/edk/js/tests/BUILD.gn index 21c9bfc4..b3b87392 100644 --- a/mojo/edk/js/tests/BUILD.gn +++ b/mojo/edk/js/tests/BUILD.gn
@@ -15,44 +15,10 @@ group("tests") { testonly = true deps = [ - ":mojo_js_integration_tests", ":mojo_js_unittests", ] } -test("mojo_js_integration_tests") { - deps = [ - ":js_to_cpp_bindings", - "//base/test:test_support", - "//gin:gin_test", - "//mojo/common", - "//mojo/edk/js", - "//mojo/edk/test:run_all_unittests", - "//mojo/public/cpp/bindings", - "//mojo/public/cpp/system", - "//mojo/public/js:bindings", - ] - - sources = [ - "js_to_cpp_tests.cc", - ] - - data = [ - "js_to_cpp_tests.js", - ] - - configs += [ "//v8:external_startup_data" ] -} - -mojom("js_to_cpp_bindings") { - sources = [ - "js_to_cpp.mojom", - ] - - # TODO(crbug.com/699569): Convert to use the new JS bindings. - use_new_js_bindings = false -} - test("mojo_js_unittests") { deps = [ "//base",
diff --git a/mojo/edk/js/tests/js_to_cpp_tests.cc b/mojo/edk/js/tests/js_to_cpp_tests.cc deleted file mode 100644 index d193ffc..0000000 --- a/mojo/edk/js/tests/js_to_cpp_tests.cc +++ /dev/null
@@ -1,459 +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 <stddef.h> -#include <stdint.h> - -#include <string> -#include <utility> - -#include "base/at_exit.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/macros.h" -#include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_task_environment.h" -#include "base/threading/thread_task_runner_handle.h" -#include "gin/array_buffer.h" -#include "gin/public/isolate_holder.h" -#include "gin/v8_initializer.h" -#include "mojo/common/data_pipe_utils.h" -#include "mojo/edk/js/mojo_runner_delegate.h" -#include "mojo/edk/js/tests/js_to_cpp.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/public/cpp/system/wait.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace edk { -namespace js { - -// Global value updated by some checks to prevent compilers from optimizing -// reads out of existence. -uint32_t g_waste_accumulator = 0; - -namespace { - -// Negative numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const int8_t kExpectedInt8Value = -65; -const int16_t kExpectedInt16Value = -16961; -const int32_t kExpectedInt32Value = -1145258561; -const int64_t kExpectedInt64Value = -77263311946305LL; - -// Positive numbers with different values in each byte, the last of -// which can survive promotion to double and back. -const uint8_t kExpectedUInt8Value = 65; -const uint16_t kExpectedUInt16Value = 16961; -const uint32_t kExpectedUInt32Value = 1145258561; -const uint64_t kExpectedUInt64Value = 77263311946305LL; - -// Double/float values, including special case constants. -const double kExpectedDoubleVal = 3.14159265358979323846; -const double kExpectedDoubleInf = std::numeric_limits<double>::infinity(); -const double kExpectedDoubleNan = std::numeric_limits<double>::quiet_NaN(); -const float kExpectedFloatVal = static_cast<float>(kExpectedDoubleVal); -const float kExpectedFloatInf = std::numeric_limits<float>::infinity(); -const float kExpectedFloatNan = std::numeric_limits<float>::quiet_NaN(); - -// NaN has the property that it is not equal to itself. -#define EXPECT_NAN(x) EXPECT_NE(x, x) - -void CheckDataPipe(ScopedDataPipeConsumerHandle data_pipe_handle) { - std::string buffer; - bool result = common::BlockingCopyToString(std::move(data_pipe_handle), - &buffer); - EXPECT_TRUE(result); - EXPECT_EQ(64u, buffer.size()); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(i, buffer[i]); - } -} - -void CheckMessagePipe(MessagePipeHandle message_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = Wait(message_pipe_handle, MOJO_HANDLE_SIGNAL_READABLE); - EXPECT_EQ(MOJO_RESULT_OK, result); - result = ReadMessageRaw( - message_pipe_handle, buffer, &buffer_size, 0, 0, 0); - EXPECT_EQ(MOJO_RESULT_OK, result); - EXPECT_EQ(64u, buffer_size); - for (int i = 0; i < 64; ++i) { - EXPECT_EQ(255 - i, buffer[i]); - } -} - -js_to_cpp::EchoArgsPtr BuildSampleEchoArgs() { - js_to_cpp::EchoArgsPtr args(js_to_cpp::EchoArgs::New()); - args->si64 = kExpectedInt64Value; - args->si32 = kExpectedInt32Value; - args->si16 = kExpectedInt16Value; - args->si8 = kExpectedInt8Value; - args->ui64 = kExpectedUInt64Value; - args->ui32 = kExpectedUInt32Value; - args->ui16 = kExpectedUInt16Value; - args->ui8 = kExpectedUInt8Value; - args->float_val = kExpectedFloatVal; - args->float_inf = kExpectedFloatInf; - args->float_nan = kExpectedFloatNan; - args->double_val = kExpectedDoubleVal; - args->double_inf = kExpectedDoubleInf; - args->double_nan = kExpectedDoubleNan; - args->name.emplace("coming"); - args->string_array.emplace(3); - (*args->string_array)[0] = "one"; - (*args->string_array)[1] = "two"; - (*args->string_array)[2] = "three"; - return args; -} - -void CheckSampleEchoArgs(js_to_cpp::EchoArgsPtr arg) { - EXPECT_EQ(kExpectedInt64Value, arg->si64); - EXPECT_EQ(kExpectedInt32Value, arg->si32); - EXPECT_EQ(kExpectedInt16Value, arg->si16); - EXPECT_EQ(kExpectedInt8Value, arg->si8); - EXPECT_EQ(kExpectedUInt64Value, arg->ui64); - EXPECT_EQ(kExpectedUInt32Value, arg->ui32); - EXPECT_EQ(kExpectedUInt16Value, arg->ui16); - EXPECT_EQ(kExpectedUInt8Value, arg->ui8); - EXPECT_EQ(kExpectedFloatVal, arg->float_val); - EXPECT_EQ(kExpectedFloatInf, arg->float_inf); - EXPECT_NAN(arg->float_nan); - EXPECT_EQ(kExpectedDoubleVal, arg->double_val); - EXPECT_EQ(kExpectedDoubleInf, arg->double_inf); - EXPECT_NAN(arg->double_nan); - EXPECT_EQ(std::string("coming"), *arg->name); - EXPECT_EQ(std::string("one"), (*arg->string_array)[0]); - EXPECT_EQ(std::string("two"), (*arg->string_array)[1]); - EXPECT_EQ(std::string("three"), (*arg->string_array)[2]); - CheckDataPipe(std::move(arg->data_handle)); - CheckMessagePipe(arg->message_handle.get()); -} - -void CheckSampleEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckSampleEchoArgs(std::move(list->item)); - CheckSampleEchoArgsList(list->next); -} - -// More forgiving checks are needed in the face of potentially corrupt -// messages. The values don't matter so long as all accesses are within -// bounds. -void CheckCorruptedString(const std::string& arg) { - for (size_t i = 0; i < arg.size(); ++i) - g_waste_accumulator += arg[i]; -} - -void CheckCorruptedString(const base::Optional<std::string>& arg) { - if (!arg) - return; - CheckCorruptedString(*arg); -} - -void CheckCorruptedStringArray( - const base::Optional<std::vector<std::string>>& string_array) { - if (!string_array) - return; - for (size_t i = 0; i < string_array->size(); ++i) - CheckCorruptedString((*string_array)[i]); -} - -void CheckCorruptedDataPipe(MojoHandle data_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = MojoReadData( - data_pipe_handle, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < buffer_size; ++i) - g_waste_accumulator += buffer[i]; -} - -void CheckCorruptedMessagePipe(MojoHandle message_pipe_handle) { - unsigned char buffer[100]; - uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); - MojoResult result = MojoReadMessage( - message_pipe_handle, buffer, &buffer_size, 0, 0, 0); - if (result != MOJO_RESULT_OK) - return; - for (uint32_t i = 0; i < buffer_size; ++i) - g_waste_accumulator += buffer[i]; -} - -void CheckCorruptedEchoArgs(const js_to_cpp::EchoArgsPtr& arg) { - if (arg.is_null()) - return; - CheckCorruptedString(arg->name); - CheckCorruptedStringArray(arg->string_array); - if (arg->data_handle.is_valid()) - CheckCorruptedDataPipe(arg->data_handle.get().value()); - if (arg->message_handle.is_valid()) - CheckCorruptedMessagePipe(arg->message_handle.get().value()); -} - -void CheckCorruptedEchoArgsList(const js_to_cpp::EchoArgsListPtr& list) { - if (list.is_null()) - return; - CheckCorruptedEchoArgs(list->item); - CheckCorruptedEchoArgsList(list->next); -} - -// Base Provider implementation class. It's expected that tests subclass and -// override the appropriate Provider functions. When test is done quit the -// run_loop(). -class CppSideConnection : public js_to_cpp::CppSide { - public: - CppSideConnection() - : run_loop_(nullptr), - js_side_(nullptr), - mishandled_messages_(0), - binding_(this) {} - ~CppSideConnection() override {} - - void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; } - base::RunLoop* run_loop() { return run_loop_; } - - void set_js_side(js_to_cpp::JsSide* js_side) { js_side_ = js_side; } - js_to_cpp::JsSide* js_side() { return js_side_; } - - void Bind(InterfaceRequest<js_to_cpp::CppSide> request) { - binding_.Bind(std::move(request)); - // Keep the pipe open even after validation errors. - binding_.EnableTestingMode(); - } - - // js_to_cpp::CppSide: - void StartTest() override { NOTREACHED(); } - - void TestFinished() override { NOTREACHED(); } - - void PingResponse() override { mishandled_messages_ += 1; } - - void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - void BitFlipResponse( - js_to_cpp::EchoArgsListPtr list, - js_to_cpp::ForTestingAssociatedPtrInfo not_used) override { - mishandled_messages_ += 1; - } - - void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { - mishandled_messages_ += 1; - } - - protected: - base::RunLoop* run_loop_; - js_to_cpp::JsSide* js_side_; - int mishandled_messages_; - mojo::Binding<js_to_cpp::CppSide> binding_; - - private: - DISALLOW_COPY_AND_ASSIGN(CppSideConnection); -}; - -// Trivial test to verify a message sent from JS is received. -class PingCppSideConnection : public CppSideConnection { - public: - PingCppSideConnection() : got_message_(false) {} - ~PingCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->Ping(); } - - void PingResponse() override { - got_message_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return got_message_ && !mishandled_messages_; - } - - private: - bool got_message_; - DISALLOW_COPY_AND_ASSIGN(PingCppSideConnection); -}; - -// Test that parameters are passed with correct values. -class EchoCppSideConnection : public CppSideConnection { - public: - EchoCppSideConnection() : - message_count_(0), - termination_seen_(false) { - } - ~EchoCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { - js_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs()); - } - - void EchoResponse(js_to_cpp::EchoArgsListPtr list) override { - const js_to_cpp::EchoArgsPtr& special_arg = list->item; - message_count_ += 1; - EXPECT_EQ(-1, special_arg->si64); - EXPECT_EQ(-1, special_arg->si32); - EXPECT_EQ(-1, special_arg->si16); - EXPECT_EQ(-1, special_arg->si8); - EXPECT_EQ(std::string("going"), *special_arg->name); - CheckSampleEchoArgsList(list->next); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_ && - !mishandled_messages_ && - message_count_ == kExpectedMessageCount; - } - - private: - static const int kExpectedMessageCount = 10; - int message_count_; - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(EchoCppSideConnection); -}; - -// Test that corrupted messages don't wreak havoc. -class BitFlipCppSideConnection : public CppSideConnection { - public: - BitFlipCppSideConnection() : termination_seen_(false) {} - ~BitFlipCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BitFlip(BuildSampleEchoArgs()); } - - void BitFlipResponse( - js_to_cpp::EchoArgsListPtr list, - js_to_cpp::ForTestingAssociatedPtrInfo not_used) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_; - } - - private: - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(BitFlipCppSideConnection); -}; - -// Test that severely random messages don't wreak havoc. -class BackPointerCppSideConnection : public CppSideConnection { - public: - BackPointerCppSideConnection() : termination_seen_(false) {} - ~BackPointerCppSideConnection() override {} - - // js_to_cpp::CppSide: - void StartTest() override { js_side_->BackPointer(BuildSampleEchoArgs()); } - - void BackPointerResponse(js_to_cpp::EchoArgsListPtr list) override { - CheckCorruptedEchoArgsList(list); - } - - void TestFinished() override { - termination_seen_ = true; - run_loop()->Quit(); - } - - bool DidSucceed() { - return termination_seen_; - } - - private: - bool termination_seen_; - DISALLOW_COPY_AND_ASSIGN(BackPointerCppSideConnection); -}; - -} // namespace - -class JsToCppTest : public testing::Test { - public: - JsToCppTest() {} - - void RunTest(const std::string& test, CppSideConnection* cpp_side) { - cpp_side->set_run_loop(&run_loop_); - - js_to_cpp::JsSidePtr js_side; - auto js_side_proxy = MakeRequest(&js_side); - - cpp_side->set_js_side(js_side.get()); - js_to_cpp::CppSidePtr cpp_side_ptr; - cpp_side->Bind(MakeRequest(&cpp_side_ptr)); - - js_side->SetCppSide(std::move(cpp_side_ptr)); - -#ifdef V8_USE_EXTERNAL_STARTUP_DATA - gin::V8Initializer::LoadV8Snapshot(); - gin::V8Initializer::LoadV8Natives(); -#endif - - gin::IsolateHolder::Initialize(gin::IsolateHolder::kStrictMode, - gin::IsolateHolder::kStableV8Extras, - gin::ArrayBufferAllocator::SharedInstance()); - gin::IsolateHolder instance(base::ThreadTaskRunnerHandle::Get()); - MojoRunnerDelegate delegate; - gin::ShellRunner runner(&delegate, instance.isolate()); - delegate.Start(&runner, js_side_proxy.PassMessagePipe().release().value(), - test); - - run_loop_.Run(); - } - - private: - base::ShadowingAtExitManager at_exit_; - base::test::ScopedTaskEnvironment scoped_task_environment_; - base::RunLoop run_loop_; - - DISALLOW_COPY_AND_ASSIGN(JsToCppTest); -}; - -TEST_F(JsToCppTest, Ping) { - PingCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, Echo) { - EchoCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BitFlip) { - // These tests generate a lot of expected validation errors. Suppress logging. - mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; - - BitFlipCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -TEST_F(JsToCppTest, BackPointer) { - // These tests generate a lot of expected validation errors. Suppress logging. - mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; - - BackPointerCppSideConnection cpp_side_connection; - RunTest("mojo/edk/js/tests/js_to_cpp_tests", &cpp_side_connection); - EXPECT_TRUE(cpp_side_connection.DidSucceed()); -} - -} // namespace js -} // namespace edk -} // namespace mojo
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index e8d493e..ab79ff6 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -11711,6 +11711,40 @@ }, "test": "content_browsertests" } + ], + "isolated_scripts": [ + { + "args": [ + "--additional-driver-flag=--enable-network-service" + ], + "isolate_name": "webkit_layout_tests_exparchive", + "merge": { + "args": [ + "--verbose", + "--results-json-override-with-build-property", + "build_number", + "buildnumber", + "--results-json-override-with-build-property", + "builder_name", + "buildername", + "--results-json-override-with-build-property", + "chromium_revision", + "got_revision_cp" + ], + "script": "//third_party/WebKit/Tools/Scripts/merge-layout-test-results" + }, + "name": "webkit_layout_tests", + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-14.04" + } + ], + "shards": 6 + } + } ] }, "Mojo Windows": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 70f6fa72..1d5b2959 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -3901,12 +3901,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "mojo_js_integration_tests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "mojo_js_unittests" }, { @@ -4582,12 +4576,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "mojo_js_integration_tests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "mojo_js_unittests" }, {
diff --git a/testing/buildbot/client.v8.chromium.json b/testing/buildbot/client.v8.chromium.json index bb493a0..09e30211 100644 --- a/testing/buildbot/client.v8.chromium.json +++ b/testing/buildbot/client.v8.chromium.json
@@ -236,12 +236,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "mojo_js_integration_tests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "mojo_js_unittests" }, {
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index cc09ada3..8034949 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -33,10 +33,6 @@ -ServiceWorkerVersionBrowserTest.ServiceWorkerScriptHeader -ServiceWorkerVersionBrowserTest.StartNotFound -# http://crbug.com/715677 -# Needs blob fetching for subresources --BlobStorageBrowserTest.BlobCombinations - # http://crbug.com/715630 -DownloadContentTest.* @@ -61,7 +57,6 @@ -DataUrlNavigationBrowserTest.UnknownMimeType_WindowOpen_Download -DevToolsProtocolTest.CertificateError -DevToolsProtocolTest.SubresourceWithCertificateError --FrameTreeBrowserTest.NavigateGrandchildToBlob -GenericSensorBrowserTest.AmbientLightSensorTest -HostZoomMapImplBrowserTest.GetZoomForView_Host -HostZoomMapImplBrowserTest.GetZoomForView_HostAndScheme @@ -85,6 +80,7 @@ -NavigationControllerBrowserTest.NavigateFromLoadDataWithBaseURL -NavigationControllerBrowserTest.NoDialogsFromSwappedOutFrames -NavigationControllerBrowserTest.RefererStoredForSubFrame +-NavigationHandleImplBrowserTest.ErrorCodeOnRedirect -ParallelDownloadTest.ParallelDownloadComplete -PaymentAppBrowserTest.PaymentAppInvocation -PaymentAppBrowserTest.PaymentAppOpenWindowFailed
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 3f8a6f08..3db232d8 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -704,10 +704,6 @@ "label": "//mojo/common:mojo_common_unittests", "type": "console_test_launcher", }, - "mojo_js_integration_tests": { - "label": "//mojo/edk/js/tests:mojo_js_integration_tests", - "type": "console_test_launcher", - }, "mojo_js_unittests": { "label": "//mojo/edk/js/tests:mojo_js_unittests", "type": "console_test_launcher",
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service index 6a8900c..5be456d 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
@@ -34,6 +34,15 @@ Bug(none) bluetooth/requestDevice/request-from-iframe.html [ Timeout ] Bug(none) bluetooth/requestDevice/same-device.html [ Timeout ] Bug(none) bluetooth/requestDevice/single-filter-single-service.html [ Timeout ] +Bug(none) bluetooth/server/connect/connection-succeeds.html [ Timeout ] +Bug(none) bluetooth/server/connect/garbage-collection-ran-during-success.html [ Timeout ] +Bug(none) bluetooth/server/connect/get-same-gatt-server.html [ Timeout ] +Bug(none) bluetooth/server/device-same-object.html [ Timeout ] +Bug(none) bluetooth/server/getPrimaryService/gen-invalid-service-name.html [ Timeout ] +Bug(none) bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.html [ Timeout ] +Bug(none) bluetooth/server/getPrimaryServices/gen-invalid-service-name.html [ Timeout ] +Bug(none) bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.html [ Timeout ] +Bug(none) bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.html [ Timeout ] Bug(none) compositing/iframes/iframe-in-composited-layer.html [ Failure ] Bug(none) compositing/layers-inside-overflow-scroll.html [ Timeout ] Bug(none) compositing/self-painting-layers2.html [ Timeout ] @@ -610,6 +619,7 @@ Bug(none) external/wpt/payment-request/allowpaymentrequest/setting-allowpaymentrequest.https.sub.html [ Timeout ] Bug(none) external/wpt/payment-request/historical.https.html [ Timeout ] Bug(none) external/wpt/payment-request/interfaces.https.html [ Timeout ] +Bug(none) external/wpt/payment-request/payment-request-abort-method.https.html [ Timeout ] Bug(none) external/wpt/payment-request/payment-request-constructor.https.html [ Timeout ] Bug(none) external/wpt/payment-request/payment-request-id.https.html [ Timeout ] Bug(none) external/wpt/payment-request/payment-request-show-method.https.html [ Timeout ] @@ -1258,70 +1268,7 @@ Bug(none) external/wpt/workers/constructors/Worker/Blob-url.html [ Timeout ] Bug(none) external/wpt/workers/name-property.html [ Failure Timeout ] Bug(none) external/wpt/workers/SharedWorker_blobUrl.html [ Timeout ] -Bug(none) external/wpt/XMLHttpRequest/abort-during-done.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/anonymous-mode-unsupported.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/event-upload-progress-crossorigin.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/event-upload-progress.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/formdata-blob.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/formdata.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/getallresponseheaders-cl.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/headers-normalize-response.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-method-case-insensitive.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-method-case-sensitive.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-open-sync-send.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-referer.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-about-blank-window.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-base-inserted-after-open.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-base-inserted.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-base.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-encoding.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-fragment.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-javascript-window-2.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-javascript-window.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/open-url-worker-origin.htm [ Timeout ] -Bug(none) external/wpt/XMLHttpRequest/overridemimetype-blob.html [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/response-data-blob.htm [ Timeout ] -Bug(none) external/wpt/XMLHttpRequest/response-data-deflate.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/response-data-gzip.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/response-data-progress.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/response-method.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/responsetype.html [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/responseurl.html [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/responsexml-basic.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/responsexml-media-type.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/responsexml-non-well-formed.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-accept-language.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-accept.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-after-setting-document-domain.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-authentication-basic-repeat-no-args.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-authentication-basic-setrequestheader-and-arguments.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-authentication-basic-setrequestheader-existing-session.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-authentication-basic-setrequestheader.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-authentication-basic.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-authentication-competing-names-passwords.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-authentication-prompt-manual.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-blob-with-no-mime-type.html [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-conditional.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-content-type-charset.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-content-type-string.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-data-blob.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-entity-body-basic.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-entity-body-empty.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-entity-body-get-head.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-entity-body-none.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-redirect-infinite.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-redirect-post-upload.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-response-upload-event-loadend.htm [ Timeout ] -Bug(none) external/wpt/XMLHttpRequest/send-response-upload-event-progress.htm [ Timeout ] -Bug(none) external/wpt/XMLHttpRequest/send-sync-blocks-async.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-sync-no-response-event-load.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-sync-no-response-event-loadend.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-sync-no-response-event-order.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-sync-response-event-order.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/send-sync-timeout.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/setrequestheader-case-insensitive.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/setrequestheader-header-forbidden.htm [ Failure ] -Bug(none) external/wpt/XMLHttpRequest/status-basic.htm [ Failure ] +Bug(none) external/wpt/XMLHttpRequest [ Failure Timeout ] Bug(none) fast/canvas/canvas-createImageBitmap-blob-in-workers.html [ Timeout ] Bug(none) fast/canvas/canvas-createImageBitmap-drawImage.html [ Failure ] Bug(none) fast/canvas/canvas-createImageBitmap-from-canvas-toBlob.html [ Timeout ] @@ -1424,7 +1371,7 @@ Bug(none) fast/files/read-blob-async.html [ Failure ] Bug(none) fast/files/read-file-async.html [ Failure ] Bug(none) fast/files/workers/inline-worker-via-blob-url.html [ Timeout ] -Bug(none) fast/files/workers/worker-apply-blob-url-to-xhr.html [ Timeout ] +Bug(none) fast/files/workers/worker-apply-blob-url-to-xhr.html [ Failure Timeout ] Bug(none) fast/files/workers/worker-read-blob-async.html [ Failure ] Bug(none) fast/files/workers/worker-read-blob-sync.html [ Failure ] Bug(none) fast/files/workers/worker-read-file-async.html [ Failure ] @@ -1517,6 +1464,10 @@ Bug(none) fast/xpath/4XPath/Borrowed/od_20000608.html [ Failure ] Bug(none) fast/xsl/document-function.xml [ Failure ] Bug(none) fast/xsl/dtd-in-source-document.xml [ Failure ] +Bug(none) fast/xsl/import-after-comment.xml [ Skip ] +Bug(none) fast/xsl/xslt-multiple-relative-import.xml [ Skip ] +Bug(none) fast/xsl/xslt-nested-stylesheets.xml [ Skip ] +Bug(none) fast/xsl/xslt-second-level-import.xml [ Skip ] Bug(none) fast/xsl/transform-xhr-doc.xhtml [ Failure ] Bug(none) fast/xsl/xslt-import-depth.xml [ Failure ] Bug(none) fast/xsl/xslt-import-enc16.xml [ Failure ] @@ -2363,191 +2314,7 @@ Bug(none) http/tests/websocket/workers/worker-reload.html [ Timeout ] Bug(none) http/tests/workers/shared-worker-secure-context.https.html [ Timeout ] Bug(none) http/tests/workers/text-encoding.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/abort-should-destroy-responseText.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-allow-lists-starting-with-comma.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-allow-access-control-origin-header-data-url.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-allow-access-control-origin-header.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-allow-star.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-allow.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-denied.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-get-fail-non-simple.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-non-simple-allow.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-non-simple-deny-cached.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-post-fail-non-simple-content-type.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-whitelist-request-headers.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-basic-whitelist-response-headers.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-async-header-denied.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-async-method-denied.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-async-not-supported.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-credential-sync.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-headers-async.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-headers-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-request-must-not-contain-cookie.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-sync-header-denied.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-sync-method-denied.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-preflight-sync-not-supported.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-response-with-body-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-sandboxed-iframe-allow-origin-null.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-sandboxed-iframe-allow.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-sandboxed-iframe-denied-without-wildcard.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/access-control-sandboxed-iframe-denied.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/async-xhr-revalidate-after-sync-xhr.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/authorization-header.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/binary-x-user-defined.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/blob-response-type-warm-cache.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/broken-xml-encoding.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/cache-override.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/cookies.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/cross-origin-cookie-storage.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/cross-origin-preflight-get-response-type-blob.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/cross-site-denied-response-sync-2.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/cross-site-denied-response-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/document-domain-set.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/duplicate-revalidation-reload.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/encode-request-url-2.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/encode-request-url.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/encoding-send-latin-1.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/event-target.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/exceptions.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/extra-parameters.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/failed-auth.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/filename-encoding.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/get-dangerous-headers.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/logout.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/methods-lower-case.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/methods.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/newline-in-request-uri.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/null-auth.php [ Failure ] -Bug(none) http/tests/xmlhttprequest/onloadend-event-after-sync-requests.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/open-async-overload.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/00.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/01.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/02.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/03.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/04.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/05.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/06.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/07.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/08.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/09.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/10.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/11.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/12.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/13.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/14.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/15.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/16.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/17.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/18.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/19.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/20.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/21.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/22.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/23.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/24.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/25.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/26.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/27.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/28.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/29.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/30.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/31.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/32.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/33.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/34.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/35.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/36.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/37.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/38.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/39.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/40.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/41.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/42.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/43.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/44.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/45.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/46.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-exact-matching/47.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-header-cross-origin-get-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-header-cross-origin-post-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-header-same-origin-get-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-header-same-origin-post-sync.html [ Timeout Failure ] -Bug(none) http/tests/xmlhttprequest/origin-whitelisting-all.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-whitelisting-exact-match.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-whitelisting-https.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-whitelisting-ip-addresses-with-subdomains.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-whitelisting-ip-addresses.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-whitelisting-removal.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/origin-whitelisting-subdomains.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/post-blob-content-type-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/post-content-type.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/post-formdata.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/post-with-boundary.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/redirect-cross-origin-tripmine.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/referer.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/remember-bad-password.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/reopen-encoding.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/request-encoding.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/request-encoding2.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/request-encoding3.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/request-encoding4.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/response-blob-mimetype.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/response-blob-size.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/response-encoding.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/response-encoding2.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/send-entity-body-basic.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/send-entity-body-charset.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/serialize-document.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/set-dangerous-headers.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/simple-cross-origin-denied-events-post-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/simple-cross-origin-denied-events-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/state-after-network-error.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/sync-after-async-same-resource.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/sync-repeated-and-caching.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/sync-xhr-revalidate-after-async-xhr.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-aborted.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-twice.html [ Failure Timeout ] -Bug(none) http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-aborted.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-simple.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-synconworker.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/timeout/xmlhttprequest-timeout-worker-twice.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/upload-onload-event.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/upload-onloadend-event-after-abort.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/upload-onloadend-event-after-load.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/upload-onloadend-event-after-sync-requests.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/upload-onprogress-event.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/upload-progress-events.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/web-apps/002-simple.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/002.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/003.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/004.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/005.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/007.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/008.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/010.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/011.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/012.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/014.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/015.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/web-apps/018.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/withCredentials-after-send.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/workers/post-formdata.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/workers/shared-worker-response-type-blob-sync.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/workers/shared-worker-response-type-blob.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/workers/upload-onprogress-event.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-sync.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob.html [ Timeout ] -Bug(none) http/tests/xmlhttprequest/xhr-to-blob-in-isolated-world.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xml-encoding.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-latin1.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-missing-file-exception.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-response-type-blob.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-setrequestheader-no-value.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-sync-no-progress-events.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-sync-no-timers.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-sync-vs-async-assertion-failure.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/xmlhttprequest-unload-sync.html [ Failure ] -Bug(none) http/tests/xmlhttprequest/zero-length-response-sync.html [ Failure ] +Bug(none) http/tests/xmlhttprequest [ Failure Timeout ] Bug(none) imagecapture/getPhotoCapabilities.html [ Timeout ] Bug(none) imagecapture/MediaStreamTrack-applyConstraints-getSettings.html [ Timeout ] Bug(none) imagecapture/MediaStreamTrack-applyConstraints-reject.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 1b9b127..a55a5a2 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -88,6 +88,8 @@ crbug.com/728566 virtual/gpu-rasterization/images/color-profile-background-image-cross-fade.html [ NeedsManualRebaseline ] crbug.com/728566 virtual/gpu-rasterization/images/color-profile-mask-image-svg.html [ NeedsManualRebaseline ] +crbug.com/722000 virtual/gpu/fast/canvas/canvas-ellipse-circumference-fill.html [ NeedsManualRebaseline ] + ########## Bugs to fix ########## # This is a missing event and increasing the timeout or using run-after-layout-and-paint doesn't # seem to fix it.
diff --git a/third_party/WebKit/LayoutTests/dom/README.md b/third_party/WebKit/LayoutTests/dom/README.md index 43589e6..6e6ea5e 100644 --- a/third_party/WebKit/LayoutTests/dom/README.md +++ b/third_party/WebKit/LayoutTests/dom/README.md
@@ -22,6 +22,10 @@ See [legacy_dom_conformance/README.md](legacy_dom_conformance/README.md) +* node/ + + For [Node interface](https://dom.spec.whatwg.org/#interface-node) + * parent_node/ For [ParentNode mixin](https://dom.spec.whatwg.org/#interface-parentnode)
diff --git a/third_party/WebKit/LayoutTests/dom/node/replace_child_recheck.html b/third_party/WebKit/LayoutTests/dom/node/replace_child_recheck.html new file mode 100644 index 0000000..26941413b --- /dev/null +++ b/third_party/WebKit/LayoutTests/dom/node/replace_child_recheck.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html> +<body> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<div id="parent"><br id="child"><br id="next"></div> +<script> +test(() => { + let parent = document.querySelector('#parent'); + parent.addEventListener('DOMSubtreeModified', () => { + document.body.appendChild(document.querySelector('#next')); + }, {once: true}); + let new_node = document.createElement('span'); + assert_throws('NotFoundError', () => { + parent.replaceChild(new_node, document.querySelector('#child')); + }); + assert_equals(parent.firstChild, null); + assert_equals(new_node.parentNode, null); + assert_equals(new_node.nextSibling, null); +}, 'Re-parenting a reference node should not crash replaceChild().'); +</script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-insertBefore-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-insertBefore-expected.txt deleted file mode 100644 index 884f0500..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-insertBefore-expected.txt +++ /dev/null
@@ -1,41 +0,0 @@ -This is a testharness.js-based test. -PASS Calling insertBefore with a non-Node first argument must throw TypeError. -PASS Calling insertBefore with a non-Node first argument on a leaf node DocumentType must throw TypeError. -PASS Calling insertBefore an a leaf node DocumentType must throw HIERARCHY_REQUEST_ERR. -PASS Calling insertBefore with a non-Node first argument on a leaf node Text must throw TypeError. -PASS Calling insertBefore an a leaf node Text must throw HIERARCHY_REQUEST_ERR. -PASS Calling insertBefore with a non-Node first argument on a leaf node Comment must throw TypeError. -PASS Calling insertBefore an a leaf node Comment must throw HIERARCHY_REQUEST_ERR. -PASS Calling insertBefore with a non-Node first argument on a leaf node ProcessingInstruction must throw TypeError. -PASS Calling insertBefore an a leaf node ProcessingInstruction must throw HIERARCHY_REQUEST_ERR. -PASS Calling insertBefore with an inclusive ancestor of the context object must throw HIERARCHY_REQUEST_ERR. -PASS Calling insertBefore with a reference child whose parent is not the context node must throw a NotFoundError. -PASS If the context node is a document, inserting a document or text node should throw a HierarchyRequestError. -PASS If the context node is a document, appending a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError. -PASS If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError. -PASS If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError. -FAIL If the context node is a document and a doctype is following the reference child, inserting a DocumentFragment with an element should throw a HierarchyRequestError. assert_throws: function "function () { - doc.insertBefore(df, doc.doctype); - }" did not throw -FAIL If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () { - doc.insertBefore(df, comment); - }" did not throw -PASS If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError. -FAIL If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () { - doc.insertBefore(a, doc.doctype); - }" did not throw -FAIL If the context node is a document and a doctype is following the reference child, inserting an element should throw a HierarchyRequestError. assert_throws: function "function () { - doc.insertBefore(a, comment); - }" did not throw -PASS If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError. -FAIL If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError. assert_throws: function "function () { - doc.insertBefore(doctype, comment); - }" did not throw -FAIL If the context node is a document with and element child, appending a doctype should throw a HierarchyRequestError. assert_throws: function "function () { - doc.insertBefore(doctype, null); - }" did not throw -PASS If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError. -PASS If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError. -PASS Inserting a node before itself should not move the node -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-replaceChild-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-replaceChild-expected.txt deleted file mode 100644 index 51224a08..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/dom/nodes/Node-replaceChild-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -This is a testharness.js-based test. -PASS Passing null to replaceChild should throw a TypeError. -PASS If child's parent is not the context node, a NotFoundError exception should be thrown -PASS If the context node is not a node that can contain children, a NotFoundError exception should be thrown -PASS If node is an inclusive ancestor of the context node, a HierarchyRequestError should be thrown. -PASS If the context node is a document, inserting a document or text node should throw a HierarchyRequestError. -PASS If the context node is a document, inserting a DocumentFragment that contains a text node or too many elements should throw a HierarchyRequestError. -PASS If the context node is a document (without element children), inserting a DocumentFragment that contains multiple elements should throw a HierarchyRequestError. -PASS If the context node is a document, inserting a DocumentFragment with an element if there already is an element child should throw a HierarchyRequestError. -FAIL If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () { - doc.replaceChild(df, comment); - }" did not throw -PASS If the context node is a document, inserting an element if there already is an element child should throw a HierarchyRequestError. -FAIL If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError. assert_throws: function "function () { - doc.replaceChild(a, comment); - }" did not throw -PASS If the context node is a document, inserting a doctype if there already is a doctype child should throw a HierarchyRequestError. -FAIL If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError. assert_throws: function "function () { - doc.replaceChild(doctype, comment); - }" did not throw -PASS If the context node is a DocumentFragment, inserting a document or a doctype should throw a HierarchyRequestError. -PASS If the context node is an element, inserting a document or a doctype should throw a HierarchyRequestError. -PASS Replacing a node with its next sibling should work (2 children) -PASS Replacing a node with its next sibling should work (4 children) -PASS Replacing a node with itself should not move the node -PASS If the context node is a document, inserting a new doctype should work. -PASS Replacing the document element with a DocumentFragment containing a single element should work. -PASS Replacing the document element with a DocumentFragment containing a single element and comments should work. -PASS Replacing the document element with a single element should work. -PASS replaceChild should work in the presence of mutation events. -PASS Replacing an element with a DocumentFragment should allow a child of the DocumentFragment to be found by Id. -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/Source/build/scripts/make_css_property_apis.py b/third_party/WebKit/Source/build/scripts/make_css_property_apis.py index 1b9448c..4c9fb60 100755 --- a/third_party/WebKit/Source/build/scripts/make_css_property_apis.py +++ b/third_party/WebKit/Source/build/scripts/make_css_property_apis.py
@@ -45,7 +45,6 @@ self._outputs = { 'CSSPropertyDescriptor.cpp': self.generate_property_descriptor_cpp, 'CSSPropertyDescriptor.h': self.generate_property_descriptor_h, - 'CSSPropertyAPI.h': self.generate_property_api, } # Stores a map of API method name -> (return_type, parameters) @@ -116,13 +115,6 @@ 'all_api_methods': self.all_api_methods, } - @template_expander.use_jinja('CSSPropertyAPI.h.tmpl') - def generate_property_api(self): - return { - 'ordered_api_method_names': self.ordered_api_method_names, - 'all_api_methods': self.all_api_methods, - } - # Provides a function object given the classname of the property. def generate_property_api_h_builder(self, api_classname, property_name): @template_expander.use_jinja('CSSPropertyAPIFiles.h.tmpl')
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPI.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPI.h.tmpl deleted file mode 100644 index e5ee163ef0..0000000 --- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPI.h.tmpl +++ /dev/null
@@ -1,48 +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 CSSPropertyAPI_h -#define CSSPropertyAPI_h - -#include "core/CSSPropertyNames.h" -#include "platform/wtf/Allocator.h" - -namespace blink { - -class CSSValue; -class CSSParserContext; -class CSSParserLocalContext; -class CSSParserTokenRange; - -// Base class for property APIs that contain logic for handling individual -// properties. -// The methods declared here are standard methods among property APIs, and can -// be called on a particular property API through a CSSPropertyDescriptor -// object. -// Note that not all methods are implemented by all property APIs. Methods that -// are not implemented on a property API will return nullptr when accessed -// through a CSSPropertyDescriptor. -// See the api_methods field on properties defined in CSSProperties.json5 for a -// definition of which methods are implemented on a property. -// -// Status (5th May 2017): Eventually, all property specific logic will be -// contained within property APIs that inherit from CSSPropertyAPI. -// Currently, the code base is in a transitional state and property specific -// logic is still scattered around the code base. -class CSSPropertyAPI { - STATIC_ONLY(CSSPropertyAPI); - - public: - {% for api_method_name in ordered_api_method_names %} - {% set api_method = all_api_methods[api_method_name] %} - {% if api_method.description %} - // {{api_method.description}} - {% endif %} - static {{api_method.return_type}} {{api_method_name}}{{api_method.parameters}}; - {% endfor %} -}; - -} // namespace blink - -#endif // CSSPropertyAPI_h
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl index b6c1b68..8213a8a2 100644 --- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyAPIFiles.h.tmpl
@@ -6,13 +6,13 @@ #define {{api_classname}}_h #include "core/CSSPropertyNames.h" -#include "core/css/properties/CSSPropertyAPI.h" namespace blink { class CSSParserTokenRange; class CSSParserContext; class CSSParserLocalContext; +class CSSValue; // {{api_classname}} is the API that contains logic // for handling the {{property_name}} property. @@ -23,7 +23,7 @@ // {{property_name}} property will be contained within // {{api_classname}}. Currently, the code base is in a transitional // state and property specific logic is still scattered around the code base. -class {{api_classname}} : public CSSPropertyAPI { +class {{api_classname}} { public: {% for api_method in all_api_methods if api_method in methods_for_class %} static {{all_api_methods[api_method].return_type}} {{api_method}}{{all_api_methods[api_method].parameters}};
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index 9e24917..389b4fa 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -450,11 +450,9 @@ "../build/scripts/templates/CSSPropertyDescriptor.cpp.tmpl", "../build/scripts/templates/CSSPropertyDescriptor.h.tmpl", "../build/scripts/templates/CSSPropertyAPIFiles.h.tmpl", - "../build/scripts/templates/CSSPropertyAPI.h.tmpl", ] in_files = [ "css/properties/CSSPropertyAPIMethods.json5" ] outputs = [ - "$blink_core_output_dir/css/properties/CSSPropertyAPI.h", "$blink_core_output_dir/css/properties/CSSPropertyAPIAlignItems.h", "$blink_core_output_dir/css/properties/CSSPropertyAPIAlignOrJustifyContent.h", "$blink_core_output_dir/css/properties/CSSPropertyAPIAlignOrJustifySelf.h", @@ -1446,6 +1444,7 @@ "//testing/gmock", "//testing/gtest", "//third_party/WebKit/Source/core/editing:unit_tests", + "//third_party/WebKit/Source/core/mojo:unit_tests", ] }
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index 7fd6171..d9b981b 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -38,7 +38,7 @@ // - api_class: true|"classname" // Specifies the existence (and optionally name) of a CSSPropertyAPI // implementation for the property to be used by make_css_property_apis.py. - // See core/css/properties/CSSPropertyAPI.h for API details. + // See core/css/properties/CSSPropertyAPI<PropertyName>.h for API details. // * Add this flag if the API has been implemented for this property. // * If the classname for this is different to the name of the property, specify a // value for this flag. e.g. api_class=CSSPropertyAPIWebkitPadding
diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp index 1f9836b..b1910ec 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
@@ -40,7 +40,6 @@ #include "core/css/parser/CSSVariableParser.h" #include "core/css/parser/FontVariantLigaturesParser.h" #include "core/css/parser/FontVariantNumericParser.h" -#include "core/css/properties/CSSPropertyAPI.h" #include "core/css/properties/CSSPropertyAlignmentUtils.h" #include "core/css/properties/CSSPropertyAnimationNameUtils.h" #include "core/css/properties/CSSPropertyColumnUtils.h"
diff --git a/third_party/WebKit/Source/core/css/properties/README.md b/third_party/WebKit/Source/core/css/properties/README.md index 35fad85..ae1a2ad 100644 --- a/third_party/WebKit/Source/core/css/properties/README.md +++ b/third_party/WebKit/Source/core/css/properties/README.md
@@ -21,6 +21,26 @@ [design doc](https://docs.google.com/document/d/1ywjUTmnxF5FXlpUTuLpint0w4TdSsjJzdWJqmhNzlss/edit#heading=h.1ckibme4i78b) for details of progress. +## Methods implemented by each property API + +Methods implemented by a property API depends on whether it is a longhand or shorthand property. +They implement different methods because a shorthand property will cease to exist after parsing is done. +It will not be relevant in subsequent operations, except for serialization. + +Each <LonghandProperty> has a property API called CSSPropertyAPI<LonghandProperty> and each <ShorthandProperty> +has a property API called CSSShorthandPropertyAPI<ShorthandProperty>. + +1. CSSPropertyAPI<LonghandProperty> + Aims to implement all property-specific logic for this longhand property. Currently(7/6/2017) it implements: + 1. static const CSSValue* parseSingleValue(CSSParserTokenRange&, const CSSParserContext&, const CSSParserLocalContext&); + - Parses a single CSS property and returns the corresponding CSSValue. If the input is invalid it returns nullptr. + +2. CSSShorthandPropertyAPI<ShorthandProperty> + Aims to implement all property-specific logic for this shorthand property. Currently(7/6/2017) it implements: + 1. static bool parseShorthand(bool important, CSSParserTokenRange&, const CSSParserContext*, HeapVector<CSSProperty, 256>& properties); + - Returns true if the property can be parsed as a shorthand. It also adds parsed properties to the `properties` set. + + ## How to add a new property API 1. Add a .cpp file to this directory named @@ -28,7 +48,7 @@ 2. Implement the property API in the .cpp file 1. Add `#include "core/css/properties/CSSPropertyAPI<Property/GroupName>.h"` (this will be a generated file) - 2. Implement the required methods on the API, e.g. `parseSingleValue` + 2. Implement the required methods on the API. 3. If logic is required by multiple property APIs you may need to create a new Utils file. 4. Add the new property to `core/css/CSSProperties.json5`. Ensure that you
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.cpp b/third_party/WebKit/Source/core/dom/ContainerNode.cpp index ffd506dd..071f762 100644 --- a/third_party/WebKit/Source/core/dom/ContainerNode.cpp +++ b/third_party/WebKit/Source/core/dom/ContainerNode.cpp
@@ -115,8 +115,10 @@ DISABLE_CFI_PERF bool ContainerNode::CheckAcceptChild(const Node* new_child, + const Node* next, const Node* old_child, ExceptionState& exception_state) const { + DCHECK(!(next && old_child)); // Not mentioned in spec: throw NotFoundError if newChild is null if (!new_child) { exception_state.ThrowDOMException(kNotFoundError, @@ -145,16 +147,17 @@ return false; } - return CheckAcceptChildGuaranteedNodeTypes(*new_child, old_child, + return CheckAcceptChildGuaranteedNodeTypes(*new_child, next, old_child, exception_state); } bool ContainerNode::CheckAcceptChildGuaranteedNodeTypes( const Node& new_child, + const Node* next, const Node* old_child, ExceptionState& exception_state) const { if (IsDocumentNode()) - return ToDocument(this)->CanAcceptChild(new_child, old_child, + return ToDocument(this)->CanAcceptChild(new_child, next, old_child, exception_state); // Skip containsIncludingHostElements() if !newChild.parentNode() && // isConnected(). |newChild| typically has no parentNode(), and it means @@ -212,7 +215,7 @@ // node. Firefox and Edge don't throw in this case. return false; } - if (!CheckAcceptChildGuaranteedNodeTypes(*child, old_child, + if (!CheckAcceptChildGuaranteedNodeTypes(*child, next, old_child, exception_state)) return false; } @@ -320,7 +323,7 @@ } // Make sure adding the new child is OK. - if (!CheckAcceptChild(new_child, 0, exception_state)) + if (!CheckAcceptChild(new_child, ref_child, nullptr, exception_state)) return new_child; DCHECK(new_child); @@ -388,7 +391,7 @@ return true; // TODO(esprehn): Are there other conditions where the parser can create // invalid trees? - return ToDocument(*this).CanAcceptChild(new_child, nullptr, + return ToDocument(*this).CanAcceptChild(new_child, nullptr, nullptr, IGNORE_EXCEPTION_FOR_TESTING); } @@ -450,7 +453,7 @@ // doctype and parent is not a document, throw a HierarchyRequestError. // 6. If parent is a document, and any of the statements below, switched on // node, are true, throw a HierarchyRequestError. - if (!CheckAcceptChild(new_child, old_child, exception_state)) + if (!CheckAcceptChild(new_child, nullptr, old_child, exception_state)) return old_child; // 3. If child’s parent is not parent, then throw a NotFoundError. @@ -499,9 +502,18 @@ return nullptr; } - // Does this one more time because removeChild() fires a MutationEvent. - if (!CheckAcceptChild(new_child, old_child, exception_state)) + // Check DOM structure one more time because removeChild() above fires + // synchronous events. + if (!CheckAcceptChild(new_child, nullptr, old_child, exception_state)) return old_child; + if (next && next->parentNode() != this) { + exception_state.ThrowDOMException( + kNotFoundError, + "The node before which the new node is to " + "be inserted is not a child of this " + "node."); + return old_child; + } // 13. Let nodes be node’s children if node is a DocumentFragment node, and // a list containing solely node otherwise. @@ -734,7 +746,7 @@ Node* ContainerNode::AppendChild(Node* new_child, ExceptionState& exception_state) { // Make sure adding the new child is ok - if (!CheckAcceptChild(new_child, 0, exception_state)) + if (!CheckAcceptChild(new_child, nullptr, nullptr, exception_state)) return new_child; DCHECK(new_child);
diff --git a/third_party/WebKit/Source/core/dom/ContainerNode.h b/third_party/WebKit/Source/core/dom/ContainerNode.h index 397c2e2..72db2f3 100644 --- a/third_party/WebKit/Source/core/dom/ContainerNode.h +++ b/third_party/WebKit/Source/core/dom/ContainerNode.h
@@ -419,9 +419,11 @@ NodeVector&, ExceptionState&) const; inline bool CheckAcceptChildGuaranteedNodeTypes(const Node& new_child, + const Node* next, const Node* old_child, ExceptionState&) const; inline bool CheckAcceptChild(const Node* new_child, + const Node* next, const Node* old_child, ExceptionState&) const; inline bool CheckParserAcceptChild(const Node& new_child) const;
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index 4e88854..dd13c4ad 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -3868,27 +3868,68 @@ return false; } +// This is an implementation of step 6 of +// https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity +// and https://dom.spec.whatwg.org/#concept-node-replace . +// +// 6. If parent is a document, and any of the statements below, switched on +// node, are true, throw a HierarchyRequestError. +// -> DocumentFragment node +// If node has more than one element child or has a Text node child. +// Otherwise, if node has one element child and either parent has an element +// child, child is a doctype, or child is not null and a doctype is +// following child. +// -> element +// parent has an element child, child is a doctype, or child is not null and +// a doctype is following child. +// -> doctype +// parent has a doctype child, child is non-null and an element is preceding +// child, or child is null and parent has an element child. +// +// 6. If parent is a document, and any of the statements below, switched on +// node, are true, throw a HierarchyRequestError. +// -> DocumentFragment node +// If node has more than one element child or has a Text node child. +// Otherwise, if node has one element child and either parent has an element +// child that is not child or a doctype is following child. +// -> element +// parent has an element child that is not child or a doctype is following +// child. +// -> doctype +// parent has a doctype child that is not child, or an element is preceding +// child. bool Document::CanAcceptChild(const Node& new_child, + const Node* next, const Node* old_child, ExceptionState& exception_state) const { + DCHECK(!(next && old_child)); if (old_child && old_child->getNodeType() == new_child.getNodeType()) return true; int num_doctypes = 0; int num_elements = 0; + bool has_doctype_after_reference_node = false; + bool has_element_after_reference_node = false; // First, check how many doctypes and elements we have, not counting // the child we're about to remove. + bool saw_reference_node = false; for (Node& child : NodeTraversal::ChildrenOf(*this)) { - if (old_child && *old_child == child) + if (old_child && *old_child == child) { + saw_reference_node = true; continue; + } + if (&child == next) + saw_reference_node = true; switch (child.getNodeType()) { case kDocumentTypeNode: num_doctypes++; + has_doctype_after_reference_node = saw_reference_node; break; case kElementNode: num_elements++; + has_element_after_reference_node = saw_reference_node; break; default: break; @@ -3918,6 +3959,12 @@ break; case kElementNode: num_elements++; + if (has_doctype_after_reference_node) { + exception_state.ThrowDOMException( + kHierarchyRequestError, + "Can't insert an element before a doctype."); + return false; + } break; } } @@ -3938,9 +3985,21 @@ return true; case kDocumentTypeNode: num_doctypes++; + if (num_elements > 0 && !has_element_after_reference_node) { + exception_state.ThrowDOMException( + kHierarchyRequestError, + "Can't insert a doctype before the root element."); + return false; + } break; case kElementNode: num_elements++; + if (has_doctype_after_reference_node) { + exception_state.ThrowDOMException( + kHierarchyRequestError, + "Can't insert an element before a doctype."); + return false; + } break; } }
diff --git a/third_party/WebKit/Source/core/dom/Document.h b/third_party/WebKit/Source/core/dom/Document.h index b95f82ec..efed3a4 100644 --- a/third_party/WebKit/Source/core/dom/Document.h +++ b/third_party/WebKit/Source/core/dom/Document.h
@@ -766,6 +766,7 @@ // nodeWillBeRemoved is only safe when removing one node at a time. void NodeWillBeRemoved(Node&); bool CanAcceptChild(const Node& new_child, + const Node* next, const Node* old_child, ExceptionState&) const;
diff --git a/third_party/WebKit/Source/core/mojo/BUILD.gn b/third_party/WebKit/Source/core/mojo/BUILD.gn index 202d78e..aaa52ac 100644 --- a/third_party/WebKit/Source/core/mojo/BUILD.gn +++ b/third_party/WebKit/Source/core/mojo/BUILD.gn
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//mojo/public/tools/bindings/mojom.gni") import("//third_party/WebKit/Source/core/core.gni") blink_core_sources("mojo") { @@ -23,3 +24,39 @@ "//services/service_manager/public/cpp", ] } + +source_set("unit_tests") { + testonly = true + sources = [ + "tests/JsToCppTest.cpp", + ] + + data = [ + "tests/JsToCppTest.js", + ] + + configs += [ + "//third_party/WebKit/Source/core:blink_core_pch", + "//third_party/WebKit/Source:config", + "//third_party/WebKit/Source:inside_blink", + ] + + deps = [ + ":test_bindings_blink", + "//mojo/public/cpp/bindings", + "//testing/gtest", + "//third_party/WebKit/Source/core:core", + "//third_party/WebKit/Source/core:testing", + ] + + data_deps = [ + ":test_bindings", # For JS bindings: crbug.com/729649. + "//mojo/public/js:new_bindings", + ] +} + +mojom("test_bindings") { + sources = [ + "tests/JsToCpp.mojom", + ] +}
diff --git a/mojo/edk/js/tests/js_to_cpp.mojom b/third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom similarity index 100% rename from mojo/edk/js/tests/js_to_cpp.mojom rename to third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom
diff --git a/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp b/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp new file mode 100644 index 0000000..2b7ada7a0 --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.cpp
@@ -0,0 +1,435 @@ +// 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 "bindings/core/v8/ScriptController.h" +#include "bindings/core/v8/ScriptSourceCode.h" +#include "bindings/core/v8/V8BindingForCore.h" +#include "bindings/core/v8/V8BindingForTesting.h" +#include "bindings/core/v8/V8ScriptRunner.h" +#include "core/frame/Settings.h" +#include "core/mojo/MojoHandle.h" +#include "core/page/Page.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/system/wait.h" +#include "platform/testing/UnitTestHelpers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom-blink.h" + +namespace blink { +namespace { + +// Global value updated by some checks to prevent compilers from optimizing +// reads out of existence. +uint32_t g_waste_accumulator = 0; + +// Negative numbers with different values in each byte, the last of +// which can survive promotion to double and back. +const int8_t kExpectedInt8Value = -65; +const int16_t kExpectedInt16Value = -16961; +const int32_t kExpectedInt32Value = -1145258561; +const int64_t kExpectedInt64Value = -77263311946305LL; + +// Positive numbers with different values in each byte, the last of +// which can survive promotion to double and back. +const uint8_t kExpectedUInt8Value = 65; +const uint16_t kExpectedUInt16Value = 16961; +const uint32_t kExpectedUInt32Value = 1145258561; +const uint64_t kExpectedUInt64Value = 77263311946305LL; + +// Double/float values, including special case constants. +const double kExpectedDoubleVal = 3.14159265358979323846; +const double kExpectedDoubleInf = std::numeric_limits<double>::infinity(); +const double kExpectedDoubleNan = std::numeric_limits<double>::quiet_NaN(); +const float kExpectedFloatVal = static_cast<float>(kExpectedDoubleVal); +const float kExpectedFloatInf = std::numeric_limits<float>::infinity(); +const float kExpectedFloatNan = std::numeric_limits<float>::quiet_NaN(); + +// NaN has the property that it is not equal to itself. +#define EXPECT_NAN(x) EXPECT_NE(x, x) + +String MojoBindingsScriptPath() { + String filepath = testing::ExecutableDir(); + filepath.append("/gen/mojo/public/js/mojo_bindings.js"); + return filepath; +} + +String TestBindingsScriptPath() { + String filepath = testing::ExecutableDir(); + filepath.append( + "/gen/third_party/WebKit/Source/core/mojo/tests/JsToCpp.mojom.js"); + return filepath; +} + +String TestScriptPath() { + String filepath = testing::BlinkRootDir(); + filepath.append("/Source/core/mojo/tests/JsToCppTest.js"); + return filepath; +} + +v8::Local<v8::Value> ExecuteScript(const String& script_path, + LocalFrame& frame) { + RefPtr<SharedBuffer> script_src = testing::ReadFromFile(script_path); + return frame.GetScriptController().ExecuteScriptInMainWorldAndReturnValue( + ScriptSourceCode(String(script_src->Data(), script_src->size()))); +} + +void CheckDataPipe(mojo::DataPipeConsumerHandle data_pipe_handle) { + const void* buffer = nullptr; + unsigned num_bytes = 0; + MojoResult result = Wait(data_pipe_handle, MOJO_HANDLE_SIGNAL_READABLE); + EXPECT_EQ(MOJO_RESULT_OK, result); + result = BeginReadDataRaw(data_pipe_handle, &buffer, &num_bytes, + MOJO_READ_DATA_FLAG_NONE); + EXPECT_EQ(MOJO_RESULT_OK, result); + EXPECT_EQ(64u, num_bytes); + for (unsigned i = 0; i < num_bytes; ++i) { + EXPECT_EQ(i, static_cast<unsigned>(static_cast<const char*>(buffer)[i])); + } + EndReadDataRaw(data_pipe_handle, num_bytes); +} + +void CheckMessagePipe(mojo::MessagePipeHandle message_pipe_handle) { + unsigned char buffer[100]; + uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); + MojoResult result = Wait(message_pipe_handle, MOJO_HANDLE_SIGNAL_READABLE); + EXPECT_EQ(MOJO_RESULT_OK, result); + result = ReadMessageRaw(message_pipe_handle, buffer, &buffer_size, 0, 0, 0); + EXPECT_EQ(MOJO_RESULT_OK, result); + EXPECT_EQ(64u, buffer_size); + for (int i = 0; i < 64; ++i) { + EXPECT_EQ(255 - i, buffer[i]); + } +} + +js_to_cpp::blink::EchoArgsPtr BuildSampleEchoArgs() { + auto args = js_to_cpp::blink::EchoArgs::New(); + args->si64 = kExpectedInt64Value; + args->si32 = kExpectedInt32Value; + args->si16 = kExpectedInt16Value; + args->si8 = kExpectedInt8Value; + args->ui64 = kExpectedUInt64Value; + args->ui32 = kExpectedUInt32Value; + args->ui16 = kExpectedUInt16Value; + args->ui8 = kExpectedUInt8Value; + args->float_val = kExpectedFloatVal; + args->float_inf = kExpectedFloatInf; + args->float_nan = kExpectedFloatNan; + args->double_val = kExpectedDoubleVal; + args->double_inf = kExpectedDoubleInf; + args->double_nan = kExpectedDoubleNan; + args->name = "coming"; + args->string_array.emplace(3); + (*args->string_array)[0] = "one"; + (*args->string_array)[1] = "two"; + (*args->string_array)[2] = "three"; + return args; +} + +void CheckSampleEchoArgs(const js_to_cpp::blink::EchoArgsPtr& arg) { + EXPECT_EQ(kExpectedInt64Value, arg->si64); + EXPECT_EQ(kExpectedInt32Value, arg->si32); + EXPECT_EQ(kExpectedInt16Value, arg->si16); + EXPECT_EQ(kExpectedInt8Value, arg->si8); + EXPECT_EQ(kExpectedUInt64Value, arg->ui64); + EXPECT_EQ(kExpectedUInt32Value, arg->ui32); + EXPECT_EQ(kExpectedUInt16Value, arg->ui16); + EXPECT_EQ(kExpectedUInt8Value, arg->ui8); + EXPECT_EQ(kExpectedFloatVal, arg->float_val); + EXPECT_EQ(kExpectedFloatInf, arg->float_inf); + EXPECT_NAN(arg->float_nan); + EXPECT_EQ(kExpectedDoubleVal, arg->double_val); + EXPECT_EQ(kExpectedDoubleInf, arg->double_inf); + EXPECT_NAN(arg->double_nan); + EXPECT_EQ(String("coming"), arg->name); + EXPECT_EQ(String("one"), (*arg->string_array)[0]); + EXPECT_EQ(String("two"), (*arg->string_array)[1]); + EXPECT_EQ(String("three"), (*arg->string_array)[2]); + CheckDataPipe(arg->data_handle.get()); + CheckMessagePipe(arg->message_handle.get()); +} + +void CheckSampleEchoArgsList(const js_to_cpp::blink::EchoArgsListPtr& list) { + if (list.is_null()) + return; + CheckSampleEchoArgs(list->item); + CheckSampleEchoArgsList(list->next); +} + +// More forgiving checks are needed in the face of potentially corrupt +// messages. The values don't matter so long as all accesses are within +// bounds. +void CheckCorruptedString(const String& arg) { + for (size_t i = 0; i < arg.length(); ++i) + g_waste_accumulator += arg[i]; +} + +void CheckCorruptedStringArray(const Optional<Vector<String>>& string_array) { + if (!string_array) + return; + for (size_t i = 0; i < string_array->size(); ++i) + CheckCorruptedString((*string_array)[i]); +} + +void CheckCorruptedDataPipe(mojo::DataPipeConsumerHandle data_pipe_handle) { + unsigned char buffer[100]; + uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); + MojoResult result = ReadDataRaw(data_pipe_handle, buffer, &buffer_size, + MOJO_READ_DATA_FLAG_NONE); + if (result != MOJO_RESULT_OK) + return; + for (uint32_t i = 0; i < buffer_size; ++i) + g_waste_accumulator += buffer[i]; +} + +void CheckCorruptedMessagePipe(mojo::MessagePipeHandle message_pipe_handle) { + unsigned char buffer[100]; + uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); + MojoResult result = + ReadMessageRaw(message_pipe_handle, buffer, &buffer_size, 0, 0, 0); + if (result != MOJO_RESULT_OK) + return; + for (uint32_t i = 0; i < buffer_size; ++i) + g_waste_accumulator += buffer[i]; +} + +void CheckCorruptedEchoArgs(const js_to_cpp::blink::EchoArgsPtr& arg) { + if (arg.is_null()) + return; + CheckCorruptedString(arg->name); + CheckCorruptedStringArray(arg->string_array); + if (arg->data_handle.is_valid()) + CheckCorruptedDataPipe(arg->data_handle.get()); + if (arg->message_handle.is_valid()) + CheckCorruptedMessagePipe(arg->message_handle.get()); +} + +void CheckCorruptedEchoArgsList(const js_to_cpp::blink::EchoArgsListPtr& list) { + if (list.is_null()) + return; + CheckCorruptedEchoArgs(list->item); + CheckCorruptedEchoArgsList(list->next); +} + +// Base Provider implementation class. It's expected that tests subclass and +// override the appropriate Provider functions. When test is done quit the +// run_loop(). +class CppSideConnection : public js_to_cpp::blink::CppSide { + public: + CppSideConnection() : mishandled_messages_(0), binding_(this) {} + ~CppSideConnection() override {} + + void set_js_side(js_to_cpp::blink::JsSidePtr js_side) { + js_side_ = std::move(js_side); + } + js_to_cpp::blink::JsSide* js_side() { return js_side_.get(); } + + void Bind(mojo::InterfaceRequest<js_to_cpp::blink::CppSide> request) { + binding_.Bind(std::move(request)); + // Keep the pipe open even after validation errors. + binding_.EnableTestingMode(); + } + + // js_to_cpp::CppSide: + void StartTest() override { NOTREACHED(); } + + void TestFinished() override { NOTREACHED(); } + + void PingResponse() override { mishandled_messages_ += 1; } + + void EchoResponse(js_to_cpp::blink::EchoArgsListPtr list) override { + mishandled_messages_ += 1; + } + + void BitFlipResponse( + js_to_cpp::blink::EchoArgsListPtr list, + js_to_cpp::blink::ForTestingAssociatedPtrInfo not_used) override { + mishandled_messages_ += 1; + } + + void BackPointerResponse(js_to_cpp::blink::EchoArgsListPtr list) override { + mishandled_messages_ += 1; + } + + protected: + js_to_cpp::blink::JsSidePtr js_side_; + int mishandled_messages_; + mojo::Binding<js_to_cpp::blink::CppSide> binding_; +}; + +// Trivial test to verify a message sent from JS is received. +class PingCppSideConnection : public CppSideConnection { + public: + PingCppSideConnection() : got_message_(false) {} + ~PingCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { js_side_->Ping(); } + + void PingResponse() override { + got_message_ = true; + testing::ExitRunLoop(); + } + + bool DidSucceed() { return got_message_ && !mishandled_messages_; } + + private: + bool got_message_; +}; + +// Test that parameters are passed with correct values. +class EchoCppSideConnection : public CppSideConnection { + public: + EchoCppSideConnection() : message_count_(0), termination_seen_(false) {} + ~EchoCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { + js_side_->Echo(kExpectedMessageCount, BuildSampleEchoArgs()); + } + + void EchoResponse(js_to_cpp::blink::EchoArgsListPtr list) override { + message_count_ += 1; + + const js_to_cpp::blink::EchoArgsPtr& special_arg = list->item; + EXPECT_EQ(-1, special_arg->si64); + EXPECT_EQ(-1, special_arg->si32); + EXPECT_EQ(-1, special_arg->si16); + EXPECT_EQ(-1, special_arg->si8); + EXPECT_EQ(String("going"), special_arg->name); + CheckDataPipe(special_arg->data_handle.get()); + CheckMessagePipe(special_arg->message_handle.get()); + + CheckSampleEchoArgsList(list->next); + } + + void TestFinished() override { + termination_seen_ = true; + testing::ExitRunLoop(); + } + + bool DidSucceed() { + return termination_seen_ && !mishandled_messages_ && + message_count_ == kExpectedMessageCount; + } + + private: + static const int kExpectedMessageCount = 10; + int message_count_; + bool termination_seen_; +}; + +// Test that corrupted messages don't wreak havoc. +class BitFlipCppSideConnection : public CppSideConnection { + public: + BitFlipCppSideConnection() : termination_seen_(false) {} + ~BitFlipCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { js_side_->BitFlip(BuildSampleEchoArgs()); } + + void BitFlipResponse( + js_to_cpp::blink::EchoArgsListPtr list, + js_to_cpp::blink::ForTestingAssociatedPtrInfo not_used) override { + CheckCorruptedEchoArgsList(list); + } + + void TestFinished() override { + termination_seen_ = true; + testing::ExitRunLoop(); + } + + bool DidSucceed() { return termination_seen_; } + + private: + bool termination_seen_; +}; + +// Test that severely random messages don't wreak havoc. +class BackPointerCppSideConnection : public CppSideConnection { + public: + BackPointerCppSideConnection() : termination_seen_(false) {} + ~BackPointerCppSideConnection() override {} + + // js_to_cpp::CppSide: + void StartTest() override { js_side_->BackPointer(BuildSampleEchoArgs()); } + + void BackPointerResponse(js_to_cpp::blink::EchoArgsListPtr list) override { + CheckCorruptedEchoArgsList(list); + } + + void TestFinished() override { + termination_seen_ = true; + testing::ExitRunLoop(); + } + + bool DidSucceed() { return termination_seen_; } + + private: + bool termination_seen_; +}; + +class JsToCppTest : public ::testing::Test { + public: + void RunTest(CppSideConnection* cpp_side) { + js_to_cpp::blink::CppSidePtr cpp_side_ptr; + cpp_side->Bind(MakeRequest(&cpp_side_ptr)); + + js_to_cpp::blink::JsSidePtr js_side_ptr; + auto js_side_request = MakeRequest(&js_side_ptr); + js_side_ptr->SetCppSide(std::move(cpp_side_ptr)); + cpp_side->set_js_side(std::move(js_side_ptr)); + + V8TestingScope scope; + scope.GetPage().GetSettings().SetScriptEnabled(true); + ExecuteScript(MojoBindingsScriptPath(), scope.GetFrame()); + ExecuteScript(TestBindingsScriptPath(), scope.GetFrame()); + + v8::Local<v8::Value> start_fn = + ExecuteScript(TestScriptPath(), scope.GetFrame()); + ASSERT_FALSE(start_fn.IsEmpty()); + ASSERT_TRUE(start_fn->IsFunction()); + v8::Local<v8::Object> global_proxy = scope.GetContext()->Global(); + v8::Local<v8::Value> args[1] = { + ToV8(MojoHandle::Create( + mojo::ScopedHandle::From(js_side_request.PassMessagePipe())), + global_proxy, scope.GetIsolate())}; + V8ScriptRunner::CallFunction( + start_fn.As<v8::Function>(), scope.GetExecutionContext(), global_proxy, + WTF_ARRAY_LENGTH(args), args, scope.GetIsolate()); + testing::EnterRunLoop(); + } +}; + +TEST_F(JsToCppTest, Ping) { + PingCppSideConnection cpp_side_connection; + RunTest(&cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +TEST_F(JsToCppTest, Echo) { + EchoCppSideConnection cpp_side_connection; + RunTest(&cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +TEST_F(JsToCppTest, BitFlip) { + // These tests generate a lot of expected validation errors. Suppress logging. + mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; + + BitFlipCppSideConnection cpp_side_connection; + RunTest(&cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +TEST_F(JsToCppTest, BackPointer) { + // These tests generate a lot of expected validation errors. Suppress logging. + mojo::internal::ScopedSuppressValidationErrorLoggingForTests log_suppression; + + BackPointerCppSideConnection cpp_side_connection; + RunTest(&cpp_side_connection); + EXPECT_TRUE(cpp_side_connection.DidSucceed()); +} + +} // namespace +} // namespace blink
diff --git a/mojo/edk/js/tests/js_to_cpp_tests.js b/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.js similarity index 74% rename from mojo/edk/js/tests/js_to_cpp_tests.js rename to third_party/WebKit/Source/core/mojo/tests/JsToCppTest.js index 6ffce09..139687a 100644 --- a/mojo/edk/js/tests/js_to_cpp_tests.js +++ b/third_party/WebKit/Source/core/mojo/tests/JsToCppTest.js
@@ -2,26 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -define('mojo/edk/js/tests/js_to_cpp_tests', [ - 'console', - 'mojo/edk/js/tests/js_to_cpp.mojom', - 'mojo/public/js/bindings', - 'mojo/public/js/connector', - 'mojo/public/js/core', -], function (console, jsToCpp, bindings, connector, core) { +(function () { var retainedJsSide; - var retainedJsSideStub; var sampleData; var sampleMessage; var BAD_VALUE = 13; var DATA_PIPE_PARAMS = { - flags: core.CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, elementNumBytes: 1, capacityNumBytes: 64 }; function JsSideConnection() { - this.binding = new bindings.Binding(jsToCpp.JsSide, this); + this.binding = new mojo.Binding(jsToCpp.JsSide, this); } JsSideConnection.prototype.setCppSide = function(cppSide) { @@ -55,13 +47,13 @@ arg.si8 = BAD_VALUE; for (i = 0; i < numIterations; ++i) { - dataPipe1 = core.createDataPipe(DATA_PIPE_PARAMS); - dataPipe2 = core.createDataPipe(DATA_PIPE_PARAMS); - messagePipe1 = core.createMessagePipe(); - messagePipe2 = core.createMessagePipe(); + dataPipe1 = Mojo.createDataPipe(DATA_PIPE_PARAMS); + dataPipe2 = Mojo.createDataPipe(DATA_PIPE_PARAMS); + messagePipe1 = Mojo.createMessagePipe(); + messagePipe2 = Mojo.createMessagePipe(); - arg.data_handle = dataPipe1.consumerHandle; - arg.message_handle = messagePipe1.handle1; + arg.dataHandle = dataPipe1.consumer; + arg.messageHandle = messagePipe1.handle1; specialArg = new jsToCpp.EchoArgs(); specialArg.si64 = -1; @@ -69,20 +61,19 @@ specialArg.si16 = -1; specialArg.si8 = -1; specialArg.name = 'going'; - specialArg.data_handle = dataPipe2.consumerHandle; - specialArg.message_handle = messagePipe2.handle1; + specialArg.dataHandle = dataPipe2.consumer; + specialArg.messageHandle = messagePipe2.handle1; writeDataPipe(dataPipe1, sampleData); writeDataPipe(dataPipe2, sampleData); writeMessagePipe(messagePipe1, sampleMessage); writeMessagePipe(messagePipe2, sampleMessage); - this.cppSide_.echoResponse(createEchoArgsList(specialArg, arg)); - core.close(dataPipe1.producerHandle); - core.close(dataPipe2.producerHandle); - core.close(messagePipe1.handle0); - core.close(messagePipe2.handle0); + dataPipe1.producer.close(); + dataPipe2.producer.close(); + messagePipe1.handle0.close(); + messagePipe2.handle0.close(); } this.cppSide_.testFinished(); }; @@ -91,7 +82,7 @@ var iteration = 0; var dataPipe; var messagePipe; - var proto = connector.Connector.prototype; + var proto = mojo.internal.Connector.prototype; var stopSignalled = false; proto.realAccept = proto.accept; @@ -110,13 +101,13 @@ }; while (!stopSignalled) { - messagePipe = core.createMessagePipe(); + messagePipe = Mojo.createMessagePipe(); writeMessagePipe(messagePipe, sampleMessage); - arg.message_handle = messagePipe.handle1; + arg.messageHandle = messagePipe.handle1; this.cppSide_.bitFlipResponse(createEchoArgsList(arg), null); - core.close(messagePipe.handle0); + messagePipe.handle0.close(); iteration += 1; } @@ -129,7 +120,7 @@ var iteration = 0; var dataPipe; var messagePipe; - var proto = connector.Connector.prototype; + var proto = mojo.internal.Connector.prototype; var stopSignalled = false; proto.realAccept = proto.accept; @@ -146,13 +137,13 @@ }; while (!stopSignalled) { - messagePipe = core.createMessagePipe(); + messagePipe = Mojo.createMessagePipe(); writeMessagePipe(messagePipe, sampleMessage); - arg.message_handle = messagePipe.handle1; + arg.messageHandle = messagePipe.handle1; this.cppSide_.backPointerResponse(createEchoArgsList(arg)); - core.close(messagePipe.handle0); + messagePipe.handle0.close(); iteration += 1; } @@ -162,10 +153,9 @@ }; function writeDataPipe(pipe, data) { - var writeResult = core.writeData( - pipe.producerHandle, data, core.WRITE_DATA_FLAG_ALL_OR_NONE); + var writeResult = pipe.producer.writeData(data); - if (writeResult.result != core.RESULT_OK) { + if (writeResult.result != Mojo.RESULT_OK) { console.log('ERROR: Data pipe write result was ' + writeResult.result); return false; } @@ -177,8 +167,8 @@ } function writeMessagePipe(pipe, arrayBuffer) { - var result = core.writeMessage(pipe.handle0, arrayBuffer, [], 0); - if (result != core.RESULT_OK) { + var result = pipe.handle0.writeMessage(arrayBuffer, []); + if (result != Mojo.RESULT_OK) { console.log('ERROR: Message pipe write result was ' + result); return false; } @@ -212,4 +202,4 @@ retainedJsSide = new JsSideConnection; retainedJsSide.binding.bind(jsSideRequestHandle); }; -}); +})();
diff --git a/third_party/WebKit/Source/core/mojo/tests/OWNERS b/third_party/WebKit/Source/core/mojo/tests/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/third_party/WebKit/Source/core/mojo/tests/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index 9c3ea0f..f165b66 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -711,6 +711,19 @@ UI._windowFocused = function(document, event) { if (event.target.document.nodeType === Node.DOCUMENT_NODE) document.body.classList.remove('inactive'); + UI._keyboardFocus = true; + var listener = () => { + var activeElement = document.deepActiveElement(); + if (activeElement) + activeElement.removeAttribute('data-keyboard-focus'); + UI._keyboardFocus = false; + }; + document.defaultView.requestAnimationFrame(() => { + UI._keyboardFocus = false; + document.removeEventListener('mousedown', listener, true); + }); + document.addEventListener('mousedown', listener, true); + }; /**
diff --git a/third_party/WebKit/Source/platform/instrumentation/tracing/web_process_memory_dump_test.cc b/third_party/WebKit/Source/platform/instrumentation/tracing/web_process_memory_dump_test.cc index 94dfc59..a3e3353 100644 --- a/third_party/WebKit/Source/platform/instrumentation/tracing/web_process_memory_dump_test.cc +++ b/third_party/WebKit/Source/platform/instrumentation/tracing/web_process_memory_dump_test.cc
@@ -115,10 +115,12 @@ auto wmad4 = wpmd1->CreateMemoryAllocatorDump("1/4"); wpmd1->AddOwnershipEdge(wmad4->Guid(), guid); auto allocator_dumps_edges = - wpmd1->process_memory_dump()->allocator_dumps_edges(); + wpmd1->process_memory_dump()->allocator_dumps_edges_for_testing(); ASSERT_EQ(1u, allocator_dumps_edges.size()); - ASSERT_EQ(wmad4->Guid(), allocator_dumps_edges[0].source.ToUint64()); - ASSERT_EQ(guid, allocator_dumps_edges[0].target.ToUint64()); + auto it = allocator_dumps_edges.begin(); + ASSERT_NE(allocator_dumps_edges.end(), it); + ASSERT_EQ(wmad4->Guid(), it->first.ToUint64()); + ASSERT_EQ(guid, it->second.target.ToUint64()); // Check that createDumpAdapterForSkia() works. auto skia_trace_memory_dump = wpmd1->CreateDumpAdapterForSkia("1/skia");
diff --git a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp index d0e10b6..2f6d1541 100644 --- a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp +++ b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.cpp
@@ -89,6 +89,12 @@ return FilePathToWebString(BlinkRootFilePath()); } +String ExecutableDir() { + base::FilePath path; + base::PathService::Get(base::DIR_EXE, &path); + return FilePathToWebString(base::MakeAbsoluteFilePath(path)); +} + String WebTestDataPath(const String& relative_path) { return FilePathToWebString( BlinkRootFilePath()
diff --git a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h index 3b94f961..6f18cad 100644 --- a/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h +++ b/third_party/WebKit/Source/platform/testing/UnitTestHelpers.h
@@ -52,6 +52,9 @@ // /src/third_party/WebKit. String BlinkRootDir(); +// Returns directory containing the current executable as absolute path. +String ExecutableDir(); + // Returns test data absolute path for webkit_unit_tests, i.e. // <blinkRootDir>/Source/web/tests/data/<relativePath>. // It returns the top web test directory if |relativePath| was not specified.
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp index 3a276ad..a03ded1d 100644 --- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp +++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.cpp
@@ -259,17 +259,12 @@ inspected_frames_( InspectedFrames::Create(web_local_frame_impl_->GetFrame())), resource_container_(new InspectorResourceContainer(inspected_frames_)), - page_agent_(nullptr), - network_agent_(nullptr), - layer_tree_agent_(nullptr), - tracing_agent_(nullptr), - trace_events_agent_(new InspectorTraceEvents()), - overlay_agent_(nullptr), + trace_events_(new InspectorTraceEvents()), include_view_agents_(include_view_agents), layer_tree_id_(0) { DCHECK(IsMainThread()); DCHECK(web_local_frame_impl_->GetFrame()); - probe_sink_->addInspectorTraceEvents(trace_events_agent_); + probe_sink_->addInspectorTraceEvents(trace_events_); } WebDevToolsAgentImpl::~WebDevToolsAgentImpl() { @@ -282,138 +277,149 @@ visitor->Trace(resource_content_loader_); visitor->Trace(inspected_frames_); visitor->Trace(resource_container_); - visitor->Trace(page_agent_); - visitor->Trace(network_agent_); - visitor->Trace(layer_tree_agent_); - visitor->Trace(tracing_agent_); - visitor->Trace(trace_events_agent_); - visitor->Trace(overlay_agent_); - visitor->Trace(session_); + visitor->Trace(trace_events_); + visitor->Trace(page_agents_); + visitor->Trace(network_agents_); + visitor->Trace(layer_tree_agents_); + visitor->Trace(tracing_agents_); + visitor->Trace(overlay_agents_); + visitor->Trace(sessions_); } void WebDevToolsAgentImpl::WillBeDestroyed() { DCHECK(web_local_frame_impl_->GetFrame()); DCHECK(inspected_frames_->Root()->View()); - probe_sink_->removeInspectorTraceEvents(trace_events_agent_); - trace_events_agent_ = nullptr; - if (session_) - Detach(session_->SessionId()); + probe_sink_->removeInspectorTraceEvents(trace_events_); + trace_events_ = nullptr; + + Vector<int> session_ids; + for (int session_id : sessions_.Keys()) + session_ids.push_back(session_id); + for (int session_id : session_ids) + Detach(session_id); + resource_content_loader_->Dispose(); client_ = nullptr; } -void WebDevToolsAgentImpl::InitializeSession(int session_id, - const String& host_id, - String* state) { +InspectorSession* WebDevToolsAgentImpl::InitializeSession(int session_id, + const String& host_id, + String* state) { DCHECK(client_); ClientMessageLoopAdapter::EnsureMainThreadDebuggerCreated(client_); MainThreadDebugger* main_thread_debugger = MainThreadDebugger::Instance(); v8::Isolate* isolate = V8PerIsolateData::MainThreadIsolate(); - session_ = new InspectorSession( + InspectorSession* session = new InspectorSession( this, probe_sink_.Get(), session_id, main_thread_debugger->GetV8Inspector(), main_thread_debugger->ContextGroupId(inspected_frames_->Root()), state); InspectorDOMAgent* dom_agent = new InspectorDOMAgent( - isolate, inspected_frames_.Get(), session_->V8Session()); - session_->Append(dom_agent); + isolate, inspected_frames_.Get(), session->V8Session()); + session->Append(dom_agent); InspectorLayerTreeAgent* layer_tree_agent = InspectorLayerTreeAgent::Create(inspected_frames_.Get()); - layer_tree_agent_ = layer_tree_agent; - session_->Append(layer_tree_agent); + layer_tree_agents_.Set(session_id, layer_tree_agent); + session->Append(layer_tree_agent); InspectorNetworkAgent* network_agent = InspectorNetworkAgent::Create(inspected_frames_.Get()); - network_agent_ = network_agent; - session_->Append(network_agent); + network_agents_.Set(session_id, network_agent); + session->Append(network_agent); InspectorCSSAgent* css_agent = InspectorCSSAgent::Create( - dom_agent, inspected_frames_.Get(), network_agent_, + dom_agent, inspected_frames_.Get(), network_agent, resource_content_loader_.Get(), resource_container_.Get()); - session_->Append(css_agent); + session->Append(css_agent); - session_->Append(new InspectorAnimationAgent( - inspected_frames_.Get(), css_agent, session_->V8Session())); + session->Append(new InspectorAnimationAgent(inspected_frames_.Get(), + css_agent, session->V8Session())); - session_->Append(InspectorMemoryAgent::Create()); + session->Append(InspectorMemoryAgent::Create()); - session_->Append( + session->Append( InspectorApplicationCacheAgent::Create(inspected_frames_.Get())); - session_->Append(new InspectorIndexedDBAgent(inspected_frames_.Get(), - session_->V8Session())); + session->Append(new InspectorIndexedDBAgent(inspected_frames_.Get(), + session->V8Session())); InspectorWorkerAgent* worker_agent = new InspectorWorkerAgent(inspected_frames_.Get()); - session_->Append(worker_agent); + session->Append(worker_agent); InspectorTracingAgent* tracing_agent = InspectorTracingAgent::Create( this, worker_agent, inspected_frames_.Get()); - tracing_agent_ = tracing_agent; - session_->Append(tracing_agent); + tracing_agents_.Set(session_id, tracing_agent); + session->Append(tracing_agent); - session_->Append( - new InspectorDOMDebuggerAgent(isolate, dom_agent, session_->V8Session())); + session->Append( + new InspectorDOMDebuggerAgent(isolate, dom_agent, session->V8Session())); - session_->Append(InspectorInputAgent::Create(inspected_frames_.Get())); + session->Append(InspectorInputAgent::Create(inspected_frames_.Get())); InspectorPageAgent* page_agent = InspectorPageAgent::Create( inspected_frames_.Get(), this, resource_content_loader_.Get(), - session_->V8Session()); - page_agent_ = page_agent; - session_->Append(page_agent); + session->V8Session()); + page_agents_.Set(session_id, page_agent); + session->Append(page_agent); - session_->Append(new InspectorLogAgent( + session->Append(new InspectorLogAgent( &inspected_frames_->Root()->GetPage()->GetConsoleMessageStorage(), inspected_frames_->Root()->GetPerformanceMonitor())); - session_->Append( - new DeviceOrientationInspectorAgent(inspected_frames_.Get())); + session->Append(new DeviceOrientationInspectorAgent(inspected_frames_.Get())); InspectorOverlayAgent* overlay_agent = new InspectorOverlayAgent(web_local_frame_impl_, inspected_frames_.Get(), - session_->V8Session(), dom_agent); - overlay_agent_ = overlay_agent; - session_->Append(overlay_agent); + session->V8Session(), dom_agent); + overlay_agents_.Set(session_id, overlay_agent); + session->Append(overlay_agent); - tracing_agent_->SetLayerTreeId(layer_tree_id_); - network_agent_->SetHostId(host_id); + tracing_agent->SetLayerTreeId(layer_tree_id_); + network_agent->SetHostId(host_id); if (include_view_agents_) { // TODO(dgozman): we should actually pass the view instead of frame, but // during remote->local transition we cannot access mainFrameImpl() yet, so // we have to store the frame which will become the main frame later. - session_->Append( + session->Append( InspectorEmulationAgent::Create(web_local_frame_impl_, this)); // TODO(dgozman): migrate each of the following agents to frame once module // is ready. Page* page = web_local_frame_impl_->ViewImpl()->GetPage(); - session_->Append(InspectorDatabaseAgent::Create(page)); - session_->Append(new InspectorAccessibilityAgent(page, dom_agent)); - session_->Append(InspectorDOMStorageAgent::Create(page)); - session_->Append(InspectorCacheStorageAgent::Create()); + session->Append(InspectorDatabaseAgent::Create(page)); + session->Append(new InspectorAccessibilityAgent(page, dom_agent)); + session->Append(InspectorDOMStorageAgent::Create(page)); + session->Append(InspectorCacheStorageAgent::Create()); } - Platform::Current()->CurrentThread()->AddTaskObserver(this); + if (!sessions_.size()) + Platform::Current()->CurrentThread()->AddTaskObserver(this); + + sessions_.Set(session_id, session); + return session; } -void WebDevToolsAgentImpl::DestroySession() { - overlay_agent_.Clear(); - tracing_agent_.Clear(); - layer_tree_agent_.Clear(); - network_agent_.Clear(); - page_agent_.Clear(); +void WebDevToolsAgentImpl::DestroySession(int session_id) { + overlay_agents_.erase(session_id); + tracing_agents_.erase(session_id); + layer_tree_agents_.erase(session_id); + network_agents_.erase(session_id); + page_agents_.erase(session_id); - session_->Dispose(); - session_.Clear(); + auto session_it = sessions_.find(session_id); + DCHECK(session_it != sessions_.end()); + session_it->value->Dispose(); + sessions_.erase(session_it); - Platform::Current()->CurrentThread()->RemoveTaskObserver(this); + if (!sessions_.size()) + Platform::Current()->CurrentThread()->RemoveTaskObserver(this); } void WebDevToolsAgentImpl::Attach(const WebString& host_id, int session_id) { - if (Attached()) + if (!session_id || sessions_.find(session_id) != sessions_.end()) return; InitializeSession(session_id, host_id, nullptr); } @@ -421,17 +427,17 @@ void WebDevToolsAgentImpl::Reattach(const WebString& host_id, int session_id, const WebString& saved_state) { - if (Attached()) + if (!session_id || sessions_.find(session_id) != sessions_.end()) return; String state = saved_state; - InitializeSession(session_id, host_id, &state); - session_->Restore(); + InspectorSession* session = InitializeSession(session_id, host_id, &state); + session->Restore(); } void WebDevToolsAgentImpl::Detach(int session_id) { - if (!Attached() || session_id != session_->SessionId()) + if (!session_id || sessions_.find(session_id) == sessions_.end()) return; - DestroySession(); + DestroySession(session_id); } void WebDevToolsAgentImpl::ContinueProgram() { @@ -441,39 +447,45 @@ void WebDevToolsAgentImpl::DidCommitLoadForLocalFrame(LocalFrame* frame) { resource_container_->DidCommitLoadForLocalFrame(frame); resource_content_loader_->DidCommitLoadForLocalFrame(frame); - if (session_) - session_->DidCommitLoadForLocalFrame(frame); + for (auto& it : sessions_) + it.value->DidCommitLoadForLocalFrame(frame); } void WebDevToolsAgentImpl::DidStartProvisionalLoad(LocalFrame* frame) { - if (session_ && inspected_frames_->Root() == frame) - session_->V8Session()->resume(); + if (inspected_frames_->Root() == frame) { + for (auto& it : sessions_) + it.value->V8Session()->resume(); + } } bool WebDevToolsAgentImpl::ScreencastEnabled() { - return page_agent_ && page_agent_->ScreencastEnabled(); + for (auto& it : page_agents_) { + if (it.value->ScreencastEnabled()) + return true; + } + return false; } void WebDevToolsAgentImpl::WillAddPageOverlay(const GraphicsLayer* layer) { - if (layer_tree_agent_) - layer_tree_agent_->WillAddPageOverlay(layer); + for (auto& it : layer_tree_agents_) + it.value->WillAddPageOverlay(layer); } void WebDevToolsAgentImpl::DidRemovePageOverlay(const GraphicsLayer* layer) { - if (layer_tree_agent_) - layer_tree_agent_->DidRemovePageOverlay(layer); + for (auto& it : layer_tree_agents_) + it.value->DidRemovePageOverlay(layer); } void WebDevToolsAgentImpl::RootLayerCleared() { - if (tracing_agent_) - tracing_agent_->RootLayerCleared(); + for (auto& it : tracing_agents_) + it.value->RootLayerCleared(); } void WebDevToolsAgentImpl::LayerTreeViewChanged( WebLayerTreeView* layer_tree_view) { layer_tree_id_ = layer_tree_view ? layer_tree_view->LayerTreeId() : 0; - if (tracing_agent_) - tracing_agent_->SetLayerTreeId(layer_tree_id_); + for (auto& it : tracing_agents_) + it.value->SetLayerTreeId(layer_tree_id_); } void WebDevToolsAgentImpl::EnableTracing(const String& category_filter) { @@ -487,13 +499,13 @@ } void WebDevToolsAgentImpl::ShowReloadingBlanket() { - if (overlay_agent_) - overlay_agent_->ShowReloadingBlanket(); + for (auto& it : overlay_agents_) + it.value->ShowReloadingBlanket(); } void WebDevToolsAgentImpl::HideReloadingBlanket() { - if (overlay_agent_) - overlay_agent_->HideReloadingBlanket(); + for (auto& it : overlay_agents_) + it.value->HideReloadingBlanket(); } void WebDevToolsAgentImpl::SetCPUThrottlingRate(double rate) { @@ -517,17 +529,23 @@ void WebDevToolsAgentImpl::DispatchMessageFromFrontend(int session_id, const String& method, const String& message) { - if (!Attached() || session_id != session_->SessionId()) + if (!session_id) + return; + auto session_it = sessions_.find(session_id); + if (session_it == sessions_.end()) return; InspectorTaskRunner::IgnoreInterruptsScope scope( MainThreadDebugger::Instance()->TaskRunner()); - session_->DispatchProtocolMessage(method, message); + session_it->value->DispatchProtocolMessage(method, message); } void WebDevToolsAgentImpl::InspectElementAt( int session_id, const WebPoint& point_in_root_frame) { - if (!overlay_agent_ || !session_ || session_->SessionId() != session_id) + if (!session_id) + return; + auto agent_it = overlay_agents_.find(session_id); + if (agent_it == overlay_agents_.end()) return; HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kMove | HitTestRequest::kReadOnly | @@ -547,7 +565,7 @@ Node* node = result.InnerNode(); if (!node && web_local_frame_impl_->GetFrame()->GetDocument()) node = web_local_frame_impl_->GetFrame()->GetDocument()->documentElement(); - overlay_agent_->Inspect(node); + agent_it->value->Inspect(node); } void WebDevToolsAgentImpl::FailedToRequestDevTools() { @@ -564,8 +582,8 @@ } void WebDevToolsAgentImpl::PageLayoutInvalidated(bool resized) { - if (overlay_agent_) - overlay_agent_->PageLayoutInvalidated(resized); + for (auto& it : overlay_agents_) + it.value->PageLayoutInvalidated(resized); } void WebDevToolsAgentImpl::WaitForCreateWindow(LocalFrame* frame) { @@ -578,37 +596,41 @@ WebString WebDevToolsAgentImpl::EvaluateInWebInspectorOverlay( const WebString& script) { - if (!overlay_agent_) - return WebString(); - - return overlay_agent_->EvaluateInOverlayForTest(script); + WebString result; + for (auto& it : overlay_agents_) + result = it.value->EvaluateInOverlayForTest(script); + return result; } void WebDevToolsAgentImpl::PaintOverlay() { - if (overlay_agent_) - overlay_agent_->PaintOverlay(); + for (auto& it : overlay_agents_) + it.value->PaintOverlay(); } void WebDevToolsAgentImpl::LayoutOverlay() { - if (overlay_agent_) - overlay_agent_->LayoutOverlay(); + for (auto& it : overlay_agents_) + it.value->LayoutOverlay(); } bool WebDevToolsAgentImpl::HandleInputEvent(const WebInputEvent& event) { - if (overlay_agent_) - return overlay_agent_->HandleInputEvent(event); + for (auto& it : overlay_agents_) { + if (it.value->HandleInputEvent(event)) + return true; + } return false; } bool WebDevToolsAgentImpl::CacheDisabled() { - if (!network_agent_) - return false; - return network_agent_->CacheDisabled(); + for (auto& it : network_agents_) { + if (it.value->CacheDisabled()) + return true; + } + return false; } void WebDevToolsAgentImpl::FlushProtocolNotifications() { - if (session_) - session_->flushProtocolNotifications(); + for (auto& it : sessions_) + it.value->flushProtocolNotifications(); } void WebDevToolsAgentImpl::WillProcessTask() {
diff --git a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h index 3d04b7b..5cb35e1 100644 --- a/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h +++ b/third_party/WebKit/Source/web/WebDevToolsAgentImpl.h
@@ -132,8 +132,10 @@ void WillProcessTask() override; void DidProcessTask() override; - void InitializeSession(int session_id, const String& host_id, String* state); - void DestroySession(); + InspectorSession* InitializeSession(int session_id, + const String& host_id, + String* state); + void DestroySession(int session_id); void DispatchMessageFromFrontend(int session_id, const String& method, const String& message); @@ -143,7 +145,7 @@ int session_id, std::unique_ptr<WebDevToolsAgent::MessageDescriptor>); - bool Attached() const { return session_.Get(); } + bool Attached() const { return !!sessions_.size(); } WebDevToolsAgentClient* client_; Member<WebLocalFrameBase> web_local_frame_impl_; @@ -152,15 +154,15 @@ Member<InspectorResourceContentLoader> resource_content_loader_; Member<InspectedFrames> inspected_frames_; Member<InspectorResourceContainer> resource_container_; + Member<InspectorTraceEvents> trace_events_; - Member<InspectorPageAgent> page_agent_; - Member<InspectorNetworkAgent> network_agent_; - Member<InspectorLayerTreeAgent> layer_tree_agent_; - Member<InspectorTracingAgent> tracing_agent_; - Member<InspectorTraceEvents> trace_events_agent_; - Member<InspectorOverlayAgent> overlay_agent_; + HeapHashMap<int, Member<InspectorPageAgent>> page_agents_; + HeapHashMap<int, Member<InspectorNetworkAgent>> network_agents_; + HeapHashMap<int, Member<InspectorLayerTreeAgent>> layer_tree_agents_; + HeapHashMap<int, Member<InspectorTracingAgent>> tracing_agents_; + HeapHashMap<int, Member<InspectorOverlayAgent>> overlay_agents_; - Member<InspectorSession> session_; + HeapHashMap<int, Member<InspectorSession>> sessions_; bool include_view_agents_; int layer_tree_id_; };
diff --git a/tools/determinism/deterministic_build_whitelist.pyl b/tools/determinism/deterministic_build_whitelist.pyl index 5721b9d..c9c4472 100644 --- a/tools/determinism/deterministic_build_whitelist.pyl +++ b/tools/determinism/deterministic_build_whitelist.pyl
@@ -119,7 +119,6 @@ 'message_center_unittests', 'midi_unittests', 'mojo_common_unittests', - 'mojo_js_integration_tests', 'mojo_js_unittests', 'mojo_public_bindings_unittests', 'mojo_public_system_unittests', @@ -276,7 +275,6 @@ 'midi_unittests.exe', 'mini_installer.exe', 'mksnapshot.exe', - 'mojo_js_integration_tests.exe', 'mojo_js_unittests.exe', 'mojo_message_pipe_perftests.exe', 'mojo_public_bindings_perftests.exe',
diff --git a/tools/gritsettings/resource_ids b/tools/gritsettings/resource_ids index 25abc65..090fabd 100644 --- a/tools/gritsettings/resource_ids +++ b/tools/gritsettings/resource_ids
@@ -100,9 +100,6 @@ "includes": [11940], "structures": [11950], }, - "chrome/browser/resources/options_test_resources.grd": { - "structures": [12000], - }, "chrome/browser/resources/password_manager_internals_resources.grd": { "includes": [12010], },
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index a246254..7dd1f1d 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -10799,6 +10799,13 @@ </description> </action> +<action name="MobileWebsiteSettingsOpenedFromVR"> + <owner>ymalik@chromium.org</owner> + <description> + Page Info opened via the toolbar page info (i.e. https lock) icon in VR. + </description> +</action> + <action name="MostVisited0"> <obsolete>No longer recorded.</obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a98b41e..67e489f 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -37224,6 +37224,7 @@ <enum name="VRUnsupportedMode" type="int"> <int value="0" label="Unhandled code point in URL"/> <int value="1" label="Could not elide URL"/> + <int value="2" label="Unhandled PageInfo"/> </enum> <enum name="VRViewerType" type="int">
diff --git a/ui/events/devices/mojo/BUILD.gn b/ui/events/devices/mojo/BUILD.gn index cfdbf86..fe65d7d1 100644 --- a/ui/events/devices/mojo/BUILD.gn +++ b/ui/events/devices/mojo/BUILD.gn
@@ -22,7 +22,4 @@ public_deps = [ ":mojo", ] - - # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. - use_once_callback = false }
diff --git a/ui/events/devices/mojo/device_struct_traits_unittest.cc b/ui/events/devices/mojo/device_struct_traits_unittest.cc index 04ed725..c47a52f1 100644 --- a/ui/events/devices/mojo/device_struct_traits_unittest.cc +++ b/ui/events/devices/mojo/device_struct_traits_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "base/files/file_path.h" #include "base/message_loop/message_loop.h" #include "mojo/public/cpp/bindings/binding_set.h" @@ -28,14 +30,13 @@ private: // mojom::DeviceStructTraitsTest: void EchoInputDevice(const InputDevice& in, - const EchoInputDeviceCallback& callback) override { - callback.Run(in); + EchoInputDeviceCallback callback) override { + std::move(callback).Run(in); } - void EchoTouchscreenDevice( - const TouchscreenDevice& in, - const EchoTouchscreenDeviceCallback& callback) override { - callback.Run(in); + void EchoTouchscreenDevice(const TouchscreenDevice& in, + EchoTouchscreenDeviceCallback callback) override { + std::move(callback).Run(in); } base::MessageLoop loop_; // A MessageLoop is needed for mojo IPC to work.
diff --git a/ui/events/mojo/BUILD.gn b/ui/events/mojo/BUILD.gn index 3015a85d..34b89eb 100644 --- a/ui/events/mojo/BUILD.gn +++ b/ui/events/mojo/BUILD.gn
@@ -26,7 +26,4 @@ public_deps = [ ":interfaces", ] - - # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. - use_once_callback = false }
diff --git a/ui/events/mojo/struct_traits_unittest.cc b/ui/events/mojo/struct_traits_unittest.cc index 3ec4376..48a3654 100644 --- a/ui/events/mojo/struct_traits_unittest.cc +++ b/ui/events/mojo/struct_traits_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "base/message_loop/message_loop.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,8 +30,8 @@ private: // TraitsTestService: void EchoEvent(std::unique_ptr<ui::Event> e, - const EchoEventCallback& callback) override { - callback.Run(std::move(e)); + EchoEventCallback callback) override { + std::move(callback).Run(std::move(e)); } base::MessageLoop loop_;
diff --git a/ui/latency/mojo/BUILD.gn b/ui/latency/mojo/BUILD.gn index dc8f800..0840e693 100644 --- a/ui/latency/mojo/BUILD.gn +++ b/ui/latency/mojo/BUILD.gn
@@ -24,7 +24,4 @@ public_deps = [ ":interfaces", ] - - # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. - use_once_callback = false }
diff --git a/ui/latency/mojo/struct_traits_unittest.cc b/ui/latency/mojo/struct_traits_unittest.cc index 3efa55f0..31a063d2 100644 --- a/ui/latency/mojo/struct_traits_unittest.cc +++ b/ui/latency/mojo/struct_traits_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "base/message_loop/message_loop.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,21 +25,20 @@ private: // TraitsTestService: - void EchoLatencyComponent( - const LatencyInfo::LatencyComponent& l, - const EchoLatencyComponentCallback& callback) override { - callback.Run(l); + void EchoLatencyComponent(const LatencyInfo::LatencyComponent& l, + EchoLatencyComponentCallback callback) override { + std::move(callback).Run(l); } void EchoLatencyComponentId( const std::pair<LatencyComponentType, int64_t>& id, - const EchoLatencyComponentIdCallback& callback) override { - callback.Run(id); + EchoLatencyComponentIdCallback callback) override { + std::move(callback).Run(id); } void EchoLatencyInfo(const LatencyInfo& info, - const EchoLatencyInfoCallback& callback) override { - callback.Run(info); + EchoLatencyInfoCallback callback) override { + std::move(callback).Run(info); } base::MessageLoop loop_;
diff --git a/ui/message_center/mojo/BUILD.gn b/ui/message_center/mojo/BUILD.gn index 6bdef07..a19b11a 100644 --- a/ui/message_center/mojo/BUILD.gn +++ b/ui/message_center/mojo/BUILD.gn
@@ -25,9 +25,6 @@ public_deps = [ ":mojo", ] - - # TODO(crbug.com/714018): Convert the implementation to use OnceCallback. - use_once_callback = false } source_set("struct_traits") {
diff --git a/ui/message_center/mojo/struct_traits_unittest.cc b/ui/message_center/mojo/struct_traits_unittest.cc index 9e39789..c86745d 100644 --- a/ui/message_center/mojo/struct_traits_unittest.cc +++ b/ui/message_center/mojo/struct_traits_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <utility> + #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "mojo/public/cpp/bindings/binding_set.h" @@ -36,8 +38,8 @@ private: // TraitsTestService: void EchoNotification(const Notification& n, - const EchoNotificationCallback& callback) override { - callback.Run(n); + EchoNotificationCallback callback) override { + std::move(callback).Run(n); } base::MessageLoop loop_;