雑記

ものを書く練習。学びをまとめる場。

Chromiumを手探る 3

この記事は前回からの連載(?)です。よろしければそちらから。

タブがシークレットモードで開かなかった原因

前回設定した関数 NewEmptyTab() の中で

void NewEmptyTab(Browser* browser, Profile* profile){
  // incognitoとbrowser->profile()を一致させる?
  bool incognito = profile->IsOffTheRecord();
  PrefService* prefs = profile->GetPrefs();
  if (incognito) {
    if (IncognitoModePrefs::GetAvailability(prefs) ==
          IncognitoModePrefs::DISABLED) {
      incognito = false;
    }
  } else if (profile->IsGuestSession() ||
             (browser_defaults::kAlwaysOpenIncognitoWindow &&
              IncognitoModePrefs::ShouldLaunchIncognito(
                  *base::CommandLine::ForCurrentProcess(), prefs))) {
    incognito = true;
  }

つまり、おそらく
NewIncognitoTab() が呼ばれる
 ↓
profile->IsOffTheRecord() なので incognito = true になる
 ↓
IncognitoModePrefs::GetAvailability(prefs) == IncognitoModePrefs::DISABLED なので incognito = false になってしまう
 ↓
普通のタブが開く
という挙動になってしまったのが原因だと考えました。

てかわざわざこんなことしなくても SetProfile() って関数作って NewTab() と NewIncognitoTab() の中で profile をセットすればいいだけじゃね?と思ってしまいました。実はこれは相方のアイデアなのですが、潔く丸パクリすることにしました。決断力。

改装

NewTab() と NewIncognitoTab() は以下のようにコードを変えました。(大事だと思ったので丸々載せますが基本元のNewTab()と構成は一緒です)

void NewTab(Browser* browser) {
  base::RecordAction(UserMetricsAction("NewTab"));
  // TODO(asvitkine): This is invoked programmatically from several places.
  // Audit the code and change it so that the histogram only gets collected for
  // user-initiated commands.
  UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
                            TabStripModel::NEW_TAB_ENUM_COUNT);
    
  browser->SetProfile(browser->profile()->GetOriginalProfile());

  if (browser->is_type_tabbed()) {
    AddTabAt(browser, GURL(), -1, true);
    browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  } else {
    ScopedTabbedBrowserDisplayer displayer(browser->profile());
    Browser* b = displayer.browser();
    AddTabAt(b, GURL(), -1, true);
    b->window()->Show();
    // The call to AddBlankTabAt above did not set the focus to the tab as its
    // window was not active, so we have to do it explicitly.
    // See http://crbug.com/6380.
    b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  }
}
    
void NewIncognitoTab(Browser* browser) {
    base::RecordAction(UserMetricsAction("NewTab"));
    // TODO(asvitkine): This is invoked programmatically from several places.
    // Audit the code and change it so that the histogram only gets collected for
    // user-initiated commands.
    UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
                                TabStripModel::NEW_TAB_ENUM_COUNT);
    
    browser->SetProfile(browser->profile()->GetOffTheRecordProfile());
    
    if (browser->is_type_tabbed()) {
        AddTabAt(browser, GURL(), -1, true);
        browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
    } else {
        ScopedTabbedBrowserDisplayer displayer(browser->profile());
        Browser* b = displayer.browser();
        AddTabAt(b, GURL(), -1, true);
        b->window()->Show();
        // The call to AddBlankTabAt above did not set the focus to the tab as its
        // window was not active, so we have to do it explicitly.
        // See http://crbug.com/6380.
        b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
    }
}

そして browser.h には

class Browser : public TabStripModelObserver,
                  ・・・
{
  public : 
  ・・・
   // Accessors ////////////////////////////////////////////////////////////////
  ・・・
  void SetProfile(Profile* profile) { profile_ = profile; }
  ・・・
}

さらに、タブによってprofileを変えるために browser.h 内の Profile* const profile_; から const を削除して Profile* profile_; にしました。

また、よくよくみていくと tab_activity_watcher.cc にて

namespace resource_coordinator {
class TabActivityWatcher::WebContentsData
    : public content::WebContentsObserver,
      public content::WebContentsUserData<WebContentsData>,
      public content::RenderWidgetHost::InputEventObserver {
  ・・・
  private :
    explicit WebContentsData(content::WebContents* web_contents)
      : WebContentsObserver(web_contents) {
    DCHECK(!web_contents->GetBrowserContext()->IsOffTheRecord());
    tab_metrics_.web_contents = web_contents;
    web_contents->GetRenderViewHost()->GetWidget()->AddInputEventObserver(this);
    ・・・
  }
  ・・・
}
}

と DCHECK で OffTheRecord() のチェックが入ってしまっているので、この一行を削除しました。

結果

f:id:RHys:20181022181753p:plainf:id:RHys:20181022181759p:plain

画像ではわかりにくいですが無事実装できました!!

やっぱりひとまずとはいえ完成すると嬉しいですね!w

課題

f:id:RHys:20181022182029p:plain

実は先ほどの画像の状態で、もう一度元のタブに戻った時の画像がこちらなのですが、なんか変ですよね...?

おそらくこのタブを開いた時は browser->profile() が GetOriginalProfile() だったのに、新しいシークレットタブを開いたせいで profile が GetOffTheRecordProfile() になってしまっているせいで、なんらかのコンフリクトが生じてしまっています。

この画像のタブで検索をしてみても新しいタブが開かれてしまうんですよね...

選択するタブを切り替える時の動作を追うことができればそこでまた profile を変更するようにすれば良いと思うのですが、残念ながら講義時間中ではそこまで追いきれませんでした。1

後は見てお気づきかとは思いますが GUI やショートカットキーの割り当てですね。画像ではショートカットキーが割り当てられているような雰囲気を醸していますがこれはハリボテで押しても何も反応しませんw

相方は Linux で行なっていたのでキーの割り当てが比較的簡単にできていそうでしたが、macOS は何か特殊らしくよくわからなかったですね。時間を見つけてまた取り組みたいところです。

感想

さて、初めてこんな複雑なプログラムに触れて見ましたが、意外とたのしかったです。なんというか、これを趣味にするのもわかる気がする。。。

自分はプログラミング完全初心者2で、特に c++java なんかは見たこともほとんどないレベルだったのですが、まあやっていくうちになんとなく読めてなんとなーく書けるようになっていきました。

なので初心者の方々も気軽に触ってみてはいかがでしょうか。


次回以降の演習で chromium を手探る方は無理ない程度に無理して頑張ってください!


  1. はじめにも記載しましたが大学の実習の一環として取り組んでいます。詳細はこちら

  2. 実は去年の必修のプログラミングの単位も落としています。ほんとうにつらい