Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / components / autofill / ios / browser / js_suggestion_manager.mm
blob829df6952a7232dfc4128671a591bd20b5de5894
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "components/autofill/ios/browser/js_suggestion_manager.h"
7 #include "base/format_macros.h"
8 #include "base/json/string_escape.h"
9 #include "base/logging.h"
10 #include "base/strings/sys_string_conversions.h"
12 namespace {
13 // Santizies |str| and wraps it in quotes so it can be injected safely in
14 // JavaScript.
15 NSString* JSONEscape(NSString* str) {
16   return base::SysUTF8ToNSString(
17       base::GetQuotedJSONString(base::SysNSStringToUTF8(str)));
19 }  // namespace
21 @implementation JsSuggestionManager
23 #pragma mark -
24 #pragma mark ProtectedMethods
26 - (NSString*)scriptPath {
27   return @"suggestion_controller";
30 - (NSString*)presenceBeacon {
31   return @"__gCrWeb.suggestion";
34 - (void)selectNextElement {
35   [self selectElementAfterForm:@"" field:@""];
38 - (void)selectElementAfterForm:(NSString*)formName field:(NSString*)fieldName {
39   NSString* selectNextElementJS = [NSString
40       stringWithFormat:@"__gCrWeb.suggestion.selectNextElement(%@, %@)",
41                        JSONEscape(formName), JSONEscape(fieldName)];
42   [self evaluate:selectNextElementJS stringResultHandler:nil];
45 - (void)selectPreviousElement {
46   [self selectElementBeforeForm:@"" field:@""];
49 - (void)selectElementBeforeForm:(NSString*)formName field:(NSString*)fieldName {
50   NSString* selectPreviousElementJS = [NSString
51       stringWithFormat:@"__gCrWeb.suggestion.selectPreviousElement(%@, %@)",
52                        JSONEscape(formName), JSONEscape(fieldName)];
53   [self evaluate:selectPreviousElementJS stringResultHandler:nil];
56 - (void)fetchPreviousAndNextElementsPresenceWithCompletionHandler:
57         (void (^)(BOOL, BOOL))completionHandler {
58   [self fetchPreviousAndNextElementsPresenceForForm:@""
59                                               field:@""
60                                   completionHandler:completionHandler];
63 - (void)fetchPreviousAndNextElementsPresenceForForm:(NSString*)formName
64                                               field:(NSString*)fieldName
65                                   completionHandler:
66                                       (void (^)(BOOL, BOOL))completionHandler {
67   DCHECK(completionHandler);
68   DCHECK([self hasBeenInjected]);
69   id stringResultHandler = ^(NSString* result, NSError* error) {
70     // The result maybe an empty string here due to 2 reasons:
71     // 1) When there is an exception running the JS
72     // 2) There is a race when the page is changing due to which
73     // JSSuggestionManager has not yet injected __gCrWeb.suggestion object
74     // Handle this case gracefully.
75     // TODO(shreyasv): Figure out / narrow down further why this occurs.
76     // crbug.com/432217.
77     // If a page has overridden Array.toString, the string returned may not
78     // contain a ",", hence this is a defensive measure to early return.
79     NSArray* components = [result componentsSeparatedByString:@","];
80     if (components.count != 2) {
81       completionHandler(NO, NO);
82       return;
83     }
85     DCHECK([components[0] isEqualToString:@"true"] ||
86            [components[0] isEqualToString:@"false"]);
87     BOOL hasPreviousElement = [components[0] isEqualToString:@"true"];
88     DCHECK([components[1] isEqualToString:@"true"] ||
89            [components[1] isEqualToString:@"false"]);
90     BOOL hasNextElement = [components[1] isEqualToString:@"true"];
91     completionHandler(hasPreviousElement, hasNextElement);
92   };
93   NSString* escapedFormName = JSONEscape(formName);
94   NSString* escapedFieldName = JSONEscape(fieldName);
95   NSString* js = [NSString
96       stringWithFormat:@"[__gCrWeb.suggestion.hasPreviousElement(%@, %@),"
97                        @"__gCrWeb.suggestion.hasNextElement(%@, %@)]"
98                        @".toString()",
99                        escapedFormName, escapedFieldName, escapedFormName,
100                        escapedFieldName];
101   [self evaluate:js stringResultHandler:stringResultHandler];
104 - (void)closeKeyboard {
105   // Deferred execution used because of a risk of crwebinvoke:// triggered
106   // immediately by the loss of focus.
107   [self deferredEvaluate:@"document.activeElement.blur()"];
110 @end