File: external_protocol_dialog.mm

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (137 lines) | stat: -rw-r--r-- 4,653 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// 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.

#import "chrome/browser/ui/cocoa/external_protocol_dialog.h"

#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram_macros.h"
#include "chrome/browser/external_protocol/external_protocol_handler.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/shell_integration.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/grit/chromium_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/gfx/text_elider.h"

///////////////////////////////////////////////////////////////////////////////
// ExternalProtocolHandler

// static
void ExternalProtocolHandler::RunExternalProtocolDialog(
    const GURL& url, int render_process_host_id, int routing_id,
    ui::PageTransition page_transition, bool has_user_gesture) {
  [[ExternalProtocolDialogController alloc] initWithGURL:&url
                                     renderProcessHostId:render_process_host_id
                                               routingId:routing_id];
}

///////////////////////////////////////////////////////////////////////////////
// ExternalProtocolDialogController

@interface ExternalProtocolDialogController(Private)
- (void)alertEnded:(NSAlert *)alert
        returnCode:(int)returnCode
       contextInfo:(void*)contextInfo;
@end

@implementation ExternalProtocolDialogController
- (id)initWithGURL:(const GURL*)url
    renderProcessHostId:(int)renderProcessHostId
    routingId:(int)routingId {
  DCHECK(base::MessageLoopForUI::IsCurrent());

  if (!(self = [super init]))
    return nil;

  url_ = *url;
  render_process_host_id_ = renderProcessHostId;
  routing_id_ = routingId;
  creation_time_ = base::Time::Now();

  base::string16 appName =
      shell_integration::GetApplicationNameForProtocol(url_);
  if (appName.length() == 0) {
    // No registered apps for this protocol; give up and go home.
    [self autorelease];
    return nil;
  }

  alert_ = [[NSAlert alloc] init];

  [alert_ setMessageText:
      l10n_util::GetNSStringFWithFixup(IDS_EXTERNAL_PROTOCOL_TITLE, appName)];

  NSButton* allowButton = [alert_
      addButtonWithTitle:l10n_util::GetNSStringFWithFixup(
                   IDS_EXTERNAL_PROTOCOL_OK_BUTTON_TEXT, appName)];
  [allowButton setKeyEquivalent:@""];  // disallow as default
  [alert_ addButtonWithTitle:
      l10n_util::GetNSStringWithFixup(
                   IDS_EXTERNAL_PROTOCOL_CANCEL_BUTTON_TEXT)];

  [alert_ setShowsSuppressionButton:YES];
  [[alert_ suppressionButton]
      setTitle:l10n_util::GetNSStringFWithFixup(
                   IDS_EXTERNAL_PROTOCOL_CHECKBOX_TEXT, appName)];

  [alert_ beginSheetModalForWindow:nil  // nil here makes it app-modal
                     modalDelegate:self
                    didEndSelector:@selector(alertEnded:returnCode:contextInfo:)
                       contextInfo:nil];

  return self;
}

- (void)dealloc {
  [alert_ release];

  [super dealloc];
}

- (void)alertEnded:(NSAlert *)alert
        returnCode:(int)returnCode
       contextInfo:(void*)contextInfo {
  ExternalProtocolHandler::BlockState blockState =
      ExternalProtocolHandler::UNKNOWN;
  switch (returnCode) {
    case NSAlertFirstButtonReturn:
      blockState = ExternalProtocolHandler::DONT_BLOCK;
      break;
    case NSAlertSecondButtonReturn:
      blockState = ExternalProtocolHandler::BLOCK;
      break;
    default:
      NOTREACHED();
  }

  content::WebContents* web_contents =
      tab_util::GetWebContentsByID(render_process_host_id_, routing_id_);

  if (web_contents) {
    Profile* profile =
        Profile::FromBrowserContext(web_contents->GetBrowserContext());
    bool isChecked = [[alert_ suppressionButton] state] == NSOnState;
    // Set the "don't warn me again" info.
    if (isChecked)
      ExternalProtocolHandler::SetBlockState(url_.scheme(), blockState,
                                             profile);

    ExternalProtocolHandler::RecordCheckboxStateMetrics(isChecked);
    ExternalProtocolHandler::RecordHandleStateMetrics(isChecked, blockState);

    if (blockState == ExternalProtocolHandler::DONT_BLOCK) {
      UMA_HISTOGRAM_LONG_TIMES("clickjacking.launch_url",
                               base::Time::Now() - creation_time_);

      ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(url_,
                                                             web_contents);
    }
  }

  [self autorelease];
}

@end